2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/param.h>
33 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/module.h>
37 #include <sys/malloc.h>
39 #include <sys/timeet.h>
40 #include <sys/timetc.h>
41 #include <sys/watchdog.h>
42 #include <machine/bus.h>
43 #include <machine/cpu.h>
44 #include <machine/intr.h>
46 #include <arm/ti/tivar.h>
47 #include <arm/ti/ti_scm.h>
48 #include <arm/ti/ti_prcm.h>
50 #include <dev/ofw/openfirm.h>
51 #include <dev/ofw/ofw_bus.h>
52 #include <dev/ofw/ofw_bus_subr.h>
54 #include <machine/bus.h>
56 #include "am335x_scm.h"
59 #define CM_PER_L4LS_CLKSTCTRL (CM_PER + 0x000)
60 #define CM_PER_L3S_CLKSTCTRL (CM_PER + 0x004)
61 #define CM_PER_L3_CLKSTCTRL (CM_PER + 0x00C)
62 #define CM_PER_CPGMAC0_CLKCTRL (CM_PER + 0x014)
63 #define CM_PER_LCDC_CLKCTRL (CM_PER + 0x018)
64 #define CM_PER_USB0_CLKCTRL (CM_PER + 0x01C)
65 #define CM_PER_TPTC0_CLKCTRL (CM_PER + 0x024)
66 #define CM_PER_UART5_CLKCTRL (CM_PER + 0x038)
67 #define CM_PER_MMC0_CLKCTRL (CM_PER + 0x03C)
68 #define CM_PER_I2C2_CLKCTRL (CM_PER + 0x044)
69 #define CM_PER_I2C1_CLKCTRL (CM_PER + 0x048)
70 #define CM_PER_SPI0_CLKCTRL (CM_PER + 0x04C)
71 #define CM_PER_SPI1_CLKCTRL (CM_PER + 0x050)
72 #define CM_PER_UART1_CLKCTRL (CM_PER + 0x06C)
73 #define CM_PER_UART2_CLKCTRL (CM_PER + 0x070)
74 #define CM_PER_UART3_CLKCTRL (CM_PER + 0x074)
75 #define CM_PER_UART4_CLKCTRL (CM_PER + 0x078)
76 #define CM_PER_TIMER7_CLKCTRL (CM_PER + 0x07C)
77 #define CM_PER_TIMER2_CLKCTRL (CM_PER + 0x080)
78 #define CM_PER_TIMER3_CLKCTRL (CM_PER + 0x084)
79 #define CM_PER_TIMER4_CLKCTRL (CM_PER + 0x088)
80 #define CM_PER_GPIO1_CLKCTRL (CM_PER + 0x0AC)
81 #define CM_PER_GPIO2_CLKCTRL (CM_PER + 0x0B0)
82 #define CM_PER_GPIO3_CLKCTRL (CM_PER + 0x0B4)
83 #define CM_PER_TPCC_CLKCTRL (CM_PER + 0x0BC)
84 #define CM_PER_EPWMSS1_CLKCTRL (CM_PER + 0x0CC)
85 #define CM_PER_EPWMSS0_CLKCTRL (CM_PER + 0x0D4)
86 #define CM_PER_EPWMSS2_CLKCTRL (CM_PER + 0x0D8)
87 #define CM_PER_L3_INSTR_CLKCTRL (CM_PER + 0x0DC)
88 #define CM_PER_L3_CLKCTRL (CM_PER + 0x0E0)
89 #define CM_PER_PRUSS_CLKCTRL (CM_PER + 0x0E8)
90 #define CM_PER_TIMER5_CLKCTRL (CM_PER + 0x0EC)
91 #define CM_PER_TIMER6_CLKCTRL (CM_PER + 0x0F0)
92 #define CM_PER_MMC1_CLKCTRL (CM_PER + 0x0F4)
93 #define CM_PER_MMC2_CLKCTRL (CM_PER + 0x0F8)
94 #define CM_PER_TPTC1_CLKCTRL (CM_PER + 0x0FC)
95 #define CM_PER_TPTC2_CLKCTRL (CM_PER + 0x100)
96 #define CM_PER_SPINLOCK0_CLKCTRL (CM_PER + 0x10C)
97 #define CM_PER_MAILBOX0_CLKCTRL (CM_PER + 0x110)
98 #define CM_PER_OCPWP_L3_CLKSTCTRL (CM_PER + 0x12C)
99 #define CM_PER_OCPWP_CLKCTRL (CM_PER + 0x130)
100 #define CM_PER_CPSW_CLKSTCTRL (CM_PER + 0x144)
101 #define CM_PER_PRUSS_CLKSTCTRL (CM_PER + 0x140)
103 #define CM_WKUP 0x400
104 #define CM_WKUP_CLKSTCTRL (CM_WKUP + 0x000)
105 #define CM_WKUP_CONTROL_CLKCTRL (CM_WKUP + 0x004)
106 #define CM_WKUP_GPIO0_CLKCTRL (CM_WKUP + 0x008)
107 #define CM_WKUP_CM_L3_AON_CLKSTCTRL (CM_WKUP + 0x01C)
108 #define CM_WKUP_CM_CLKSEL_DPLL_MPU (CM_WKUP + 0x02C)
109 #define CM_WKUP_CM_IDLEST_DPLL_DISP (CM_WKUP + 0x048)
110 #define CM_WKUP_CM_CLKSEL_DPLL_DISP (CM_WKUP + 0x054)
111 #define CM_WKUP_CM_CLKDCOLDO_DPLL_PER (CM_WKUP + 0x07C)
112 #define CM_WKUP_CM_CLKMODE_DPLL_DISP (CM_WKUP + 0x098)
113 #define CM_WKUP_I2C0_CLKCTRL (CM_WKUP + 0x0B8)
114 #define CM_WKUP_ADC_TSC_CLKCTRL (CM_WKUP + 0x0BC)
116 #define CM_DPLL 0x500
117 #define CLKSEL_TIMER7_CLK (CM_DPLL + 0x004)
118 #define CLKSEL_TIMER2_CLK (CM_DPLL + 0x008)
119 #define CLKSEL_TIMER3_CLK (CM_DPLL + 0x00C)
120 #define CLKSEL_TIMER4_CLK (CM_DPLL + 0x010)
121 #define CLKSEL_TIMER5_CLK (CM_DPLL + 0x018)
122 #define CLKSEL_TIMER6_CLK (CM_DPLL + 0x01C)
123 #define CLKSEL_PRUSS_OCP_CLK (CM_DPLL + 0x030)
126 #define CM_RTC_RTC_CLKCTRL (CM_RTC + 0x000)
127 #define CM_RTC_CLKSTCTRL (CM_RTC + 0x004)
129 #define PRM_PER 0xC00
130 #define PRM_PER_RSTCTRL (PRM_PER + 0x00)
132 #define PRM_DEVICE_OFFSET 0xF00
133 #define PRM_RSTCTRL (PRM_DEVICE_OFFSET + 0x00)
135 struct am335x_prcm_softc {
136 struct resource * res[2];
138 bus_space_handle_t bsh;
142 static struct resource_spec am335x_prcm_spec[] = {
143 { SYS_RES_MEMORY, 0, RF_ACTIVE },
147 static struct am335x_prcm_softc *am335x_prcm_sc = NULL;
149 static int am335x_clk_noop_activate(struct ti_clock_dev *clkdev);
150 static int am335x_clk_generic_activate(struct ti_clock_dev *clkdev);
151 static int am335x_clk_gpio_activate(struct ti_clock_dev *clkdev);
152 static int am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev);
153 static int am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev);
154 static int am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
155 static int am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
156 static int am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
157 static int am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
158 static int am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
159 static int am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
160 static int am335x_clk_set_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int freq);
161 static void am335x_prcm_reset(void);
162 static int am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev);
163 static int am335x_clk_musb0_activate(struct ti_clock_dev *clkdev);
164 static int am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev);
165 static int am335x_clk_pruss_activate(struct ti_clock_dev *clkdev);
167 #define AM335X_NOOP_CLOCK_DEV(i) \
169 .clk_activate = am335x_clk_noop_activate, \
170 .clk_deactivate = am335x_clk_noop_deactivate, \
171 .clk_set_source = am335x_clk_noop_set_source, \
172 .clk_accessible = NULL, \
173 .clk_get_source_freq = NULL, \
174 .clk_set_source_freq = NULL \
177 #define AM335X_GENERIC_CLOCK_DEV(i) \
179 .clk_activate = am335x_clk_generic_activate, \
180 .clk_deactivate = am335x_clk_generic_deactivate, \
181 .clk_set_source = am335x_clk_generic_set_source, \
182 .clk_accessible = NULL, \
183 .clk_get_source_freq = NULL, \
184 .clk_set_source_freq = NULL \
187 #define AM335X_GPIO_CLOCK_DEV(i) \
189 .clk_activate = am335x_clk_gpio_activate, \
190 .clk_deactivate = am335x_clk_generic_deactivate, \
191 .clk_set_source = am335x_clk_generic_set_source, \
192 .clk_accessible = NULL, \
193 .clk_get_source_freq = NULL, \
194 .clk_set_source_freq = NULL \
197 #define AM335X_MMCHS_CLOCK_DEV(i) \
199 .clk_activate = am335x_clk_generic_activate, \
200 .clk_deactivate = am335x_clk_generic_deactivate, \
201 .clk_set_source = am335x_clk_generic_set_source, \
202 .clk_accessible = NULL, \
203 .clk_get_source_freq = am335x_clk_hsmmc_get_source_freq, \
204 .clk_set_source_freq = NULL \
207 struct ti_clock_dev ti_am335x_clk_devmap[] = {
210 .clk_activate = NULL,
211 .clk_deactivate = NULL,
212 .clk_set_source = NULL,
213 .clk_accessible = NULL,
214 .clk_get_source_freq = am335x_clk_get_sysclk_freq,
215 .clk_set_source_freq = NULL,
217 /* MPU (ARM) core clocks */
219 .clk_activate = NULL,
220 .clk_deactivate = NULL,
221 .clk_set_source = NULL,
222 .clk_accessible = NULL,
223 .clk_get_source_freq = am335x_clk_get_arm_fclk_freq,
224 .clk_set_source_freq = NULL,
226 /* CPSW Ethernet Switch core clocks */
228 .clk_activate = am335x_clk_cpsw_activate,
229 .clk_deactivate = NULL,
230 .clk_set_source = NULL,
231 .clk_accessible = NULL,
232 .clk_get_source_freq = NULL,
233 .clk_set_source_freq = NULL,
236 /* Mentor USB HS controller core clocks */
238 .clk_activate = am335x_clk_musb0_activate,
239 .clk_deactivate = NULL,
240 .clk_set_source = NULL,
241 .clk_accessible = NULL,
242 .clk_get_source_freq = NULL,
243 .clk_set_source_freq = NULL,
246 /* LCD controller clocks */
248 .clk_activate = am335x_clk_lcdc_activate,
249 .clk_deactivate = NULL,
250 .clk_set_source = NULL,
251 .clk_accessible = NULL,
252 .clk_get_source_freq = am335x_clk_get_arm_disp_freq,
253 .clk_set_source_freq = am335x_clk_set_arm_disp_freq,
257 AM335X_NOOP_CLOCK_DEV(UART1_CLK),
258 AM335X_GENERIC_CLOCK_DEV(UART2_CLK),
259 AM335X_GENERIC_CLOCK_DEV(UART3_CLK),
260 AM335X_GENERIC_CLOCK_DEV(UART4_CLK),
261 AM335X_GENERIC_CLOCK_DEV(UART5_CLK),
262 AM335X_GENERIC_CLOCK_DEV(UART6_CLK),
265 AM335X_GENERIC_CLOCK_DEV(TIMER2_CLK),
266 AM335X_GENERIC_CLOCK_DEV(TIMER3_CLK),
267 AM335X_GENERIC_CLOCK_DEV(TIMER4_CLK),
268 AM335X_GENERIC_CLOCK_DEV(TIMER5_CLK),
269 AM335X_GENERIC_CLOCK_DEV(TIMER6_CLK),
270 AM335X_GENERIC_CLOCK_DEV(TIMER7_CLK),
272 /* GPIO, we use hwmods as reference, not units in spec */
273 AM335X_GPIO_CLOCK_DEV(GPIO1_CLK),
274 AM335X_GPIO_CLOCK_DEV(GPIO2_CLK),
275 AM335X_GPIO_CLOCK_DEV(GPIO3_CLK),
276 AM335X_GPIO_CLOCK_DEV(GPIO4_CLK),
278 /* I2C we use hwmods as reference, not units in spec */
279 AM335X_GENERIC_CLOCK_DEV(I2C1_CLK),
280 AM335X_GENERIC_CLOCK_DEV(I2C2_CLK),
281 AM335X_GENERIC_CLOCK_DEV(I2C3_CLK),
283 /* McSPI we use hwmods as reference, not units in spec */
284 AM335X_GENERIC_CLOCK_DEV(SPI0_CLK),
285 AM335X_GENERIC_CLOCK_DEV(SPI1_CLK),
288 AM335X_GENERIC_CLOCK_DEV(TSC_ADC_CLK),
291 AM335X_GENERIC_CLOCK_DEV(EDMA_TPCC_CLK),
292 AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC0_CLK),
293 AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC1_CLK),
294 AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC2_CLK),
297 AM335X_MMCHS_CLOCK_DEV(MMC1_CLK),
298 AM335X_MMCHS_CLOCK_DEV(MMC2_CLK),
299 AM335X_MMCHS_CLOCK_DEV(MMC3_CLK),
302 AM335X_GENERIC_CLOCK_DEV(PWMSS0_CLK),
303 AM335X_GENERIC_CLOCK_DEV(PWMSS1_CLK),
304 AM335X_GENERIC_CLOCK_DEV(PWMSS2_CLK),
306 /* System Mailbox clock */
307 AM335X_GENERIC_CLOCK_DEV(MAILBOX0_CLK),
310 AM335X_GENERIC_CLOCK_DEV(SPINLOCK0_CLK),
314 .clk_activate = am335x_clk_pruss_activate,
315 .clk_deactivate = NULL,
316 .clk_set_source = NULL,
317 .clk_accessible = NULL,
318 .clk_get_source_freq = NULL,
319 .clk_set_source_freq = NULL,
323 AM335X_GENERIC_CLOCK_DEV(RTC_CLK),
325 { INVALID_CLK_IDENT, NULL, NULL, NULL, NULL }
328 struct am335x_clk_details {
330 uint32_t clkctrl_reg;
334 #define _CLK_DETAIL(i, c, s) \
336 .clkctrl_reg = (c), \
340 static struct am335x_clk_details g_am335x_clk_details[] = {
342 /* UART. UART0 clock not controllable. */
343 _CLK_DETAIL(UART1_CLK, 0, 0),
344 _CLK_DETAIL(UART2_CLK, CM_PER_UART1_CLKCTRL, 0),
345 _CLK_DETAIL(UART3_CLK, CM_PER_UART2_CLKCTRL, 0),
346 _CLK_DETAIL(UART4_CLK, CM_PER_UART3_CLKCTRL, 0),
347 _CLK_DETAIL(UART5_CLK, CM_PER_UART4_CLKCTRL, 0),
348 _CLK_DETAIL(UART6_CLK, CM_PER_UART5_CLKCTRL, 0),
350 /* DMTimer modules */
351 _CLK_DETAIL(TIMER2_CLK, CM_PER_TIMER2_CLKCTRL, CLKSEL_TIMER2_CLK),
352 _CLK_DETAIL(TIMER3_CLK, CM_PER_TIMER3_CLKCTRL, CLKSEL_TIMER3_CLK),
353 _CLK_DETAIL(TIMER4_CLK, CM_PER_TIMER4_CLKCTRL, CLKSEL_TIMER4_CLK),
354 _CLK_DETAIL(TIMER5_CLK, CM_PER_TIMER5_CLKCTRL, CLKSEL_TIMER5_CLK),
355 _CLK_DETAIL(TIMER6_CLK, CM_PER_TIMER6_CLKCTRL, CLKSEL_TIMER6_CLK),
356 _CLK_DETAIL(TIMER7_CLK, CM_PER_TIMER7_CLKCTRL, CLKSEL_TIMER7_CLK),
358 /* GPIO modules, hwmods start with gpio1 */
359 _CLK_DETAIL(GPIO1_CLK, CM_WKUP_GPIO0_CLKCTRL, 0),
360 _CLK_DETAIL(GPIO2_CLK, CM_PER_GPIO1_CLKCTRL, 0),
361 _CLK_DETAIL(GPIO3_CLK, CM_PER_GPIO2_CLKCTRL, 0),
362 _CLK_DETAIL(GPIO4_CLK, CM_PER_GPIO3_CLKCTRL, 0),
364 /* I2C modules, hwmods start with i2c1 */
365 _CLK_DETAIL(I2C1_CLK, CM_WKUP_I2C0_CLKCTRL, 0),
366 _CLK_DETAIL(I2C2_CLK, CM_PER_I2C1_CLKCTRL, 0),
367 _CLK_DETAIL(I2C3_CLK, CM_PER_I2C2_CLKCTRL, 0),
369 /* McSPI modules, hwmods start with spi0 */
370 _CLK_DETAIL(SPI0_CLK, CM_PER_SPI0_CLKCTRL, 0),
371 _CLK_DETAIL(SPI1_CLK, CM_PER_SPI1_CLKCTRL, 0),
374 _CLK_DETAIL(TSC_ADC_CLK, CM_WKUP_ADC_TSC_CLKCTRL, 0),
377 _CLK_DETAIL(EDMA_TPCC_CLK, CM_PER_TPCC_CLKCTRL, 0),
378 _CLK_DETAIL(EDMA_TPTC0_CLK, CM_PER_TPTC0_CLKCTRL, 0),
379 _CLK_DETAIL(EDMA_TPTC1_CLK, CM_PER_TPTC1_CLKCTRL, 0),
380 _CLK_DETAIL(EDMA_TPTC2_CLK, CM_PER_TPTC2_CLKCTRL, 0),
382 /* MMCHS modules, hwmods start with mmc1*/
383 _CLK_DETAIL(MMC1_CLK, CM_PER_MMC0_CLKCTRL, 0),
384 _CLK_DETAIL(MMC2_CLK, CM_PER_MMC1_CLKCTRL, 0),
385 _CLK_DETAIL(MMC3_CLK, CM_PER_MMC1_CLKCTRL, 0),
388 _CLK_DETAIL(PWMSS0_CLK, CM_PER_EPWMSS0_CLKCTRL, 0),
389 _CLK_DETAIL(PWMSS1_CLK, CM_PER_EPWMSS1_CLKCTRL, 0),
390 _CLK_DETAIL(PWMSS2_CLK, CM_PER_EPWMSS2_CLKCTRL, 0),
392 _CLK_DETAIL(MAILBOX0_CLK, CM_PER_MAILBOX0_CLKCTRL, 0),
393 _CLK_DETAIL(SPINLOCK0_CLK, CM_PER_SPINLOCK0_CLKCTRL, 0),
396 _CLK_DETAIL(RTC_CLK, CM_RTC_RTC_CLKCTRL, 0),
398 { INVALID_CLK_IDENT, 0},
401 /* Read/Write macros */
402 #define prcm_read_4(reg) \
403 bus_space_read_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg)
404 #define prcm_write_4(reg, val) \
405 bus_space_write_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg, val)
407 void am335x_prcm_setup_dmtimer(int);
410 am335x_prcm_probe(device_t dev)
413 if (!ofw_bus_status_okay(dev))
416 if (ofw_bus_is_compatible(dev, "ti,am3-prcm")) {
417 device_set_desc(dev, "AM335x Power and Clock Management");
418 return(BUS_PROBE_DEFAULT);
425 am335x_prcm_attach(device_t dev)
427 struct am335x_prcm_softc *sc = device_get_softc(dev);
432 if (bus_alloc_resources(dev, am335x_prcm_spec, sc->res)) {
433 device_printf(dev, "could not allocate resources\n");
437 sc->bst = rman_get_bustag(sc->res[0]);
438 sc->bsh = rman_get_bushandle(sc->res[0]);
441 ti_cpu_reset = am335x_prcm_reset;
447 am335x_prcm_new_pass(device_t dev)
449 struct am335x_prcm_softc *sc = device_get_softc(dev);
450 unsigned int sysclk, fclk;
452 sc = device_get_softc(dev);
453 if (sc->attach_done ||
454 bus_current_pass < (BUS_PASS_TIMER + BUS_PASS_ORDER_EARLY)) {
455 bus_generic_new_pass(dev);
461 if (am335x_clk_get_sysclk_freq(NULL, &sysclk) != 0)
463 if (am335x_clk_get_arm_fclk_freq(NULL, &fclk) != 0)
466 device_printf(dev, "Clocks: System %u.%01u MHz, CPU %u MHz\n",
467 sysclk/1000000, (sysclk % 1000000)/100000, fclk/1000000);
469 device_printf(dev, "can't read frequencies yet (SCM device not ready?)\n");
480 static device_method_t am335x_prcm_methods[] = {
481 DEVMETHOD(device_probe, am335x_prcm_probe),
482 DEVMETHOD(device_attach, am335x_prcm_attach),
485 DEVMETHOD(bus_new_pass, am335x_prcm_new_pass),
489 static driver_t am335x_prcm_driver = {
492 sizeof(struct am335x_prcm_softc),
495 static devclass_t am335x_prcm_devclass;
497 EARLY_DRIVER_MODULE(am335x_prcm, simplebus, am335x_prcm_driver,
498 am335x_prcm_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
499 MODULE_VERSION(am335x_prcm, 1);
500 MODULE_DEPEND(am335x_prcm, ti_scm, 1, 1, 1);
502 static struct am335x_clk_details*
503 am335x_clk_details(clk_ident_t id)
505 struct am335x_clk_details *walker;
507 for (walker = g_am335x_clk_details; walker->id != INVALID_CLK_IDENT; walker++) {
508 if (id == walker->id)
516 am335x_clk_noop_activate(struct ti_clock_dev *clkdev)
523 am335x_clk_generic_activate(struct ti_clock_dev *clkdev)
525 struct am335x_prcm_softc *sc = am335x_prcm_sc;
526 struct am335x_clk_details* clk_details;
531 clk_details = am335x_clk_details(clkdev->id);
533 if (clk_details == NULL)
536 /* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
537 prcm_write_4(clk_details->clkctrl_reg, 2);
538 while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 2)
545 am335x_clk_gpio_activate(struct ti_clock_dev *clkdev)
547 struct am335x_prcm_softc *sc = am335x_prcm_sc;
548 struct am335x_clk_details* clk_details;
553 clk_details = am335x_clk_details(clkdev->id);
555 if (clk_details == NULL)
558 /* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
559 /* set *_CLKCTRL register OPTFCLKEN_GPIO_1_G DBCLK[18] to FCLK_EN(1) */
560 prcm_write_4(clk_details->clkctrl_reg, 2 | (1 << 18));
561 while ((prcm_read_4(clk_details->clkctrl_reg) &
562 (3 | (1 << 18) )) != (2 | (1 << 18)))
569 am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev)
576 am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev)
578 struct am335x_prcm_softc *sc = am335x_prcm_sc;
579 struct am335x_clk_details* clk_details;
584 clk_details = am335x_clk_details(clkdev->id);
586 if (clk_details == NULL)
589 /* set *_CLKCTRL register MODULEMODE[1:0] to disable(0) */
590 prcm_write_4(clk_details->clkctrl_reg, 0);
591 while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 0)
598 am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
605 am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
607 struct am335x_prcm_softc *sc = am335x_prcm_sc;
608 struct am335x_clk_details* clk_details;
614 clk_details = am335x_clk_details(clkdev->id);
616 if (clk_details == NULL)
621 reg = 0; /* SEL2: TCLKIN clock */
624 reg = 1; /* SEL1: CLK_M_OSC clock */
627 reg = 2; /* SEL3: CLK_32KHZ clock */
633 prcm_write_4(clk_details->clksel_reg, reg);
634 while ((prcm_read_4(clk_details->clksel_reg) & 0x3) != reg)
641 am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
648 am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
650 uint32_t ctrl_status;
652 /* Read the input clock freq from the control module. */
653 if (ti_scm_reg_read_4(SCM_CTRL_STATUS, &ctrl_status))
656 switch ((ctrl_status>>22) & 0x3) {
678 #define DPLL_BYP_CLKSEL(reg) ((reg>>23) & 1)
679 #define DPLL_DIV(reg) ((reg & 0x7f)+1)
680 #define DPLL_MULT(reg) ((reg>>8) & 0x7FF)
681 #define DPLL_MAX_MUL 0x800
682 #define DPLL_MAX_DIV 0x80
685 am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
690 reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_MPU);
692 /*Check if we are running in bypass */
693 if (DPLL_BYP_CLKSEL(reg))
696 am335x_clk_get_sysclk_freq(NULL, &sysclk);
697 *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
702 am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
707 reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_DISP);
709 /*Check if we are running in bypass */
710 if (DPLL_BYP_CLKSEL(reg))
713 am335x_clk_get_sysclk_freq(NULL, &sysclk);
714 *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
719 am335x_clk_set_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int freq)
724 unsigned int delta, min_delta;
726 am335x_clk_get_sysclk_freq(NULL, &sysclk);
729 prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x4);
731 /* Make sure it's in bypass mode */
732 while (!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP)
736 /* Dumb and non-optimal implementation */
738 for (i = 1; i < DPLL_MAX_MUL; i++) {
739 for (j = 1; j < DPLL_MAX_DIV; j++) {
740 delta = abs(freq - i*(sysclk/j));
741 if (delta < min_delta) {
751 prcm_write_4(CM_WKUP_CM_CLKSEL_DPLL_DISP, (mul << 8) | (div - 1));
754 prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7);
757 while ((!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP)
758 & (1 << 0))) && timeout--)
765 am335x_prcm_reset(void)
767 prcm_write_4(PRM_RSTCTRL, (1<<1));
771 am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev)
773 struct am335x_prcm_softc *sc = am335x_prcm_sc;
778 /* set MODULENAME to ENABLE */
779 prcm_write_4(CM_PER_CPGMAC0_CLKCTRL, 2);
781 /* wait for IDLEST to become Func(0) */
782 while(prcm_read_4(CM_PER_CPGMAC0_CLKCTRL) & (3<<16));
784 /*set CLKTRCTRL to SW_WKUP(2) */
785 prcm_write_4(CM_PER_CPSW_CLKSTCTRL, 2);
787 /* wait for 125 MHz OCP clock to become active */
788 while((prcm_read_4(CM_PER_CPSW_CLKSTCTRL) & (1<<4)) == 0);
793 am335x_clk_musb0_activate(struct ti_clock_dev *clkdev)
795 struct am335x_prcm_softc *sc = am335x_prcm_sc;
800 /* set ST_DPLL_CLKDCOLDO(9) to CLK_GATED(1) */
801 /* set DPLL_CLKDCOLDO_GATE_CTRL(8) to CLK_ENABLE(1)*/
802 prcm_write_4(CM_WKUP_CM_CLKDCOLDO_DPLL_PER, 0x300);
804 /*set MODULEMODE to ENABLE(2) */
805 prcm_write_4(CM_PER_USB0_CLKCTRL, 2);
807 /* wait for MODULEMODE to become ENABLE(2) */
808 while ((prcm_read_4(CM_PER_USB0_CLKCTRL) & 0x3) != 2)
811 /* wait for IDLEST to become Func(0) */
812 while(prcm_read_4(CM_PER_USB0_CLKCTRL) & (3<<16))
819 am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev)
821 struct am335x_prcm_softc *sc = am335x_prcm_sc;
827 * For now set frequency to 2*VGA_PIXEL_CLOCK
829 am335x_clk_set_arm_disp_freq(clkdev, 25175000*2);
831 /*set MODULEMODE to ENABLE(2) */
832 prcm_write_4(CM_PER_LCDC_CLKCTRL, 2);
834 /* wait for MODULEMODE to become ENABLE(2) */
835 while ((prcm_read_4(CM_PER_LCDC_CLKCTRL) & 0x3) != 2)
838 /* wait for IDLEST to become Func(0) */
839 while(prcm_read_4(CM_PER_LCDC_CLKCTRL) & (3<<16))
846 am335x_clk_pruss_activate(struct ti_clock_dev *clkdev)
848 struct am335x_prcm_softc *sc = am335x_prcm_sc;
853 /* Set MODULEMODE to ENABLE(2) */
854 prcm_write_4(CM_PER_PRUSS_CLKCTRL, 2);
856 /* Wait for MODULEMODE to become ENABLE(2) */
857 while ((prcm_read_4(CM_PER_PRUSS_CLKCTRL) & 0x3) != 2)
860 /* Set CLKTRCTRL to SW_WKUP(2) */
861 prcm_write_4(CM_PER_PRUSS_CLKSTCTRL, 2);
863 /* Wait for the 200 MHz OCP clock to become active */
864 while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<4)) == 0)
867 /* Wait for the 200 MHz IEP clock to become active */
868 while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<5)) == 0)
871 /* Wait for the 192 MHz UART clock to become active */
872 while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<6)) == 0)
875 /* Select L3F as OCP clock */
876 prcm_write_4(CLKSEL_PRUSS_OCP_CLK, 0);
877 while ((prcm_read_4(CLKSEL_PRUSS_OCP_CLK) & 0x3) != 0)
880 /* Clear the RESET bit */
881 prcm_write_4(PRM_PER_RSTCTRL, prcm_read_4(PRM_PER_RSTCTRL) & ~2);