]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/arm/ti/am335x/am335x_prcm.c
MFC r257199, r257200, r257217:
[FreeBSD/stable/10.git] / sys / arm / ti / am335x / am335x_prcm.c
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$");
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
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)
119
120 #define PRM_PER                         0xC00
121 #define PRM_PER_RSTCTRL                 (PRM_PER + 0x00)
122
123 #define PRM_DEVICE_OFFSET               0xF00
124 #define PRM_RSTCTRL                     (PRM_DEVICE_OFFSET + 0x00)
125
126 struct am335x_prcm_softc {
127         struct resource *       res[2];
128         bus_space_tag_t         bst;
129         bus_space_handle_t      bsh;
130 };
131
132 static struct resource_spec am335x_prcm_spec[] = {
133         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
134         { -1, 0 }
135 };
136
137 static struct am335x_prcm_softc *am335x_prcm_sc = NULL;
138
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);
155
156 #define AM335X_NOOP_CLOCK_DEV(i) \
157         {       .id = (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 \
163         }
164
165 #define AM335X_GENERIC_CLOCK_DEV(i) \
166         {       .id = (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 \
172         }
173
174 #define AM335X_GPIO_CLOCK_DEV(i) \
175         {       .id = (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 \
181         }
182
183 #define AM335X_MMCHS_CLOCK_DEV(i) \
184         {       .id = (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 \
190         }
191
192 struct ti_clock_dev ti_clk_devmap[] = {
193         /* System clocks */
194         {       .id                  = SYS_CLK,
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,
200         },
201         /* MPU (ARM) core clocks */
202         {       .id                  = MPU_CLK,
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,
208         },
209         /* CPSW Ethernet Switch core clocks */
210         {       .id                  = CPSW_CLK,
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,
216         },
217
218         /* Mentor USB HS controller core clocks */
219         {       .id                  = MUSB0_CLK,
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,
225         },
226
227         /* LCD controller clocks */
228         {       .id                  = LCDC_CLK,
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,
234         },
235
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),
243
244         /* DMTimer */
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),
251
252         /* GPIO */
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),
257
258         /* I2C */
259         AM335X_GENERIC_CLOCK_DEV(I2C0_CLK),
260         AM335X_GENERIC_CLOCK_DEV(I2C1_CLK),
261         AM335X_GENERIC_CLOCK_DEV(I2C2_CLK),
262
263         /* EDMA */
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),
268
269         /* MMCHS */
270         AM335X_MMCHS_CLOCK_DEV(MMC0_CLK),
271         AM335X_MMCHS_CLOCK_DEV(MMC1_CLK),
272         AM335X_MMCHS_CLOCK_DEV(MMC2_CLK),
273
274         /* PWMSS */
275         AM335X_GENERIC_CLOCK_DEV(PWMSS0_CLK),
276         AM335X_GENERIC_CLOCK_DEV(PWMSS1_CLK),
277         AM335X_GENERIC_CLOCK_DEV(PWMSS2_CLK),
278
279         /* System Mailbox clock */
280         AM335X_GENERIC_CLOCK_DEV(MAILBOX0_CLK),
281
282         /* SPINLOCK */
283         AM335X_GENERIC_CLOCK_DEV(SPINLOCK0_CLK),
284
285         /* PRU-ICSS */
286         {       .id                  = PRUSS_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,
292         },
293
294
295
296         {  INVALID_CLK_IDENT, NULL, NULL, NULL, NULL }
297 };
298
299 struct am335x_clk_details {
300         clk_ident_t     id;
301         uint32_t        clkctrl_reg;
302         uint32_t        clksel_reg;
303 };
304
305 #define _CLK_DETAIL(i, c, s) \
306         {       .id = (i), \
307                 .clkctrl_reg = (c), \
308                 .clksel_reg = (s), \
309         }
310
311 static struct am335x_clk_details g_am335x_clk_details[] = {
312
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),
320
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),
328
329         /* GPIO modules */
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),
334
335         /* I2C modules */
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),
339
340         /* EDMA modules */
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),
345
346         /* MMCHS modules*/
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),
350
351         /* PWMSS modules */
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),
355
356         _CLK_DETAIL(MAILBOX0_CLK, CM_PER_MAILBOX0_CLKCTRL, 0),
357         _CLK_DETAIL(SPINLOCK0_CLK, CM_PER_SPINLOCK0_CLKCTRL, 0),
358
359         { INVALID_CLK_IDENT, 0},
360 };
361
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)
367
368 void am335x_prcm_setup_dmtimer(int);
369
370 static int
371 am335x_prcm_probe(device_t dev)
372 {
373         if (ofw_bus_is_compatible(dev, "am335x,prcm")) {
374                 device_set_desc(dev, "AM335x Power and Clock Management");
375                 return(BUS_PROBE_DEFAULT);
376         }
377
378         return (ENXIO);
379 }
380
381 static int
382 am335x_prcm_attach(device_t dev)
383 {
384         struct am335x_prcm_softc *sc = device_get_softc(dev);
385         unsigned int sysclk, fclk;
386
387         if (am335x_prcm_sc)
388                 return (ENXIO);
389
390         if (bus_alloc_resources(dev, am335x_prcm_spec, sc->res)) {
391                 device_printf(dev, "could not allocate resources\n");
392                 return (ENXIO);
393         }
394
395         sc->bst = rman_get_bustag(sc->res[0]);
396         sc->bsh = rman_get_bushandle(sc->res[0]);
397
398         am335x_prcm_sc = sc;
399         ti_cpu_reset = am335x_prcm_reset;
400
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);
405
406         return (0);
407 }
408
409 static device_method_t am335x_prcm_methods[] = {
410         DEVMETHOD(device_probe,         am335x_prcm_probe),
411         DEVMETHOD(device_attach,        am335x_prcm_attach),
412         { 0, 0 }
413 };
414
415 static driver_t am335x_prcm_driver = {
416         "am335x_prcm",
417         am335x_prcm_methods,
418         sizeof(struct am335x_prcm_softc),
419 };
420
421 static devclass_t am335x_prcm_devclass;
422
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);
426
427 static struct am335x_clk_details*
428 am335x_clk_details(clk_ident_t id)
429 {
430         struct am335x_clk_details *walker;
431
432         for (walker = g_am335x_clk_details; walker->id != INVALID_CLK_IDENT; walker++) {
433                 if (id == walker->id)
434                         return (walker);
435         }
436
437         return NULL;
438 }
439
440 static int
441 am335x_clk_noop_activate(struct ti_clock_dev *clkdev)
442 {
443
444         return (0);
445 }
446
447 static int
448 am335x_clk_generic_activate(struct ti_clock_dev *clkdev)
449 {
450         struct am335x_prcm_softc *sc = am335x_prcm_sc;
451         struct am335x_clk_details* clk_details;
452
453         if (sc == NULL)
454                 return ENXIO;
455
456         clk_details = am335x_clk_details(clkdev->id);
457
458         if (clk_details == NULL)
459                 return (ENXIO);
460
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)
464                 DELAY(10);
465
466         return (0);
467 }
468
469 static int
470 am335x_clk_gpio_activate(struct ti_clock_dev *clkdev)
471 {
472         struct am335x_prcm_softc *sc = am335x_prcm_sc;
473         struct am335x_clk_details* clk_details;
474
475         if (sc == NULL)
476                 return ENXIO;
477
478         clk_details = am335x_clk_details(clkdev->id);
479
480         if (clk_details == NULL)
481                 return (ENXIO);
482
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)))
488                 DELAY(10);
489
490         return (0);
491 }
492
493 static int
494 am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev)
495 {
496
497         return(0);
498 }
499
500 static int
501 am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev)
502 {
503         struct am335x_prcm_softc *sc = am335x_prcm_sc;
504         struct am335x_clk_details* clk_details;
505
506         if (sc == NULL)
507                 return ENXIO;
508
509         clk_details = am335x_clk_details(clkdev->id);
510
511         if (clk_details == NULL)
512                 return (ENXIO);
513
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)
517                 DELAY(10);
518
519         return (0);
520 }
521
522 static int
523 am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
524 {
525
526         return (0);
527 }
528
529 static int
530 am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
531 {
532         struct am335x_prcm_softc *sc = am335x_prcm_sc;
533         struct am335x_clk_details* clk_details;
534         uint32_t reg;
535
536         if (sc == NULL)
537                 return ENXIO;
538
539         clk_details = am335x_clk_details(clkdev->id);
540
541         if (clk_details == NULL)
542                 return (ENXIO);
543
544         switch (clksrc) {
545                 case EXT_CLK:
546                         reg = 0; /* SEL2: TCLKIN clock */
547                         break;
548                 case SYSCLK_CLK:
549                         reg = 1; /* SEL1: CLK_M_OSC clock */
550                         break;
551                 case F32KHZ_CLK:
552                         reg = 2; /* SEL3: CLK_32KHZ clock */
553                         break;
554                 default:
555                         return (ENXIO);
556         }
557
558         prcm_write_4(clk_details->clksel_reg, reg);
559         while ((prcm_read_4(clk_details->clksel_reg) & 0x3) != reg)
560                 DELAY(10);
561
562         return (0);
563 }
564
565 static int
566 am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev,  unsigned int *freq)
567 {
568         *freq = 96000000;
569         return (0);
570 }
571
572 static int
573 am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
574 {
575         uint32_t ctrl_status;
576
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))
580                 return ENXIO;
581
582         switch ((ctrl_status>>22) & 0x3) {
583         case 0x0:
584                 /* 19.2Mhz */
585                 *freq = 19200000;
586                 break;
587         case 0x1:
588                 /* 24Mhz */
589                 *freq = 24000000;
590                 break;
591         case 0x2:
592                 /* 25Mhz */
593                 *freq = 25000000;
594                 break;
595         case 0x3:
596                 /* 26Mhz */
597                 *freq = 26000000;
598                 break;
599         }
600
601         return (0);
602 }
603
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)
607
608 static int
609 am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
610 {
611         uint32_t reg;
612         uint32_t sysclk;
613
614         reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_MPU);
615
616         /*Check if we are running in bypass */
617         if (DPLL_BYP_CLKSEL(reg))
618                 return ENXIO;
619
620         am335x_clk_get_sysclk_freq(NULL, &sysclk);
621         *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
622         return(0);
623 }
624
625 static int
626 am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
627 {
628         uint32_t reg;
629         uint32_t sysclk;
630
631         reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_DISP);
632
633         /*Check if we are running in bypass */
634         if (DPLL_BYP_CLKSEL(reg))
635                 return ENXIO;
636
637         am335x_clk_get_sysclk_freq(NULL, &sysclk);
638         *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
639         return(0);
640 }
641
642 static void
643 am335x_prcm_reset(void)
644 {
645         prcm_write_4(PRM_RSTCTRL, (1<<1));
646 }
647
648 static int
649 am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev)
650 {
651         struct am335x_prcm_softc *sc = am335x_prcm_sc;
652
653         if (sc == NULL)
654                 return ENXIO;
655
656         /* set MODULENAME to ENABLE */
657         prcm_write_4(CM_PER_CPGMAC0_CLKCTRL, 2);
658
659         /* wait for IDLEST to become Func(0) */
660         while(prcm_read_4(CM_PER_CPGMAC0_CLKCTRL) & (3<<16));
661
662         /*set CLKTRCTRL to SW_WKUP(2) */
663         prcm_write_4(CM_PER_CPSW_CLKSTCTRL, 2);
664
665         /* wait for 125 MHz OCP clock to become active */
666         while((prcm_read_4(CM_PER_CPSW_CLKSTCTRL) & (1<<4)) == 0);
667         return(0);
668 }
669
670 static int
671 am335x_clk_musb0_activate(struct ti_clock_dev *clkdev)
672 {
673         struct am335x_prcm_softc *sc = am335x_prcm_sc;
674
675         if (sc == NULL)
676                 return ENXIO;
677
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);
681
682         /*set MODULEMODE to ENABLE(2) */
683         prcm_write_4(CM_PER_USB0_CLKCTRL, 2);
684
685         /* wait for MODULEMODE to become ENABLE(2) */
686         while ((prcm_read_4(CM_PER_USB0_CLKCTRL) & 0x3) != 2)
687                 DELAY(10);
688
689         /* wait for IDLEST to become Func(0) */
690         while(prcm_read_4(CM_PER_USB0_CLKCTRL) & (3<<16))
691                 DELAY(10);
692
693         return(0);
694 }
695
696 static int
697 am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev)
698 {
699         struct am335x_prcm_softc *sc = am335x_prcm_sc;
700
701         if (sc == NULL)
702                 return (ENXIO);
703
704         /* Bypass mode */
705         prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x4);
706
707         /* Make sure it's in bypass mode */
708         while (!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP) 
709             & (1 << 8)))
710                 DELAY(10);
711
712         /* 
713          * For now set frequency to  5xSYSFREQ 
714          * More flexible control might be required
715          */
716         prcm_write_4(CM_WKUP_CM_CLKSEL_DPLL_DISP, (5 << 8) | 0);
717
718         /* Locked mode */
719         prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7);
720
721         int timeout = 10000;
722         while ((!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP) 
723             & (1 << 0))) && timeout--)
724                 DELAY(10);
725
726         /*set MODULEMODE to ENABLE(2) */
727         prcm_write_4(CM_PER_LCDC_CLKCTRL, 2);
728
729         /* wait for MODULEMODE to become ENABLE(2) */
730         while ((prcm_read_4(CM_PER_LCDC_CLKCTRL) & 0x3) != 2)
731                 DELAY(10);
732
733         /* wait for IDLEST to become Func(0) */
734         while(prcm_read_4(CM_PER_LCDC_CLKCTRL) & (3<<16))
735                 DELAY(10);
736
737         return (0);
738 }
739
740 static int
741 am335x_clk_pruss_activate(struct ti_clock_dev *clkdev)
742 {
743         struct am335x_prcm_softc *sc = am335x_prcm_sc;
744
745         if (sc == NULL)
746                 return (ENXIO);
747
748         /* Set MODULEMODE to ENABLE(2) */
749         prcm_write_4(CM_PER_PRUSS_CLKCTRL, 2);
750
751         /* Wait for MODULEMODE to become ENABLE(2) */
752         while ((prcm_read_4(CM_PER_PRUSS_CLKCTRL) & 0x3) != 2)
753                 DELAY(10);
754
755         /* Set CLKTRCTRL to SW_WKUP(2) */
756         prcm_write_4(CM_PER_PRUSS_CLKSTCTRL, 2);
757
758         /* Wait for the 200 MHz OCP clock to become active */
759         while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<4)) == 0)
760                 DELAY(10);
761
762         /* Wait for the 200 MHz IEP clock to become active */
763         while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<5)) == 0)
764                 DELAY(10);
765
766         /* Wait for the 192 MHz UART clock to become active */
767         while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<6)) == 0)
768                 DELAY(10);
769
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)
773                 DELAY(10);
774
775         /* Clear the RESET bit */
776         prcm_write_4(PRM_PER_RSTCTRL, prcm_read_4(PRM_PER_RSTCTRL) & ~2);
777
778         return (0);
779 }