2 * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.h>
31 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/module.h>
35 #include <sys/malloc.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>
44 #include <arm/ti/tivar.h>
45 #include <arm/ti/ti_scm.h>
46 #include <arm/ti/ti_prcm.h>
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>
53 #include <machine/bus.h>
54 #include <machine/fdt.h>
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)
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)
111 #define CM_DPLL 0x500
112 #define CLKSEL_TIMER7_CLK (CM_DPLL + 0x004)
113 #define CLKSEL_TIMER2_CLK (CM_DPLL + 0x008)
114 #define CLKSEL_TIMER3_CLK (CM_DPLL + 0x00C)
115 #define CLKSEL_TIMER4_CLK (CM_DPLL + 0x010)
116 #define CLKSEL_TIMER5_CLK (CM_DPLL + 0x018)
117 #define CLKSEL_TIMER6_CLK (CM_DPLL + 0x01C)
118 #define CLKSEL_PRUSS_OCP_CLK (CM_DPLL + 0x030)
120 #define PRM_PER 0xC00
121 #define PRM_PER_RSTCTRL (PRM_PER + 0x00)
123 #define PRM_DEVICE_OFFSET 0xF00
124 #define PRM_RSTCTRL (PRM_DEVICE_OFFSET + 0x00)
126 struct am335x_prcm_softc {
127 struct resource * res[2];
129 bus_space_handle_t bsh;
132 static struct resource_spec am335x_prcm_spec[] = {
133 { SYS_RES_MEMORY, 0, RF_ACTIVE },
137 static struct am335x_prcm_softc *am335x_prcm_sc = NULL;
139 static int am335x_clk_noop_activate(struct ti_clock_dev *clkdev);
140 static int am335x_clk_generic_activate(struct ti_clock_dev *clkdev);
141 static int am335x_clk_gpio_activate(struct ti_clock_dev *clkdev);
142 static int am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev);
143 static int am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev);
144 static int am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
145 static int am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
146 static int am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
147 static int am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
148 static int am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
149 static int am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
150 static void am335x_prcm_reset(void);
151 static int am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev);
152 static int am335x_clk_musb0_activate(struct ti_clock_dev *clkdev);
153 static int am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev);
154 static int am335x_clk_pruss_activate(struct ti_clock_dev *clkdev);
156 #define AM335X_NOOP_CLOCK_DEV(i) \
158 .clk_activate = am335x_clk_noop_activate, \
159 .clk_deactivate = am335x_clk_noop_deactivate, \
160 .clk_set_source = am335x_clk_noop_set_source, \
161 .clk_accessible = NULL, \
162 .clk_get_source_freq = NULL \
165 #define AM335X_GENERIC_CLOCK_DEV(i) \
167 .clk_activate = am335x_clk_generic_activate, \
168 .clk_deactivate = am335x_clk_generic_deactivate, \
169 .clk_set_source = am335x_clk_generic_set_source, \
170 .clk_accessible = NULL, \
171 .clk_get_source_freq = NULL \
174 #define AM335X_GPIO_CLOCK_DEV(i) \
176 .clk_activate = am335x_clk_gpio_activate, \
177 .clk_deactivate = am335x_clk_generic_deactivate, \
178 .clk_set_source = am335x_clk_generic_set_source, \
179 .clk_accessible = NULL, \
180 .clk_get_source_freq = NULL \
183 #define AM335X_MMCHS_CLOCK_DEV(i) \
185 .clk_activate = am335x_clk_generic_activate, \
186 .clk_deactivate = am335x_clk_generic_deactivate, \
187 .clk_set_source = am335x_clk_generic_set_source, \
188 .clk_accessible = NULL, \
189 .clk_get_source_freq = am335x_clk_hsmmc_get_source_freq \
192 struct ti_clock_dev ti_clk_devmap[] = {
195 .clk_activate = NULL,
196 .clk_deactivate = NULL,
197 .clk_set_source = NULL,
198 .clk_accessible = NULL,
199 .clk_get_source_freq = am335x_clk_get_sysclk_freq,
201 /* MPU (ARM) core clocks */
203 .clk_activate = NULL,
204 .clk_deactivate = NULL,
205 .clk_set_source = NULL,
206 .clk_accessible = NULL,
207 .clk_get_source_freq = am335x_clk_get_arm_fclk_freq,
209 /* CPSW Ethernet Switch core clocks */
211 .clk_activate = am335x_clk_cpsw_activate,
212 .clk_deactivate = NULL,
213 .clk_set_source = NULL,
214 .clk_accessible = NULL,
215 .clk_get_source_freq = NULL,
218 /* Mentor USB HS controller core clocks */
220 .clk_activate = am335x_clk_musb0_activate,
221 .clk_deactivate = NULL,
222 .clk_set_source = NULL,
223 .clk_accessible = NULL,
224 .clk_get_source_freq = NULL,
227 /* LCD controller clocks */
229 .clk_activate = am335x_clk_lcdc_activate,
230 .clk_deactivate = NULL,
231 .clk_set_source = NULL,
232 .clk_accessible = NULL,
233 .clk_get_source_freq = am335x_clk_get_arm_disp_freq,
236 /* UART. Uart0 clock cannot be controlled. */
237 AM335X_NOOP_CLOCK_DEV(UART0_CLK),
238 AM335X_GENERIC_CLOCK_DEV(UART1_CLK),
239 AM335X_GENERIC_CLOCK_DEV(UART2_CLK),
240 AM335X_GENERIC_CLOCK_DEV(UART3_CLK),
241 AM335X_GENERIC_CLOCK_DEV(UART4_CLK),
242 AM335X_GENERIC_CLOCK_DEV(UART5_CLK),
245 AM335X_GENERIC_CLOCK_DEV(DMTIMER2_CLK),
246 AM335X_GENERIC_CLOCK_DEV(DMTIMER3_CLK),
247 AM335X_GENERIC_CLOCK_DEV(DMTIMER4_CLK),
248 AM335X_GENERIC_CLOCK_DEV(DMTIMER5_CLK),
249 AM335X_GENERIC_CLOCK_DEV(DMTIMER6_CLK),
250 AM335X_GENERIC_CLOCK_DEV(DMTIMER7_CLK),
253 AM335X_GPIO_CLOCK_DEV(GPIO0_CLK),
254 AM335X_GPIO_CLOCK_DEV(GPIO1_CLK),
255 AM335X_GPIO_CLOCK_DEV(GPIO2_CLK),
256 AM335X_GPIO_CLOCK_DEV(GPIO3_CLK),
259 AM335X_GENERIC_CLOCK_DEV(I2C0_CLK),
260 AM335X_GENERIC_CLOCK_DEV(I2C1_CLK),
261 AM335X_GENERIC_CLOCK_DEV(I2C2_CLK),
264 AM335X_GENERIC_CLOCK_DEV(EDMA_TPCC_CLK),
265 AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC0_CLK),
266 AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC1_CLK),
267 AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC2_CLK),
270 AM335X_MMCHS_CLOCK_DEV(MMC0_CLK),
271 AM335X_MMCHS_CLOCK_DEV(MMC1_CLK),
272 AM335X_MMCHS_CLOCK_DEV(MMC2_CLK),
275 AM335X_GENERIC_CLOCK_DEV(PWMSS0_CLK),
276 AM335X_GENERIC_CLOCK_DEV(PWMSS1_CLK),
277 AM335X_GENERIC_CLOCK_DEV(PWMSS2_CLK),
279 /* System Mailbox clock */
280 AM335X_GENERIC_CLOCK_DEV(MAILBOX0_CLK),
283 AM335X_GENERIC_CLOCK_DEV(SPINLOCK0_CLK),
287 .clk_activate = am335x_clk_pruss_activate,
288 .clk_deactivate = NULL,
289 .clk_set_source = NULL,
290 .clk_accessible = NULL,
291 .clk_get_source_freq = NULL,
296 { INVALID_CLK_IDENT, NULL, NULL, NULL, NULL }
299 struct am335x_clk_details {
301 uint32_t clkctrl_reg;
305 #define _CLK_DETAIL(i, c, s) \
307 .clkctrl_reg = (c), \
311 static struct am335x_clk_details g_am335x_clk_details[] = {
313 /* UART. UART0 clock not controllable. */
314 _CLK_DETAIL(UART0_CLK, 0, 0),
315 _CLK_DETAIL(UART1_CLK, CM_PER_UART1_CLKCTRL, 0),
316 _CLK_DETAIL(UART2_CLK, CM_PER_UART2_CLKCTRL, 0),
317 _CLK_DETAIL(UART3_CLK, CM_PER_UART3_CLKCTRL, 0),
318 _CLK_DETAIL(UART4_CLK, CM_PER_UART4_CLKCTRL, 0),
319 _CLK_DETAIL(UART5_CLK, CM_PER_UART5_CLKCTRL, 0),
321 /* DMTimer modules */
322 _CLK_DETAIL(DMTIMER2_CLK, CM_PER_TIMER2_CLKCTRL, CLKSEL_TIMER2_CLK),
323 _CLK_DETAIL(DMTIMER3_CLK, CM_PER_TIMER3_CLKCTRL, CLKSEL_TIMER3_CLK),
324 _CLK_DETAIL(DMTIMER4_CLK, CM_PER_TIMER4_CLKCTRL, CLKSEL_TIMER4_CLK),
325 _CLK_DETAIL(DMTIMER5_CLK, CM_PER_TIMER5_CLKCTRL, CLKSEL_TIMER5_CLK),
326 _CLK_DETAIL(DMTIMER6_CLK, CM_PER_TIMER6_CLKCTRL, CLKSEL_TIMER6_CLK),
327 _CLK_DETAIL(DMTIMER7_CLK, CM_PER_TIMER7_CLKCTRL, CLKSEL_TIMER7_CLK),
330 _CLK_DETAIL(GPIO0_CLK, CM_WKUP_GPIO0_CLKCTRL, 0),
331 _CLK_DETAIL(GPIO1_CLK, CM_PER_GPIO1_CLKCTRL, 0),
332 _CLK_DETAIL(GPIO2_CLK, CM_PER_GPIO2_CLKCTRL, 0),
333 _CLK_DETAIL(GPIO3_CLK, CM_PER_GPIO3_CLKCTRL, 0),
336 _CLK_DETAIL(I2C0_CLK, CM_WKUP_I2C0_CLKCTRL, 0),
337 _CLK_DETAIL(I2C1_CLK, CM_PER_I2C1_CLKCTRL, 0),
338 _CLK_DETAIL(I2C2_CLK, CM_PER_I2C2_CLKCTRL, 0),
341 _CLK_DETAIL(EDMA_TPCC_CLK, CM_PER_TPCC_CLKCTRL, 0),
342 _CLK_DETAIL(EDMA_TPTC0_CLK, CM_PER_TPTC0_CLKCTRL, 0),
343 _CLK_DETAIL(EDMA_TPTC1_CLK, CM_PER_TPTC1_CLKCTRL, 0),
344 _CLK_DETAIL(EDMA_TPTC2_CLK, CM_PER_TPTC2_CLKCTRL, 0),
347 _CLK_DETAIL(MMC0_CLK, CM_PER_MMC0_CLKCTRL, 0),
348 _CLK_DETAIL(MMC1_CLK, CM_PER_MMC1_CLKCTRL, 0),
349 _CLK_DETAIL(MMC2_CLK, CM_PER_MMC1_CLKCTRL, 0),
352 _CLK_DETAIL(PWMSS0_CLK, CM_PER_EPWMSS0_CLKCTRL, 0),
353 _CLK_DETAIL(PWMSS1_CLK, CM_PER_EPWMSS1_CLKCTRL, 0),
354 _CLK_DETAIL(PWMSS2_CLK, CM_PER_EPWMSS2_CLKCTRL, 0),
356 _CLK_DETAIL(MAILBOX0_CLK, CM_PER_MAILBOX0_CLKCTRL, 0),
357 _CLK_DETAIL(SPINLOCK0_CLK, CM_PER_SPINLOCK0_CLKCTRL, 0),
359 { INVALID_CLK_IDENT, 0},
362 /* Read/Write macros */
363 #define prcm_read_4(reg) \
364 bus_space_read_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg)
365 #define prcm_write_4(reg, val) \
366 bus_space_write_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg, val)
368 void am335x_prcm_setup_dmtimer(int);
371 am335x_prcm_probe(device_t dev)
373 if (ofw_bus_is_compatible(dev, "am335x,prcm")) {
374 device_set_desc(dev, "AM335x Power and Clock Management");
375 return(BUS_PROBE_DEFAULT);
382 am335x_prcm_attach(device_t dev)
384 struct am335x_prcm_softc *sc = device_get_softc(dev);
385 unsigned int sysclk, fclk;
390 if (bus_alloc_resources(dev, am335x_prcm_spec, sc->res)) {
391 device_printf(dev, "could not allocate resources\n");
395 sc->bst = rman_get_bustag(sc->res[0]);
396 sc->bsh = rman_get_bushandle(sc->res[0]);
399 ti_cpu_reset = am335x_prcm_reset;
401 am335x_clk_get_sysclk_freq(NULL, &sysclk);
402 am335x_clk_get_arm_fclk_freq(NULL, &fclk);
403 device_printf(dev, "Clocks: System %u.%01u MHz, CPU %u MHz\n",
404 sysclk/1000000, (sysclk % 1000000)/100000, fclk/1000000);
409 static device_method_t am335x_prcm_methods[] = {
410 DEVMETHOD(device_probe, am335x_prcm_probe),
411 DEVMETHOD(device_attach, am335x_prcm_attach),
415 static driver_t am335x_prcm_driver = {
418 sizeof(struct am335x_prcm_softc),
421 static devclass_t am335x_prcm_devclass;
423 DRIVER_MODULE(am335x_prcm, simplebus, am335x_prcm_driver,
424 am335x_prcm_devclass, 0, 0);
425 MODULE_DEPEND(am335x_prcm, ti_scm, 1, 1, 1);
427 static struct am335x_clk_details*
428 am335x_clk_details(clk_ident_t id)
430 struct am335x_clk_details *walker;
432 for (walker = g_am335x_clk_details; walker->id != INVALID_CLK_IDENT; walker++) {
433 if (id == walker->id)
441 am335x_clk_noop_activate(struct ti_clock_dev *clkdev)
448 am335x_clk_generic_activate(struct ti_clock_dev *clkdev)
450 struct am335x_prcm_softc *sc = am335x_prcm_sc;
451 struct am335x_clk_details* clk_details;
456 clk_details = am335x_clk_details(clkdev->id);
458 if (clk_details == NULL)
461 /* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
462 prcm_write_4(clk_details->clkctrl_reg, 2);
463 while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 2)
470 am335x_clk_gpio_activate(struct ti_clock_dev *clkdev)
472 struct am335x_prcm_softc *sc = am335x_prcm_sc;
473 struct am335x_clk_details* clk_details;
478 clk_details = am335x_clk_details(clkdev->id);
480 if (clk_details == NULL)
483 /* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
484 /* set *_CLKCTRL register OPTFCLKEN_GPIO_1_G DBCLK[18] to FCLK_EN(1) */
485 prcm_write_4(clk_details->clkctrl_reg, 2 | (1 << 18));
486 while ((prcm_read_4(clk_details->clkctrl_reg) &
487 (3 | (1 << 18) )) != (2 | (1 << 18)))
494 am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev)
501 am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev)
503 struct am335x_prcm_softc *sc = am335x_prcm_sc;
504 struct am335x_clk_details* clk_details;
509 clk_details = am335x_clk_details(clkdev->id);
511 if (clk_details == NULL)
514 /* set *_CLKCTRL register MODULEMODE[1:0] to disable(0) */
515 prcm_write_4(clk_details->clkctrl_reg, 0);
516 while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 0)
523 am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
530 am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
532 struct am335x_prcm_softc *sc = am335x_prcm_sc;
533 struct am335x_clk_details* clk_details;
539 clk_details = am335x_clk_details(clkdev->id);
541 if (clk_details == NULL)
546 reg = 0; /* SEL2: TCLKIN clock */
549 reg = 1; /* SEL1: CLK_M_OSC clock */
552 reg = 2; /* SEL3: CLK_32KHZ clock */
558 prcm_write_4(clk_details->clksel_reg, reg);
559 while ((prcm_read_4(clk_details->clksel_reg) & 0x3) != reg)
566 am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
573 am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
575 uint32_t ctrl_status;
577 /* Read the input clock freq from the control module */
578 /* control_status reg (0x40) */
579 if (ti_scm_reg_read_4(0x40, &ctrl_status))
582 switch ((ctrl_status>>22) & 0x3) {
604 #define DPLL_BYP_CLKSEL(reg) ((reg>>23) & 1)
605 #define DPLL_DIV(reg) ((reg & 0x7f)+1)
606 #define DPLL_MULT(reg) ((reg>>8) & 0x7FF)
609 am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
614 reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_MPU);
616 /*Check if we are running in bypass */
617 if (DPLL_BYP_CLKSEL(reg))
620 am335x_clk_get_sysclk_freq(NULL, &sysclk);
621 *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
626 am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
631 reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_DISP);
633 /*Check if we are running in bypass */
634 if (DPLL_BYP_CLKSEL(reg))
637 am335x_clk_get_sysclk_freq(NULL, &sysclk);
638 *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
643 am335x_prcm_reset(void)
645 prcm_write_4(PRM_RSTCTRL, (1<<1));
649 am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev)
651 struct am335x_prcm_softc *sc = am335x_prcm_sc;
656 /* set MODULENAME to ENABLE */
657 prcm_write_4(CM_PER_CPGMAC0_CLKCTRL, 2);
659 /* wait for IDLEST to become Func(0) */
660 while(prcm_read_4(CM_PER_CPGMAC0_CLKCTRL) & (3<<16));
662 /*set CLKTRCTRL to SW_WKUP(2) */
663 prcm_write_4(CM_PER_CPSW_CLKSTCTRL, 2);
665 /* wait for 125 MHz OCP clock to become active */
666 while((prcm_read_4(CM_PER_CPSW_CLKSTCTRL) & (1<<4)) == 0);
671 am335x_clk_musb0_activate(struct ti_clock_dev *clkdev)
673 struct am335x_prcm_softc *sc = am335x_prcm_sc;
678 /* set ST_DPLL_CLKDCOLDO(9) to CLK_GATED(1) */
679 /* set DPLL_CLKDCOLDO_GATE_CTRL(8) to CLK_ENABLE(1)*/
680 prcm_write_4(CM_WKUP_CM_CLKDCOLDO_DPLL_PER, 0x300);
682 /*set MODULEMODE to ENABLE(2) */
683 prcm_write_4(CM_PER_USB0_CLKCTRL, 2);
685 /* wait for MODULEMODE to become ENABLE(2) */
686 while ((prcm_read_4(CM_PER_USB0_CLKCTRL) & 0x3) != 2)
689 /* wait for IDLEST to become Func(0) */
690 while(prcm_read_4(CM_PER_USB0_CLKCTRL) & (3<<16))
697 am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev)
699 struct am335x_prcm_softc *sc = am335x_prcm_sc;
705 prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x4);
707 /* Make sure it's in bypass mode */
708 while (!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP)
713 * For now set frequency to 5xSYSFREQ
714 * More flexible control might be required
716 prcm_write_4(CM_WKUP_CM_CLKSEL_DPLL_DISP, (5 << 8) | 0);
719 prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7);
722 while ((!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP)
723 & (1 << 0))) && timeout--)
726 /*set MODULEMODE to ENABLE(2) */
727 prcm_write_4(CM_PER_LCDC_CLKCTRL, 2);
729 /* wait for MODULEMODE to become ENABLE(2) */
730 while ((prcm_read_4(CM_PER_LCDC_CLKCTRL) & 0x3) != 2)
733 /* wait for IDLEST to become Func(0) */
734 while(prcm_read_4(CM_PER_LCDC_CLKCTRL) & (3<<16))
741 am335x_clk_pruss_activate(struct ti_clock_dev *clkdev)
743 struct am335x_prcm_softc *sc = am335x_prcm_sc;
748 /* Set MODULEMODE to ENABLE(2) */
749 prcm_write_4(CM_PER_PRUSS_CLKCTRL, 2);
751 /* Wait for MODULEMODE to become ENABLE(2) */
752 while ((prcm_read_4(CM_PER_PRUSS_CLKCTRL) & 0x3) != 2)
755 /* Set CLKTRCTRL to SW_WKUP(2) */
756 prcm_write_4(CM_PER_PRUSS_CLKSTCTRL, 2);
758 /* Wait for the 200 MHz OCP clock to become active */
759 while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<4)) == 0)
762 /* Wait for the 200 MHz IEP clock to become active */
763 while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<5)) == 0)
766 /* Wait for the 192 MHz UART clock to become active */
767 while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<6)) == 0)
770 /* Select DISP DPLL as OCP clock */
771 prcm_write_4(CLKSEL_PRUSS_OCP_CLK, 1);
772 while ((prcm_read_4(CLKSEL_PRUSS_OCP_CLK) & 0x3) != 1)
775 /* Clear the RESET bit */
776 prcm_write_4(PRM_PER_RSTCTRL, prcm_read_4(PRM_PER_RSTCTRL) & ~2);