]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/arm/ti/am335x/am335x_prcm.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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/frame.h>
43 #include <machine/intr.h>
44
45 #include <arm/ti/tivar.h>
46 #include <arm/ti/ti_scm.h>
47 #include <arm/ti/ti_prcm.h>
48
49 #include <dev/fdt/fdt_common.h>
50 #include <dev/ofw/openfirm.h>
51 #include <dev/ofw/ofw_bus.h>
52 #include <dev/ofw/ofw_bus_subr.h>
53
54 #include <machine/bus.h>
55 #include <machine/fdt.h>
56
57 #define CM_PER                          0
58 #define CM_PER_L4LS_CLKSTCTRL           (CM_PER + 0x000)
59 #define CM_PER_L3S_CLKSTCTRL            (CM_PER + 0x004)
60 #define CM_PER_L3_CLKSTCTRL             (CM_PER + 0x00C)
61 #define CM_PER_CPGMAC0_CLKCTRL          (CM_PER + 0x014)
62 #define CM_PER_LCDC_CLKCTRL             (CM_PER + 0x018)
63 #define CM_PER_USB0_CLKCTRL             (CM_PER + 0x01C)
64 #define CM_PER_TPTC0_CLKCTRL            (CM_PER + 0x024)
65 #define CM_PER_UART5_CLKCTRL            (CM_PER + 0x038)
66 #define CM_PER_MMC0_CLKCTRL             (CM_PER + 0x03C)
67 #define CM_PER_I2C2_CLKCTRL             (CM_PER + 0x044)
68 #define CM_PER_I2C1_CLKCTRL             (CM_PER + 0x048)
69 #define CM_PER_UART1_CLKCTRL            (CM_PER + 0x06C)
70 #define CM_PER_UART2_CLKCTRL            (CM_PER + 0x070)
71 #define CM_PER_UART3_CLKCTRL            (CM_PER + 0x074)
72 #define CM_PER_UART4_CLKCTRL            (CM_PER + 0x078)
73 #define CM_PER_TIMER7_CLKCTRL           (CM_PER + 0x07C)
74 #define CM_PER_TIMER2_CLKCTRL           (CM_PER + 0x080)
75 #define CM_PER_TIMER3_CLKCTRL           (CM_PER + 0x084)
76 #define CM_PER_TIMER4_CLKCTRL           (CM_PER + 0x088)
77 #define CM_PER_GPIO1_CLKCTRL            (CM_PER + 0x0AC)
78 #define CM_PER_GPIO2_CLKCTRL            (CM_PER + 0x0B0)
79 #define CM_PER_GPIO3_CLKCTRL            (CM_PER + 0x0B4)
80 #define CM_PER_TPCC_CLKCTRL             (CM_PER + 0x0BC)
81 #define CM_PER_EPWMSS1_CLKCTRL          (CM_PER + 0x0CC)
82 #define CM_PER_EPWMSS0_CLKCTRL          (CM_PER + 0x0D4)
83 #define CM_PER_EPWMSS2_CLKCTRL          (CM_PER + 0x0D8)
84 #define CM_PER_L3_INSTR_CLKCTRL         (CM_PER + 0x0DC)
85 #define CM_PER_L3_CLKCTRL               (CM_PER + 0x0E0)
86 #define CM_PER_PRUSS_CLKCTRL            (CM_PER + 0x0E8)
87 #define CM_PER_TIMER5_CLKCTRL           (CM_PER + 0x0EC)
88 #define CM_PER_TIMER6_CLKCTRL           (CM_PER + 0x0F0)
89 #define CM_PER_MMC1_CLKCTRL             (CM_PER + 0x0F4)
90 #define CM_PER_MMC2_CLKCTRL             (CM_PER + 0x0F8)
91 #define CM_PER_TPTC1_CLKCTRL            (CM_PER + 0x0FC)
92 #define CM_PER_TPTC2_CLKCTRL            (CM_PER + 0x100)
93 #define CM_PER_SPINLOCK0_CLKCTRL        (CM_PER + 0x10C)
94 #define CM_PER_MAILBOX0_CLKCTRL         (CM_PER + 0x110)
95 #define CM_PER_OCPWP_L3_CLKSTCTRL       (CM_PER + 0x12C)
96 #define CM_PER_OCPWP_CLKCTRL            (CM_PER + 0x130)
97 #define CM_PER_CPSW_CLKSTCTRL           (CM_PER + 0x144)
98 #define CM_PER_PRUSS_CLKSTCTRL          (CM_PER + 0x140)
99
100 #define CM_WKUP                         0x400
101 #define CM_WKUP_CLKSTCTRL               (CM_WKUP + 0x000)
102 #define CM_WKUP_CONTROL_CLKCTRL         (CM_WKUP + 0x004)
103 #define CM_WKUP_GPIO0_CLKCTRL           (CM_WKUP + 0x008)
104 #define CM_WKUP_CM_L3_AON_CLKSTCTRL     (CM_WKUP + 0x01C)
105 #define CM_WKUP_CM_CLKSEL_DPLL_MPU      (CM_WKUP + 0x02C)
106 #define CM_WKUP_CM_IDLEST_DPLL_DISP     (CM_WKUP + 0x048)
107 #define CM_WKUP_CM_CLKSEL_DPLL_DISP     (CM_WKUP + 0x054)
108 #define CM_WKUP_CM_CLKDCOLDO_DPLL_PER   (CM_WKUP + 0x07C)
109 #define CM_WKUP_CM_CLKMODE_DPLL_DISP    (CM_WKUP + 0x098)
110 #define CM_WKUP_I2C0_CLKCTRL            (CM_WKUP + 0x0B8)
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
127 struct am335x_prcm_softc {
128         struct resource *       res[2];
129         bus_space_tag_t         bst;
130         bus_space_handle_t      bsh;
131 };
132
133 static struct resource_spec am335x_prcm_spec[] = {
134         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
135         { -1, 0 }
136 };
137
138 static struct am335x_prcm_softc *am335x_prcm_sc = NULL;
139
140 static int am335x_clk_noop_activate(struct ti_clock_dev *clkdev);
141 static int am335x_clk_generic_activate(struct ti_clock_dev *clkdev);
142 static int am335x_clk_gpio_activate(struct ti_clock_dev *clkdev);
143 static int am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev);
144 static int am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev);
145 static int am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
146 static int am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
147 static int am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev,  unsigned int *freq);
148 static int am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
149 static int am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
150 static int am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
151 static void am335x_prcm_reset(void);
152 static int am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev);
153 static int am335x_clk_musb0_activate(struct ti_clock_dev *clkdev);
154 static int am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev);
155 static 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
193 struct ti_clock_dev ti_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         /* EDMA */
265         AM335X_GENERIC_CLOCK_DEV(EDMA_TPCC_CLK),
266         AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC0_CLK),
267         AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC1_CLK),
268         AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC2_CLK),
269
270         /* MMCHS */
271         AM335X_MMCHS_CLOCK_DEV(MMC0_CLK),
272         AM335X_MMCHS_CLOCK_DEV(MMC1_CLK),
273         AM335X_MMCHS_CLOCK_DEV(MMC2_CLK),
274
275         /* PWMSS */
276         AM335X_GENERIC_CLOCK_DEV(PWMSS0_CLK),
277         AM335X_GENERIC_CLOCK_DEV(PWMSS1_CLK),
278         AM335X_GENERIC_CLOCK_DEV(PWMSS2_CLK),
279
280         /* System Mailbox clock */
281         AM335X_GENERIC_CLOCK_DEV(MAILBOX0_CLK),
282
283         /* SPINLOCK */
284         AM335X_GENERIC_CLOCK_DEV(SPINLOCK0_CLK),
285
286         /* PRU-ICSS */
287         {       .id                  = PRUSS_CLK,
288                 .clk_activate        = am335x_clk_pruss_activate,
289                 .clk_deactivate      = NULL,
290                 .clk_set_source      = NULL,
291                 .clk_accessible      = NULL,
292                 .clk_get_source_freq = NULL,
293         },
294
295
296
297         {  INVALID_CLK_IDENT, NULL, NULL, NULL, NULL }
298 };
299
300 struct am335x_clk_details {
301         clk_ident_t     id;
302         uint32_t        clkctrl_reg;
303         uint32_t        clksel_reg;
304 };
305
306 #define _CLK_DETAIL(i, c, s) \
307         {       .id = (i), \
308                 .clkctrl_reg = (c), \
309                 .clksel_reg = (s), \
310         }
311
312 static struct am335x_clk_details g_am335x_clk_details[] = {
313
314         /* UART. UART0 clock not controllable. */
315         _CLK_DETAIL(UART0_CLK, 0, 0),
316         _CLK_DETAIL(UART1_CLK, CM_PER_UART1_CLKCTRL, 0),
317         _CLK_DETAIL(UART2_CLK, CM_PER_UART2_CLKCTRL, 0),
318         _CLK_DETAIL(UART3_CLK, CM_PER_UART3_CLKCTRL, 0),
319         _CLK_DETAIL(UART4_CLK, CM_PER_UART4_CLKCTRL, 0),
320         _CLK_DETAIL(UART5_CLK, CM_PER_UART5_CLKCTRL, 0),
321
322         /* DMTimer modules */
323         _CLK_DETAIL(DMTIMER2_CLK, CM_PER_TIMER2_CLKCTRL, CLKSEL_TIMER2_CLK),
324         _CLK_DETAIL(DMTIMER3_CLK, CM_PER_TIMER3_CLKCTRL, CLKSEL_TIMER3_CLK),
325         _CLK_DETAIL(DMTIMER4_CLK, CM_PER_TIMER4_CLKCTRL, CLKSEL_TIMER4_CLK),
326         _CLK_DETAIL(DMTIMER5_CLK, CM_PER_TIMER5_CLKCTRL, CLKSEL_TIMER5_CLK),
327         _CLK_DETAIL(DMTIMER6_CLK, CM_PER_TIMER6_CLKCTRL, CLKSEL_TIMER6_CLK),
328         _CLK_DETAIL(DMTIMER7_CLK, CM_PER_TIMER7_CLKCTRL, CLKSEL_TIMER7_CLK),
329
330         /* GPIO modules */
331         _CLK_DETAIL(GPIO0_CLK, CM_WKUP_GPIO0_CLKCTRL, 0),
332         _CLK_DETAIL(GPIO1_CLK, CM_PER_GPIO1_CLKCTRL, 0),
333         _CLK_DETAIL(GPIO2_CLK, CM_PER_GPIO2_CLKCTRL, 0),
334         _CLK_DETAIL(GPIO3_CLK, CM_PER_GPIO3_CLKCTRL, 0),
335
336         /* I2C modules */
337         _CLK_DETAIL(I2C0_CLK, CM_WKUP_I2C0_CLKCTRL, 0),
338         _CLK_DETAIL(I2C1_CLK, CM_PER_I2C1_CLKCTRL, 0),
339         _CLK_DETAIL(I2C2_CLK, CM_PER_I2C2_CLKCTRL, 0),
340
341         /* EDMA modules */
342         _CLK_DETAIL(EDMA_TPCC_CLK, CM_PER_TPCC_CLKCTRL, 0),
343         _CLK_DETAIL(EDMA_TPTC0_CLK, CM_PER_TPTC0_CLKCTRL, 0),
344         _CLK_DETAIL(EDMA_TPTC1_CLK, CM_PER_TPTC1_CLKCTRL, 0),
345         _CLK_DETAIL(EDMA_TPTC2_CLK, CM_PER_TPTC2_CLKCTRL, 0),
346
347         /* MMCHS modules*/
348         _CLK_DETAIL(MMC0_CLK, CM_PER_MMC0_CLKCTRL, 0),
349         _CLK_DETAIL(MMC1_CLK, CM_PER_MMC1_CLKCTRL, 0),
350         _CLK_DETAIL(MMC2_CLK, CM_PER_MMC1_CLKCTRL, 0),
351
352         /* PWMSS modules */
353         _CLK_DETAIL(PWMSS0_CLK, CM_PER_EPWMSS0_CLKCTRL, 0),
354         _CLK_DETAIL(PWMSS1_CLK, CM_PER_EPWMSS1_CLKCTRL, 0),
355         _CLK_DETAIL(PWMSS2_CLK, CM_PER_EPWMSS2_CLKCTRL, 0),
356
357         _CLK_DETAIL(MAILBOX0_CLK, CM_PER_MAILBOX0_CLKCTRL, 0),
358         _CLK_DETAIL(SPINLOCK0_CLK, CM_PER_SPINLOCK0_CLKCTRL, 0),
359
360         { INVALID_CLK_IDENT, 0},
361 };
362
363 /* Read/Write macros */
364 #define prcm_read_4(reg)                \
365         bus_space_read_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg)
366 #define prcm_write_4(reg, val)          \
367         bus_space_write_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg, val)
368
369 void am335x_prcm_setup_dmtimer(int);
370
371 static int
372 am335x_prcm_probe(device_t dev)
373 {
374         if (ofw_bus_is_compatible(dev, "am335x,prcm")) {
375                 device_set_desc(dev, "AM335x Power and Clock Management");
376                 return(BUS_PROBE_DEFAULT);
377         }
378
379         return (ENXIO);
380 }
381
382 static int
383 am335x_prcm_attach(device_t dev)
384 {
385         struct am335x_prcm_softc *sc = device_get_softc(dev);
386         unsigned int sysclk, fclk;
387
388         if (am335x_prcm_sc)
389                 return (ENXIO);
390
391         if (bus_alloc_resources(dev, am335x_prcm_spec, sc->res)) {
392                 device_printf(dev, "could not allocate resources\n");
393                 return (ENXIO);
394         }
395
396         sc->bst = rman_get_bustag(sc->res[0]);
397         sc->bsh = rman_get_bushandle(sc->res[0]);
398
399         am335x_prcm_sc = sc;
400         ti_cpu_reset = am335x_prcm_reset;
401
402         am335x_clk_get_sysclk_freq(NULL, &sysclk);
403         am335x_clk_get_arm_fclk_freq(NULL, &fclk);
404         device_printf(dev, "Clocks: System %u.%01u MHz, CPU %u MHz\n",
405                 sysclk/1000000, (sysclk % 1000000)/100000, fclk/1000000);
406
407         return (0);
408 }
409
410 static device_method_t am335x_prcm_methods[] = {
411         DEVMETHOD(device_probe,         am335x_prcm_probe),
412         DEVMETHOD(device_attach,        am335x_prcm_attach),
413         { 0, 0 }
414 };
415
416 static driver_t am335x_prcm_driver = {
417         "am335x_prcm",
418         am335x_prcm_methods,
419         sizeof(struct am335x_prcm_softc),
420 };
421
422 static devclass_t am335x_prcm_devclass;
423
424 DRIVER_MODULE(am335x_prcm, simplebus, am335x_prcm_driver,
425         am335x_prcm_devclass, 0, 0);
426 MODULE_DEPEND(am335x_prcm, ti_scm, 1, 1, 1);
427
428 static struct am335x_clk_details*
429 am335x_clk_details(clk_ident_t id)
430 {
431         struct am335x_clk_details *walker;
432
433         for (walker = g_am335x_clk_details; walker->id != INVALID_CLK_IDENT; walker++) {
434                 if (id == walker->id)
435                         return (walker);
436         }
437
438         return NULL;
439 }
440
441 static int
442 am335x_clk_noop_activate(struct ti_clock_dev *clkdev)
443 {
444
445         return (0);
446 }
447
448 static int
449 am335x_clk_generic_activate(struct ti_clock_dev *clkdev)
450 {
451         struct am335x_prcm_softc *sc = am335x_prcm_sc;
452         struct am335x_clk_details* clk_details;
453
454         if (sc == NULL)
455                 return ENXIO;
456
457         clk_details = am335x_clk_details(clkdev->id);
458
459         if (clk_details == NULL)
460                 return (ENXIO);
461
462         /* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
463         prcm_write_4(clk_details->clkctrl_reg, 2);
464         while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 2)
465                 DELAY(10);
466
467         return (0);
468 }
469
470 static int
471 am335x_clk_gpio_activate(struct ti_clock_dev *clkdev)
472 {
473         struct am335x_prcm_softc *sc = am335x_prcm_sc;
474         struct am335x_clk_details* clk_details;
475
476         if (sc == NULL)
477                 return ENXIO;
478
479         clk_details = am335x_clk_details(clkdev->id);
480
481         if (clk_details == NULL)
482                 return (ENXIO);
483
484         /* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
485         /* set *_CLKCTRL register OPTFCLKEN_GPIO_1_G DBCLK[18] to FCLK_EN(1) */
486         prcm_write_4(clk_details->clkctrl_reg, 2 | (1 << 18));
487         while ((prcm_read_4(clk_details->clkctrl_reg) & 
488             (3 | (1 << 18) )) != (2 | (1 << 18)))
489                 DELAY(10);
490
491         return (0);
492 }
493
494 static int
495 am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev)
496 {
497
498         return(0);
499 }
500
501 static int
502 am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev)
503 {
504         struct am335x_prcm_softc *sc = am335x_prcm_sc;
505         struct am335x_clk_details* clk_details;
506
507         if (sc == NULL)
508                 return ENXIO;
509
510         clk_details = am335x_clk_details(clkdev->id);
511
512         if (clk_details == NULL)
513                 return (ENXIO);
514
515         /* set *_CLKCTRL register MODULEMODE[1:0] to disable(0) */
516         prcm_write_4(clk_details->clkctrl_reg, 0);
517         while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 0)
518                 DELAY(10);
519
520         return (0);
521 }
522
523 static int
524 am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
525 {
526
527         return (0);
528 }
529
530 static int
531 am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
532 {
533         struct am335x_prcm_softc *sc = am335x_prcm_sc;
534         struct am335x_clk_details* clk_details;
535         uint32_t reg;
536
537         if (sc == NULL)
538                 return ENXIO;
539
540         clk_details = am335x_clk_details(clkdev->id);
541
542         if (clk_details == NULL)
543                 return (ENXIO);
544
545         switch (clksrc) {
546                 case EXT_CLK:
547                         reg = 0; /* SEL2: TCLKIN clock */
548                         break;
549                 case SYSCLK_CLK:
550                         reg = 1; /* SEL1: CLK_M_OSC clock */
551                         break;
552                 case F32KHZ_CLK:
553                         reg = 2; /* SEL3: CLK_32KHZ clock */
554                         break;
555                 default:
556                         return (ENXIO);
557         }
558
559         prcm_write_4(clk_details->clksel_reg, reg);
560         while ((prcm_read_4(clk_details->clksel_reg) & 0x3) != reg)
561                 DELAY(10);
562
563         return (0);
564 }
565
566 static int
567 am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev,  unsigned int *freq)
568 {
569         *freq = 96000000;
570         return (0);
571 }
572
573 static int
574 am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
575 {
576         uint32_t ctrl_status;
577
578         /* Read the input clock freq from the control module */
579         /* control_status reg (0x40) */
580         if (ti_scm_reg_read_4(0x40, &ctrl_status))
581                 return ENXIO;
582
583         switch ((ctrl_status>>22) & 0x3) {
584         case 0x0:
585                 /* 19.2Mhz */
586                 *freq = 19200000;
587                 break;
588         case 0x1:
589                 /* 24Mhz */
590                 *freq = 24000000;
591                 break;
592         case 0x2:
593                 /* 25Mhz */
594                 *freq = 25000000;
595                 break;
596         case 0x3:
597                 /* 26Mhz */
598                 *freq = 26000000;
599                 break;
600         }
601
602         return (0);
603 }
604
605 #define DPLL_BYP_CLKSEL(reg)    ((reg>>23) & 1)
606 #define DPLL_DIV(reg)           ((reg & 0x7f)+1)
607 #define DPLL_MULT(reg)          ((reg>>8) & 0x7FF)
608
609 static int
610 am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
611 {
612         uint32_t reg;
613         uint32_t sysclk;
614
615         reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_MPU);
616
617         /*Check if we are running in bypass */
618         if (DPLL_BYP_CLKSEL(reg))
619                 return ENXIO;
620
621         am335x_clk_get_sysclk_freq(NULL, &sysclk);
622         *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
623         return(0);
624 }
625
626 static int
627 am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
628 {
629         uint32_t reg;
630         uint32_t sysclk;
631
632         reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_DISP);
633
634         /*Check if we are running in bypass */
635         if (DPLL_BYP_CLKSEL(reg))
636                 return ENXIO;
637
638         am335x_clk_get_sysclk_freq(NULL, &sysclk);
639         *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
640         return(0);
641 }
642
643 static void
644 am335x_prcm_reset(void)
645 {
646         prcm_write_4(PRM_RSTCTRL, (1<<1));
647 }
648
649 static int
650 am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev)
651 {
652         struct am335x_prcm_softc *sc = am335x_prcm_sc;
653
654         if (sc == NULL)
655                 return ENXIO;
656
657         /* set MODULENAME to ENABLE */
658         prcm_write_4(CM_PER_CPGMAC0_CLKCTRL, 2);
659
660         /* wait for IDLEST to become Func(0) */
661         while(prcm_read_4(CM_PER_CPGMAC0_CLKCTRL) & (3<<16));
662
663         /*set CLKTRCTRL to SW_WKUP(2) */
664         prcm_write_4(CM_PER_CPSW_CLKSTCTRL, 2);
665
666         /* wait for 125 MHz OCP clock to become active */
667         while((prcm_read_4(CM_PER_CPSW_CLKSTCTRL) & (1<<4)) == 0);
668         return(0);
669 }
670
671 static int
672 am335x_clk_musb0_activate(struct ti_clock_dev *clkdev)
673 {
674         struct am335x_prcm_softc *sc = am335x_prcm_sc;
675
676         if (sc == NULL)
677                 return ENXIO;
678
679         /* set ST_DPLL_CLKDCOLDO(9) to CLK_GATED(1) */
680         /* set DPLL_CLKDCOLDO_GATE_CTRL(8) to CLK_ENABLE(1)*/
681         prcm_write_4(CM_WKUP_CM_CLKDCOLDO_DPLL_PER, 0x300);
682
683         /*set MODULEMODE to ENABLE(2) */
684         prcm_write_4(CM_PER_USB0_CLKCTRL, 2);
685
686         /* wait for MODULEMODE to become ENABLE(2) */
687         while ((prcm_read_4(CM_PER_USB0_CLKCTRL) & 0x3) != 2)
688                 DELAY(10);
689
690         /* wait for IDLEST to become Func(0) */
691         while(prcm_read_4(CM_PER_USB0_CLKCTRL) & (3<<16))
692                 DELAY(10);
693
694         return(0);
695 }
696
697 static int
698 am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev)
699 {
700         struct am335x_prcm_softc *sc = am335x_prcm_sc;
701
702         if (sc == NULL)
703                 return (ENXIO);
704
705         /* Bypass mode */
706         prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x4);
707
708         /* Make sure it's in bypass mode */
709         while (!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP) 
710             & (1 << 8)))
711                 DELAY(10);
712
713         /* 
714          * For now set frequency to  5xSYSFREQ 
715          * More flexible control might be required
716          */
717         prcm_write_4(CM_WKUP_CM_CLKSEL_DPLL_DISP, (5 << 8) | 0);
718
719         /* Locked mode */
720         prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7);
721
722         int timeout = 10000;
723         while ((!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP) 
724             & (1 << 0))) && timeout--)
725                 DELAY(10);
726
727         /*set MODULEMODE to ENABLE(2) */
728         prcm_write_4(CM_PER_LCDC_CLKCTRL, 2);
729
730         /* wait for MODULEMODE to become ENABLE(2) */
731         while ((prcm_read_4(CM_PER_LCDC_CLKCTRL) & 0x3) != 2)
732                 DELAY(10);
733
734         /* wait for IDLEST to become Func(0) */
735         while(prcm_read_4(CM_PER_LCDC_CLKCTRL) & (3<<16))
736                 DELAY(10);
737
738         return (0);
739 }
740
741 static int
742 am335x_clk_pruss_activate(struct ti_clock_dev *clkdev)
743 {
744         struct am335x_prcm_softc *sc = am335x_prcm_sc;
745
746         if (sc == NULL)
747                 return (ENXIO);
748
749         /* Set MODULEMODE to ENABLE(2) */
750         prcm_write_4(CM_PER_PRUSS_CLKCTRL, 2);
751
752         /* Wait for MODULEMODE to become ENABLE(2) */
753         while ((prcm_read_4(CM_PER_PRUSS_CLKCTRL) & 0x3) != 2)
754                 DELAY(10);
755
756         /* Set CLKTRCTRL to SW_WKUP(2) */
757         prcm_write_4(CM_PER_PRUSS_CLKSTCTRL, 2);
758
759         /* Wait for the 200 MHz OCP clock to become active */
760         while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<4)) == 0)
761                 DELAY(10);
762
763         /* Wait for the 200 MHz IEP clock to become active */
764         while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<5)) == 0)
765                 DELAY(10);
766
767         /* Wait for the 192 MHz UART clock to become active */
768         while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<6)) == 0)
769                 DELAY(10);
770
771         /* Select DISP DPLL as OCP clock */
772         prcm_write_4(CLKSEL_PRUSS_OCP_CLK, 1);
773         while ((prcm_read_4(CLKSEL_PRUSS_OCP_CLK) & 0x3) != 1)
774                 DELAY(10);
775
776         /* Clear the RESET bit */
777         prcm_write_4(PRM_PER_RSTCTRL, prcm_read_4(PRM_PER_RSTCTRL) & ~2);
778
779         return (0);
780 }