Deleted Added
sdiff udiff text old ( 266648 ) new ( 277042 )
full compact
1/*-
2 * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/arm/ti/am335x/am335x_prcm.c 266648 2014-05-25 10:49:07Z andrew $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/bus.h>
33#include <sys/kernel.h>
34#include <sys/module.h>
35#include <sys/malloc.h>
36#include <sys/rman.h>
37#include <sys/timeet.h>
38#include <sys/timetc.h>
39#include <sys/watchdog.h>
40#include <machine/bus.h>
41#include <machine/cpu.h>
42#include <machine/intr.h>
43
44#include <arm/ti/tivar.h>
45#include <arm/ti/ti_scm.h>
46#include <arm/ti/ti_prcm.h>
47
48#include <dev/fdt/fdt_common.h>
49#include <dev/ofw/openfirm.h>
50#include <dev/ofw/ofw_bus.h>
51#include <dev/ofw/ofw_bus_subr.h>
52
53#include <machine/bus.h>
54#include <machine/fdt.h>
55
56#define CM_PER 0
57#define CM_PER_L4LS_CLKSTCTRL (CM_PER + 0x000)
58#define CM_PER_L3S_CLKSTCTRL (CM_PER + 0x004)
59#define CM_PER_L3_CLKSTCTRL (CM_PER + 0x00C)
60#define CM_PER_CPGMAC0_CLKCTRL (CM_PER + 0x014)
61#define CM_PER_LCDC_CLKCTRL (CM_PER + 0x018)
62#define CM_PER_USB0_CLKCTRL (CM_PER + 0x01C)
63#define CM_PER_TPTC0_CLKCTRL (CM_PER + 0x024)
64#define CM_PER_UART5_CLKCTRL (CM_PER + 0x038)
65#define CM_PER_MMC0_CLKCTRL (CM_PER + 0x03C)
66#define CM_PER_I2C2_CLKCTRL (CM_PER + 0x044)
67#define CM_PER_I2C1_CLKCTRL (CM_PER + 0x048)
68#define CM_PER_UART1_CLKCTRL (CM_PER + 0x06C)
69#define CM_PER_UART2_CLKCTRL (CM_PER + 0x070)
70#define CM_PER_UART3_CLKCTRL (CM_PER + 0x074)
71#define CM_PER_UART4_CLKCTRL (CM_PER + 0x078)
72#define CM_PER_TIMER7_CLKCTRL (CM_PER + 0x07C)
73#define CM_PER_TIMER2_CLKCTRL (CM_PER + 0x080)
74#define CM_PER_TIMER3_CLKCTRL (CM_PER + 0x084)
75#define CM_PER_TIMER4_CLKCTRL (CM_PER + 0x088)
76#define CM_PER_GPIO1_CLKCTRL (CM_PER + 0x0AC)
77#define CM_PER_GPIO2_CLKCTRL (CM_PER + 0x0B0)
78#define CM_PER_GPIO3_CLKCTRL (CM_PER + 0x0B4)
79#define CM_PER_TPCC_CLKCTRL (CM_PER + 0x0BC)
80#define CM_PER_EPWMSS1_CLKCTRL (CM_PER + 0x0CC)
81#define CM_PER_EPWMSS0_CLKCTRL (CM_PER + 0x0D4)
82#define CM_PER_EPWMSS2_CLKCTRL (CM_PER + 0x0D8)
83#define CM_PER_L3_INSTR_CLKCTRL (CM_PER + 0x0DC)
84#define CM_PER_L3_CLKCTRL (CM_PER + 0x0E0)
85#define CM_PER_PRUSS_CLKCTRL (CM_PER + 0x0E8)
86#define CM_PER_TIMER5_CLKCTRL (CM_PER + 0x0EC)
87#define CM_PER_TIMER6_CLKCTRL (CM_PER + 0x0F0)
88#define CM_PER_MMC1_CLKCTRL (CM_PER + 0x0F4)
89#define CM_PER_MMC2_CLKCTRL (CM_PER + 0x0F8)
90#define CM_PER_TPTC1_CLKCTRL (CM_PER + 0x0FC)
91#define CM_PER_TPTC2_CLKCTRL (CM_PER + 0x100)
92#define CM_PER_SPINLOCK0_CLKCTRL (CM_PER + 0x10C)
93#define CM_PER_MAILBOX0_CLKCTRL (CM_PER + 0x110)
94#define CM_PER_OCPWP_L3_CLKSTCTRL (CM_PER + 0x12C)
95#define CM_PER_OCPWP_CLKCTRL (CM_PER + 0x130)
96#define CM_PER_CPSW_CLKSTCTRL (CM_PER + 0x144)
97#define CM_PER_PRUSS_CLKSTCTRL (CM_PER + 0x140)
98
99#define CM_WKUP 0x400
100#define CM_WKUP_CLKSTCTRL (CM_WKUP + 0x000)
101#define CM_WKUP_CONTROL_CLKCTRL (CM_WKUP + 0x004)
102#define CM_WKUP_GPIO0_CLKCTRL (CM_WKUP + 0x008)
103#define CM_WKUP_CM_L3_AON_CLKSTCTRL (CM_WKUP + 0x01C)
104#define CM_WKUP_CM_CLKSEL_DPLL_MPU (CM_WKUP + 0x02C)
105#define CM_WKUP_CM_IDLEST_DPLL_DISP (CM_WKUP + 0x048)
106#define CM_WKUP_CM_CLKSEL_DPLL_DISP (CM_WKUP + 0x054)
107#define CM_WKUP_CM_CLKDCOLDO_DPLL_PER (CM_WKUP + 0x07C)
108#define CM_WKUP_CM_CLKMODE_DPLL_DISP (CM_WKUP + 0x098)
109#define CM_WKUP_I2C0_CLKCTRL (CM_WKUP + 0x0B8)
110#define CM_WKUP_ADC_TSC_CLKCTRL (CM_WKUP + 0x0BC)
111
112#define CM_DPLL 0x500
113#define CLKSEL_TIMER7_CLK (CM_DPLL + 0x004)
114#define CLKSEL_TIMER2_CLK (CM_DPLL + 0x008)
115#define CLKSEL_TIMER3_CLK (CM_DPLL + 0x00C)
116#define CLKSEL_TIMER4_CLK (CM_DPLL + 0x010)
117#define CLKSEL_TIMER5_CLK (CM_DPLL + 0x018)
118#define CLKSEL_TIMER6_CLK (CM_DPLL + 0x01C)
119#define CLKSEL_PRUSS_OCP_CLK (CM_DPLL + 0x030)
120
121#define PRM_PER 0xC00
122#define PRM_PER_RSTCTRL (PRM_PER + 0x00)
123
124#define PRM_DEVICE_OFFSET 0xF00
125#define PRM_RSTCTRL (PRM_DEVICE_OFFSET + 0x00)
126
127struct am335x_prcm_softc {
128 struct resource * res[2];
129 bus_space_tag_t bst;
130 bus_space_handle_t bsh;
131};
132
133static struct resource_spec am335x_prcm_spec[] = {
134 { SYS_RES_MEMORY, 0, RF_ACTIVE },
135 { -1, 0 }
136};
137
138static struct am335x_prcm_softc *am335x_prcm_sc = NULL;
139
140static int am335x_clk_noop_activate(struct ti_clock_dev *clkdev);
141static int am335x_clk_generic_activate(struct ti_clock_dev *clkdev);
142static int am335x_clk_gpio_activate(struct ti_clock_dev *clkdev);
143static int am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev);
144static int am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev);
145static int am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
146static int am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
147static int am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
148static int am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
149static int am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
150static int am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
151static void am335x_prcm_reset(void);
152static int am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev);
153static int am335x_clk_musb0_activate(struct ti_clock_dev *clkdev);
154static int am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev);
155static int am335x_clk_pruss_activate(struct ti_clock_dev *clkdev);
156
157#define AM335X_NOOP_CLOCK_DEV(i) \
158 { .id = (i), \
159 .clk_activate = am335x_clk_noop_activate, \
160 .clk_deactivate = am335x_clk_noop_deactivate, \
161 .clk_set_source = am335x_clk_noop_set_source, \
162 .clk_accessible = NULL, \
163 .clk_get_source_freq = NULL \
164 }
165
166#define AM335X_GENERIC_CLOCK_DEV(i) \
167 { .id = (i), \
168 .clk_activate = am335x_clk_generic_activate, \
169 .clk_deactivate = am335x_clk_generic_deactivate, \
170 .clk_set_source = am335x_clk_generic_set_source, \
171 .clk_accessible = NULL, \
172 .clk_get_source_freq = NULL \
173 }
174
175#define AM335X_GPIO_CLOCK_DEV(i) \
176 { .id = (i), \
177 .clk_activate = am335x_clk_gpio_activate, \
178 .clk_deactivate = am335x_clk_generic_deactivate, \
179 .clk_set_source = am335x_clk_generic_set_source, \
180 .clk_accessible = NULL, \
181 .clk_get_source_freq = NULL \
182 }
183
184#define AM335X_MMCHS_CLOCK_DEV(i) \
185 { .id = (i), \
186 .clk_activate = am335x_clk_generic_activate, \
187 .clk_deactivate = am335x_clk_generic_deactivate, \
188 .clk_set_source = am335x_clk_generic_set_source, \
189 .clk_accessible = NULL, \
190 .clk_get_source_freq = am335x_clk_hsmmc_get_source_freq \
191 }
192
193struct ti_clock_dev ti_am335x_clk_devmap[] = {
194 /* System clocks */
195 { .id = SYS_CLK,
196 .clk_activate = NULL,
197 .clk_deactivate = NULL,
198 .clk_set_source = NULL,
199 .clk_accessible = NULL,
200 .clk_get_source_freq = am335x_clk_get_sysclk_freq,
201 },
202 /* MPU (ARM) core clocks */
203 { .id = MPU_CLK,
204 .clk_activate = NULL,
205 .clk_deactivate = NULL,
206 .clk_set_source = NULL,
207 .clk_accessible = NULL,
208 .clk_get_source_freq = am335x_clk_get_arm_fclk_freq,
209 },
210 /* CPSW Ethernet Switch core clocks */
211 { .id = CPSW_CLK,
212 .clk_activate = am335x_clk_cpsw_activate,
213 .clk_deactivate = NULL,
214 .clk_set_source = NULL,
215 .clk_accessible = NULL,
216 .clk_get_source_freq = NULL,
217 },
218
219 /* Mentor USB HS controller core clocks */
220 { .id = MUSB0_CLK,
221 .clk_activate = am335x_clk_musb0_activate,
222 .clk_deactivate = NULL,
223 .clk_set_source = NULL,
224 .clk_accessible = NULL,
225 .clk_get_source_freq = NULL,
226 },
227
228 /* LCD controller clocks */
229 { .id = LCDC_CLK,
230 .clk_activate = am335x_clk_lcdc_activate,
231 .clk_deactivate = NULL,
232 .clk_set_source = NULL,
233 .clk_accessible = NULL,
234 .clk_get_source_freq = am335x_clk_get_arm_disp_freq,
235 },
236
237 /* UART. Uart0 clock cannot be controlled. */
238 AM335X_NOOP_CLOCK_DEV(UART0_CLK),
239 AM335X_GENERIC_CLOCK_DEV(UART1_CLK),
240 AM335X_GENERIC_CLOCK_DEV(UART2_CLK),
241 AM335X_GENERIC_CLOCK_DEV(UART3_CLK),
242 AM335X_GENERIC_CLOCK_DEV(UART4_CLK),
243 AM335X_GENERIC_CLOCK_DEV(UART5_CLK),
244
245 /* DMTimer */
246 AM335X_GENERIC_CLOCK_DEV(DMTIMER2_CLK),
247 AM335X_GENERIC_CLOCK_DEV(DMTIMER3_CLK),
248 AM335X_GENERIC_CLOCK_DEV(DMTIMER4_CLK),
249 AM335X_GENERIC_CLOCK_DEV(DMTIMER5_CLK),
250 AM335X_GENERIC_CLOCK_DEV(DMTIMER6_CLK),
251 AM335X_GENERIC_CLOCK_DEV(DMTIMER7_CLK),
252
253 /* GPIO */
254 AM335X_GPIO_CLOCK_DEV(GPIO0_CLK),
255 AM335X_GPIO_CLOCK_DEV(GPIO1_CLK),
256 AM335X_GPIO_CLOCK_DEV(GPIO2_CLK),
257 AM335X_GPIO_CLOCK_DEV(GPIO3_CLK),
258
259 /* I2C */
260 AM335X_GENERIC_CLOCK_DEV(I2C0_CLK),
261 AM335X_GENERIC_CLOCK_DEV(I2C1_CLK),
262 AM335X_GENERIC_CLOCK_DEV(I2C2_CLK),
263
264 /* TSC_ADC */
265 AM335X_GENERIC_CLOCK_DEV(TSC_ADC_CLK),
266
267 /* EDMA */
268 AM335X_GENERIC_CLOCK_DEV(EDMA_TPCC_CLK),
269 AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC0_CLK),
270 AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC1_CLK),
271 AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC2_CLK),
272
273 /* MMCHS */
274 AM335X_MMCHS_CLOCK_DEV(MMC0_CLK),
275 AM335X_MMCHS_CLOCK_DEV(MMC1_CLK),
276 AM335X_MMCHS_CLOCK_DEV(MMC2_CLK),
277
278 /* PWMSS */
279 AM335X_GENERIC_CLOCK_DEV(PWMSS0_CLK),
280 AM335X_GENERIC_CLOCK_DEV(PWMSS1_CLK),
281 AM335X_GENERIC_CLOCK_DEV(PWMSS2_CLK),
282
283 /* System Mailbox clock */
284 AM335X_GENERIC_CLOCK_DEV(MAILBOX0_CLK),
285
286 /* SPINLOCK */
287 AM335X_GENERIC_CLOCK_DEV(SPINLOCK0_CLK),
288
289 /* PRU-ICSS */
290 { .id = PRUSS_CLK,
291 .clk_activate = am335x_clk_pruss_activate,
292 .clk_deactivate = NULL,
293 .clk_set_source = NULL,
294 .clk_accessible = NULL,
295 .clk_get_source_freq = NULL,
296 },
297
298
299
300 { INVALID_CLK_IDENT, NULL, NULL, NULL, NULL }
301};
302
303struct am335x_clk_details {
304 clk_ident_t id;
305 uint32_t clkctrl_reg;
306 uint32_t clksel_reg;
307};
308
309#define _CLK_DETAIL(i, c, s) \
310 { .id = (i), \
311 .clkctrl_reg = (c), \
312 .clksel_reg = (s), \
313 }
314
315static struct am335x_clk_details g_am335x_clk_details[] = {
316
317 /* UART. UART0 clock not controllable. */
318 _CLK_DETAIL(UART0_CLK, 0, 0),
319 _CLK_DETAIL(UART1_CLK, CM_PER_UART1_CLKCTRL, 0),
320 _CLK_DETAIL(UART2_CLK, CM_PER_UART2_CLKCTRL, 0),
321 _CLK_DETAIL(UART3_CLK, CM_PER_UART3_CLKCTRL, 0),
322 _CLK_DETAIL(UART4_CLK, CM_PER_UART4_CLKCTRL, 0),
323 _CLK_DETAIL(UART5_CLK, CM_PER_UART5_CLKCTRL, 0),
324
325 /* DMTimer modules */
326 _CLK_DETAIL(DMTIMER2_CLK, CM_PER_TIMER2_CLKCTRL, CLKSEL_TIMER2_CLK),
327 _CLK_DETAIL(DMTIMER3_CLK, CM_PER_TIMER3_CLKCTRL, CLKSEL_TIMER3_CLK),
328 _CLK_DETAIL(DMTIMER4_CLK, CM_PER_TIMER4_CLKCTRL, CLKSEL_TIMER4_CLK),
329 _CLK_DETAIL(DMTIMER5_CLK, CM_PER_TIMER5_CLKCTRL, CLKSEL_TIMER5_CLK),
330 _CLK_DETAIL(DMTIMER6_CLK, CM_PER_TIMER6_CLKCTRL, CLKSEL_TIMER6_CLK),
331 _CLK_DETAIL(DMTIMER7_CLK, CM_PER_TIMER7_CLKCTRL, CLKSEL_TIMER7_CLK),
332
333 /* GPIO modules */
334 _CLK_DETAIL(GPIO0_CLK, CM_WKUP_GPIO0_CLKCTRL, 0),
335 _CLK_DETAIL(GPIO1_CLK, CM_PER_GPIO1_CLKCTRL, 0),
336 _CLK_DETAIL(GPIO2_CLK, CM_PER_GPIO2_CLKCTRL, 0),
337 _CLK_DETAIL(GPIO3_CLK, CM_PER_GPIO3_CLKCTRL, 0),
338
339 /* I2C modules */
340 _CLK_DETAIL(I2C0_CLK, CM_WKUP_I2C0_CLKCTRL, 0),
341 _CLK_DETAIL(I2C1_CLK, CM_PER_I2C1_CLKCTRL, 0),
342 _CLK_DETAIL(I2C2_CLK, CM_PER_I2C2_CLKCTRL, 0),
343
344 /* TSC_ADC module */
345 _CLK_DETAIL(TSC_ADC_CLK, CM_WKUP_ADC_TSC_CLKCTRL, 0),
346
347 /* EDMA modules */
348 _CLK_DETAIL(EDMA_TPCC_CLK, CM_PER_TPCC_CLKCTRL, 0),
349 _CLK_DETAIL(EDMA_TPTC0_CLK, CM_PER_TPTC0_CLKCTRL, 0),
350 _CLK_DETAIL(EDMA_TPTC1_CLK, CM_PER_TPTC1_CLKCTRL, 0),
351 _CLK_DETAIL(EDMA_TPTC2_CLK, CM_PER_TPTC2_CLKCTRL, 0),
352
353 /* MMCHS modules*/
354 _CLK_DETAIL(MMC0_CLK, CM_PER_MMC0_CLKCTRL, 0),
355 _CLK_DETAIL(MMC1_CLK, CM_PER_MMC1_CLKCTRL, 0),
356 _CLK_DETAIL(MMC2_CLK, CM_PER_MMC1_CLKCTRL, 0),
357
358 /* PWMSS modules */
359 _CLK_DETAIL(PWMSS0_CLK, CM_PER_EPWMSS0_CLKCTRL, 0),
360 _CLK_DETAIL(PWMSS1_CLK, CM_PER_EPWMSS1_CLKCTRL, 0),
361 _CLK_DETAIL(PWMSS2_CLK, CM_PER_EPWMSS2_CLKCTRL, 0),
362
363 _CLK_DETAIL(MAILBOX0_CLK, CM_PER_MAILBOX0_CLKCTRL, 0),
364 _CLK_DETAIL(SPINLOCK0_CLK, CM_PER_SPINLOCK0_CLKCTRL, 0),
365
366 { INVALID_CLK_IDENT, 0},
367};
368
369/* Read/Write macros */
370#define prcm_read_4(reg) \
371 bus_space_read_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg)
372#define prcm_write_4(reg, val) \
373 bus_space_write_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg, val)
374
375void am335x_prcm_setup_dmtimer(int);
376
377static int
378am335x_prcm_probe(device_t dev)
379{
380
381 if (!ofw_bus_status_okay(dev))
382 return (ENXIO);
383
384 if (ofw_bus_is_compatible(dev, "am335x,prcm")) {
385 device_set_desc(dev, "AM335x Power and Clock Management");
386 return(BUS_PROBE_DEFAULT);
387 }
388
389 return (ENXIO);
390}
391
392static int
393am335x_prcm_attach(device_t dev)
394{
395 struct am335x_prcm_softc *sc = device_get_softc(dev);
396 unsigned int sysclk, fclk;
397
398 if (am335x_prcm_sc)
399 return (ENXIO);
400
401 if (bus_alloc_resources(dev, am335x_prcm_spec, sc->res)) {
402 device_printf(dev, "could not allocate resources\n");
403 return (ENXIO);
404 }
405
406 sc->bst = rman_get_bustag(sc->res[0]);
407 sc->bsh = rman_get_bushandle(sc->res[0]);
408
409 am335x_prcm_sc = sc;
410 ti_cpu_reset = am335x_prcm_reset;
411
412 am335x_clk_get_sysclk_freq(NULL, &sysclk);
413 am335x_clk_get_arm_fclk_freq(NULL, &fclk);
414 device_printf(dev, "Clocks: System %u.%01u MHz, CPU %u MHz\n",
415 sysclk/1000000, (sysclk % 1000000)/100000, fclk/1000000);
416
417 return (0);
418}
419
420static device_method_t am335x_prcm_methods[] = {
421 DEVMETHOD(device_probe, am335x_prcm_probe),
422 DEVMETHOD(device_attach, am335x_prcm_attach),
423 { 0, 0 }
424};
425
426static driver_t am335x_prcm_driver = {
427 "am335x_prcm",
428 am335x_prcm_methods,
429 sizeof(struct am335x_prcm_softc),
430};
431
432static devclass_t am335x_prcm_devclass;
433
434DRIVER_MODULE(am335x_prcm, simplebus, am335x_prcm_driver,
435 am335x_prcm_devclass, 0, 0);
436MODULE_DEPEND(am335x_prcm, ti_scm, 1, 1, 1);
437
438static struct am335x_clk_details*
439am335x_clk_details(clk_ident_t id)
440{
441 struct am335x_clk_details *walker;
442
443 for (walker = g_am335x_clk_details; walker->id != INVALID_CLK_IDENT; walker++) {
444 if (id == walker->id)
445 return (walker);
446 }
447
448 return NULL;
449}
450
451static int
452am335x_clk_noop_activate(struct ti_clock_dev *clkdev)
453{
454
455 return (0);
456}
457
458static int
459am335x_clk_generic_activate(struct ti_clock_dev *clkdev)
460{
461 struct am335x_prcm_softc *sc = am335x_prcm_sc;
462 struct am335x_clk_details* clk_details;
463
464 if (sc == NULL)
465 return ENXIO;
466
467 clk_details = am335x_clk_details(clkdev->id);
468
469 if (clk_details == NULL)
470 return (ENXIO);
471
472 /* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
473 prcm_write_4(clk_details->clkctrl_reg, 2);
474 while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 2)
475 DELAY(10);
476
477 return (0);
478}
479
480static int
481am335x_clk_gpio_activate(struct ti_clock_dev *clkdev)
482{
483 struct am335x_prcm_softc *sc = am335x_prcm_sc;
484 struct am335x_clk_details* clk_details;
485
486 if (sc == NULL)
487 return ENXIO;
488
489 clk_details = am335x_clk_details(clkdev->id);
490
491 if (clk_details == NULL)
492 return (ENXIO);
493
494 /* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
495 /* set *_CLKCTRL register OPTFCLKEN_GPIO_1_G DBCLK[18] to FCLK_EN(1) */
496 prcm_write_4(clk_details->clkctrl_reg, 2 | (1 << 18));
497 while ((prcm_read_4(clk_details->clkctrl_reg) &
498 (3 | (1 << 18) )) != (2 | (1 << 18)))
499 DELAY(10);
500
501 return (0);
502}
503
504static int
505am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev)
506{
507
508 return(0);
509}
510
511static int
512am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev)
513{
514 struct am335x_prcm_softc *sc = am335x_prcm_sc;
515 struct am335x_clk_details* clk_details;
516
517 if (sc == NULL)
518 return ENXIO;
519
520 clk_details = am335x_clk_details(clkdev->id);
521
522 if (clk_details == NULL)
523 return (ENXIO);
524
525 /* set *_CLKCTRL register MODULEMODE[1:0] to disable(0) */
526 prcm_write_4(clk_details->clkctrl_reg, 0);
527 while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 0)
528 DELAY(10);
529
530 return (0);
531}
532
533static int
534am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
535{
536
537 return (0);
538}
539
540static int
541am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
542{
543 struct am335x_prcm_softc *sc = am335x_prcm_sc;
544 struct am335x_clk_details* clk_details;
545 uint32_t reg;
546
547 if (sc == NULL)
548 return ENXIO;
549
550 clk_details = am335x_clk_details(clkdev->id);
551
552 if (clk_details == NULL)
553 return (ENXIO);
554
555 switch (clksrc) {
556 case EXT_CLK:
557 reg = 0; /* SEL2: TCLKIN clock */
558 break;
559 case SYSCLK_CLK:
560 reg = 1; /* SEL1: CLK_M_OSC clock */
561 break;
562 case F32KHZ_CLK:
563 reg = 2; /* SEL3: CLK_32KHZ clock */
564 break;
565 default:
566 return (ENXIO);
567 }
568
569 prcm_write_4(clk_details->clksel_reg, reg);
570 while ((prcm_read_4(clk_details->clksel_reg) & 0x3) != reg)
571 DELAY(10);
572
573 return (0);
574}
575
576static int
577am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
578{
579 *freq = 96000000;
580 return (0);
581}
582
583static int
584am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
585{
586 uint32_t ctrl_status;
587
588 /* Read the input clock freq from the control module */
589 /* control_status reg (0x40) */
590 if (ti_scm_reg_read_4(0x40, &ctrl_status))
591 return ENXIO;
592
593 switch ((ctrl_status>>22) & 0x3) {
594 case 0x0:
595 /* 19.2Mhz */
596 *freq = 19200000;
597 break;
598 case 0x1:
599 /* 24Mhz */
600 *freq = 24000000;
601 break;
602 case 0x2:
603 /* 25Mhz */
604 *freq = 25000000;
605 break;
606 case 0x3:
607 /* 26Mhz */
608 *freq = 26000000;
609 break;
610 }
611
612 return (0);
613}
614
615#define DPLL_BYP_CLKSEL(reg) ((reg>>23) & 1)
616#define DPLL_DIV(reg) ((reg & 0x7f)+1)
617#define DPLL_MULT(reg) ((reg>>8) & 0x7FF)
618
619static int
620am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
621{
622 uint32_t reg;
623 uint32_t sysclk;
624
625 reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_MPU);
626
627 /*Check if we are running in bypass */
628 if (DPLL_BYP_CLKSEL(reg))
629 return ENXIO;
630
631 am335x_clk_get_sysclk_freq(NULL, &sysclk);
632 *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
633 return(0);
634}
635
636static int
637am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
638{
639 uint32_t reg;
640 uint32_t sysclk;
641
642 reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_DISP);
643
644 /*Check if we are running in bypass */
645 if (DPLL_BYP_CLKSEL(reg))
646 return ENXIO;
647
648 am335x_clk_get_sysclk_freq(NULL, &sysclk);
649 *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
650 return(0);
651}
652
653static void
654am335x_prcm_reset(void)
655{
656 prcm_write_4(PRM_RSTCTRL, (1<<1));
657}
658
659static int
660am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev)
661{
662 struct am335x_prcm_softc *sc = am335x_prcm_sc;
663
664 if (sc == NULL)
665 return ENXIO;
666
667 /* set MODULENAME to ENABLE */
668 prcm_write_4(CM_PER_CPGMAC0_CLKCTRL, 2);
669
670 /* wait for IDLEST to become Func(0) */
671 while(prcm_read_4(CM_PER_CPGMAC0_CLKCTRL) & (3<<16));
672
673 /*set CLKTRCTRL to SW_WKUP(2) */
674 prcm_write_4(CM_PER_CPSW_CLKSTCTRL, 2);
675
676 /* wait for 125 MHz OCP clock to become active */
677 while((prcm_read_4(CM_PER_CPSW_CLKSTCTRL) & (1<<4)) == 0);
678 return(0);
679}
680
681static int
682am335x_clk_musb0_activate(struct ti_clock_dev *clkdev)
683{
684 struct am335x_prcm_softc *sc = am335x_prcm_sc;
685
686 if (sc == NULL)
687 return ENXIO;
688
689 /* set ST_DPLL_CLKDCOLDO(9) to CLK_GATED(1) */
690 /* set DPLL_CLKDCOLDO_GATE_CTRL(8) to CLK_ENABLE(1)*/
691 prcm_write_4(CM_WKUP_CM_CLKDCOLDO_DPLL_PER, 0x300);
692
693 /*set MODULEMODE to ENABLE(2) */
694 prcm_write_4(CM_PER_USB0_CLKCTRL, 2);
695
696 /* wait for MODULEMODE to become ENABLE(2) */
697 while ((prcm_read_4(CM_PER_USB0_CLKCTRL) & 0x3) != 2)
698 DELAY(10);
699
700 /* wait for IDLEST to become Func(0) */
701 while(prcm_read_4(CM_PER_USB0_CLKCTRL) & (3<<16))
702 DELAY(10);
703
704 return(0);
705}
706
707static int
708am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev)
709{
710 struct am335x_prcm_softc *sc = am335x_prcm_sc;
711
712 if (sc == NULL)
713 return (ENXIO);
714
715 /* Bypass mode */
716 prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x4);
717
718 /* Make sure it's in bypass mode */
719 while (!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP)
720 & (1 << 8)))
721 DELAY(10);
722
723 /*
724 * For now set frequency to 5xSYSFREQ
725 * More flexible control might be required
726 */
727 prcm_write_4(CM_WKUP_CM_CLKSEL_DPLL_DISP, (5 << 8) | 0);
728
729 /* Locked mode */
730 prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7);
731
732 int timeout = 10000;
733 while ((!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP)
734 & (1 << 0))) && timeout--)
735 DELAY(10);
736
737 /*set MODULEMODE to ENABLE(2) */
738 prcm_write_4(CM_PER_LCDC_CLKCTRL, 2);
739
740 /* wait for MODULEMODE to become ENABLE(2) */
741 while ((prcm_read_4(CM_PER_LCDC_CLKCTRL) & 0x3) != 2)
742 DELAY(10);
743
744 /* wait for IDLEST to become Func(0) */
745 while(prcm_read_4(CM_PER_LCDC_CLKCTRL) & (3<<16))
746 DELAY(10);
747
748 return (0);
749}
750
751static int
752am335x_clk_pruss_activate(struct ti_clock_dev *clkdev)
753{
754 struct am335x_prcm_softc *sc = am335x_prcm_sc;
755
756 if (sc == NULL)
757 return (ENXIO);
758
759 /* Set MODULEMODE to ENABLE(2) */
760 prcm_write_4(CM_PER_PRUSS_CLKCTRL, 2);
761
762 /* Wait for MODULEMODE to become ENABLE(2) */
763 while ((prcm_read_4(CM_PER_PRUSS_CLKCTRL) & 0x3) != 2)
764 DELAY(10);
765
766 /* Set CLKTRCTRL to SW_WKUP(2) */
767 prcm_write_4(CM_PER_PRUSS_CLKSTCTRL, 2);
768
769 /* Wait for the 200 MHz OCP clock to become active */
770 while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<4)) == 0)
771 DELAY(10);
772
773 /* Wait for the 200 MHz IEP clock to become active */
774 while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<5)) == 0)
775 DELAY(10);
776
777 /* Wait for the 192 MHz UART clock to become active */
778 while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<6)) == 0)
779 DELAY(10);
780
781 /* Select DISP DPLL as OCP clock */
782 prcm_write_4(CLKSEL_PRUSS_OCP_CLK, 1);
783 while ((prcm_read_4(CLKSEL_PRUSS_OCP_CLK) & 0x3) != 1)
784 DELAY(10);
785
786 /* Clear the RESET bit */
787 prcm_write_4(PRM_PER_RSTCTRL, prcm_read_4(PRM_PER_RSTCTRL) & ~2);
788
789 return (0);
790}