]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/arm/freescale/imx/imx51_ccm.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / arm / freescale / imx / imx51_ccm.c
1 /*      $NetBSD: imx51_ccm.c,v 1.1 2012/04/17 09:33:31 bsh Exp $        */
2 /*
3  * Copyright (c) 2010, 2011, 2012  Genetec Corporation.  All rights reserved.
4  * Written by Hashimoto Kenichi for Genetec Corporation.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
19  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 /*-
29  * Copyright (c) 2012, 2013 The FreeBSD Foundation
30  * All rights reserved.
31  *
32  * Portions of this software were developed by Oleksandr Rybalko
33  * under sponsorship from the FreeBSD Foundation.
34  *
35  * Redistribution and use in source and binary forms, with or without
36  * modification, are permitted provided that the following conditions
37  * are met:
38  * 1.   Redistributions of source code must retain the above copyright
39  *      notice, this list of conditions and the following disclaimer.
40  * 2.   Redistributions in binary form must reproduce the above copyright
41  *      notice, this list of conditions and the following disclaimer in the
42  *      documentation and/or other materials provided with the distribution.
43  *
44  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
45  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
48  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54  * SUCH DAMAGE.
55  */
56
57 /*
58  * Clock Controller Module (CCM)
59  */
60
61 #include <sys/cdefs.h>
62 __FBSDID("$FreeBSD$");
63
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/bus.h>
67 #include <sys/kernel.h>
68 #include <sys/module.h>
69 #include <sys/malloc.h>
70 #include <sys/rman.h>
71 #include <machine/bus.h>
72 #include <machine/cpu.h>
73 #include <machine/intr.h>
74
75 #include <dev/fdt/fdt_common.h>
76 #include <dev/ofw/openfirm.h>
77 #include <dev/ofw/ofw_bus.h>
78 #include <dev/ofw/ofw_bus_subr.h>
79
80 #include <machine/bus.h>
81 #include <machine/fdt.h>
82
83 #include <arm/freescale/imx/imx51_ccmvar.h>
84 #include <arm/freescale/imx/imx51_ccmreg.h>
85 #include <arm/freescale/imx/imx51_dpllreg.h>
86 #include <arm/freescale/imx/imx_ccmvar.h>
87 #include <arm/freescale/imx/imx_machdep.h>
88
89 #define IMXCCMDEBUG
90 #undef  IMXCCMDEBUG
91
92 #ifndef IMX51_OSC_FREQ
93 #define IMX51_OSC_FREQ  (24 * 1000 * 1000)      /* 24MHz */
94 #endif
95
96 #ifndef IMX51_CKIL_FREQ
97 #define IMX51_CKIL_FREQ 32768
98 #endif
99
100 struct imxccm_softc {
101         device_t        sc_dev;
102         struct resource *res[7];
103         u_int64_t       pll_freq[IMX51_N_DPLLS];
104 };
105
106 struct imxccm_softc *ccm_softc = NULL;
107
108 static uint64_t imx51_get_pll_freq(u_int);
109
110 static int imxccm_match(device_t);
111 static int imxccm_attach(device_t);
112
113 static device_method_t imxccm_methods[] = {
114         DEVMETHOD(device_probe, imxccm_match),
115         DEVMETHOD(device_attach, imxccm_attach),
116
117         DEVMETHOD_END
118 };
119
120 static driver_t imxccm_driver = {
121         "imxccm",
122         imxccm_methods,
123         sizeof(struct imxccm_softc),
124 };
125
126 static devclass_t imxccm_devclass;
127
128 EARLY_DRIVER_MODULE(imxccm, simplebus, imxccm_driver, imxccm_devclass, 0, 0,
129     BUS_PASS_CPU);
130
131 static struct resource_spec imxccm_spec[] = {
132         { SYS_RES_MEMORY,       0,      RF_ACTIVE },    /* Global registers */
133         { SYS_RES_MEMORY,       1,      RF_ACTIVE },    /* DPLLIP1 */
134         { SYS_RES_MEMORY,       2,      RF_ACTIVE },    /* DPLLIP2 */
135         { SYS_RES_MEMORY,       3,      RF_ACTIVE },    /* DPLLIP3 */
136         { SYS_RES_IRQ,          0,      RF_ACTIVE },    /* 71 */
137         { SYS_RES_IRQ,          1,      RF_ACTIVE },    /* 72 */
138         { -1, 0 }
139 };
140
141 static int
142 imxccm_match(device_t dev)
143 {
144
145         if (!ofw_bus_status_okay(dev))
146                 return (ENXIO);
147
148         if (!ofw_bus_is_compatible(dev, "fsl,imx51-ccm") &&
149             !ofw_bus_is_compatible(dev, "fsl,imx53-ccm"))
150                 return (ENXIO);
151
152         device_set_desc(dev, "Freescale Clock Control Module");
153         return (BUS_PROBE_DEFAULT);
154 }
155
156 static int
157 imxccm_attach(device_t dev)
158 {
159         struct imxccm_softc *sc;
160
161         sc = device_get_softc(dev);
162         sc->sc_dev = dev;
163
164         if (bus_alloc_resources(dev, imxccm_spec, sc->res)) {
165                 device_printf(dev, "could not allocate resources\n");
166                 return (ENXIO);
167         }
168
169         ccm_softc = sc;
170
171         imx51_get_pll_freq(1);
172         imx51_get_pll_freq(2);
173         imx51_get_pll_freq(3);
174
175         device_printf(dev, "PLL1=%lluMHz, PLL2=%lluMHz, PLL3=%lluMHz\n",
176             sc->pll_freq[0] / 1000000,
177             sc->pll_freq[1] / 1000000,
178             sc->pll_freq[2] / 1000000);
179         device_printf(dev, "CPU clock=%d, UART clock=%d\n",
180             imx51_get_clock(IMX51CLK_ARM_ROOT),
181             imx51_get_clock(IMX51CLK_UART_CLK_ROOT));
182         device_printf(dev,
183             "mainbus clock=%d, ahb clock=%d ipg clock=%d perclk=%d\n",
184             imx51_get_clock(IMX51CLK_MAIN_BUS_CLK),
185             imx51_get_clock(IMX51CLK_AHB_CLK_ROOT),
186             imx51_get_clock(IMX51CLK_IPG_CLK_ROOT),
187             imx51_get_clock(IMX51CLK_PERCLK_ROOT));
188
189
190         return (0);
191 }
192
193 u_int
194 imx51_get_clock(enum imx51_clock clk)
195 {
196         u_int freq;
197         u_int sel;
198         uint32_t cacrr; /* ARM clock root register */
199         uint32_t ccsr;
200         uint32_t cscdr1;
201         uint32_t cscmr1;
202         uint32_t cbcdr;
203         uint32_t cbcmr;
204         uint32_t cdcr;
205
206         if (ccm_softc == NULL)
207                 return (0);
208
209         switch (clk) {
210         case IMX51CLK_PLL1:
211         case IMX51CLK_PLL2:
212         case IMX51CLK_PLL3:
213                 return ccm_softc->pll_freq[clk-IMX51CLK_PLL1];
214         case IMX51CLK_PLL1SW:
215                 ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
216                 if ((ccsr & CCSR_PLL1_SW_CLK_SEL) == 0)
217                         return ccm_softc->pll_freq[1-1];
218                 /* step clock */
219                 /* FALLTHROUGH */
220         case IMX51CLK_PLL1STEP:
221                 ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
222                 switch ((ccsr & CCSR_STEP_SEL_MASK) >> CCSR_STEP_SEL_SHIFT) {
223                 case 0:
224                         return imx51_get_clock(IMX51CLK_LP_APM);
225                 case 1:
226                         return 0; /* XXX PLL bypass clock */
227                 case 2:
228                         return ccm_softc->pll_freq[2-1] /
229                             (1 + ((ccsr & CCSR_PLL2_DIV_PODF_MASK) >>
230                                 CCSR_PLL2_DIV_PODF_SHIFT));
231                 case 3:
232                         return ccm_softc->pll_freq[3-1] /
233                             (1 + ((ccsr & CCSR_PLL3_DIV_PODF_MASK) >>
234                                 CCSR_PLL3_DIV_PODF_SHIFT));
235                 }
236                 /*NOTREACHED*/
237         case IMX51CLK_PLL2SW:
238                 ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
239                 if ((ccsr & CCSR_PLL2_SW_CLK_SEL) == 0)
240                         return imx51_get_clock(IMX51CLK_PLL2);
241                 return 0; /* XXX PLL2 bypass clk */
242         case IMX51CLK_PLL3SW:
243                 ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
244                 if ((ccsr & CCSR_PLL3_SW_CLK_SEL) == 0)
245                         return imx51_get_clock(IMX51CLK_PLL3);
246                 return 0; /* XXX PLL3 bypass clk */
247
248         case IMX51CLK_LP_APM:
249                 ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
250                 return (ccsr & CCSR_LP_APM) ?
251                             imx51_get_clock(IMX51CLK_FPM) : IMX51_OSC_FREQ;
252
253         case IMX51CLK_ARM_ROOT:
254                 freq = imx51_get_clock(IMX51CLK_PLL1SW);
255                 cacrr = bus_read_4(ccm_softc->res[0], CCMC_CACRR);
256                 return freq / (cacrr + 1);
257
258                 /* ... */
259         case IMX51CLK_MAIN_BUS_CLK_SRC:
260                 cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR);
261                 if ((cbcdr & CBCDR_PERIPH_CLK_SEL) == 0)
262                         freq = imx51_get_clock(IMX51CLK_PLL2SW);
263                 else {
264                         freq = 0;
265                         cbcmr = bus_read_4(ccm_softc->res[0],  CCMC_CBCMR);
266                         switch ((cbcmr & CBCMR_PERIPH_APM_SEL_MASK) >>
267                                 CBCMR_PERIPH_APM_SEL_SHIFT) {
268                         case 0:
269                                 freq = imx51_get_clock(IMX51CLK_PLL1SW);
270                                 break;
271                         case 1:
272                                 freq = imx51_get_clock(IMX51CLK_PLL3SW);
273                                 break;
274                         case 2:
275                                 freq = imx51_get_clock(IMX51CLK_LP_APM);
276                                 break;
277                         case 3:
278                                 /* XXX: error */
279                                 break;
280                         }
281                 }
282                 return freq;
283         case IMX51CLK_MAIN_BUS_CLK:
284                 freq = imx51_get_clock(IMX51CLK_MAIN_BUS_CLK_SRC);
285                 cdcr = bus_read_4(ccm_softc->res[0], CCMC_CDCR);
286                 return freq / (1 + ((cdcr & CDCR_PERIPH_CLK_DVFS_PODF_MASK) >>
287                         CDCR_PERIPH_CLK_DVFS_PODF_SHIFT));
288         case IMX51CLK_AHB_CLK_ROOT:
289                 freq = imx51_get_clock(IMX51CLK_MAIN_BUS_CLK);
290                 cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR);
291                 return freq / (1 + ((cbcdr & CBCDR_AHB_PODF_MASK) >>
292                                     CBCDR_AHB_PODF_SHIFT));
293         case IMX51CLK_IPG_CLK_ROOT:
294                 freq = imx51_get_clock(IMX51CLK_AHB_CLK_ROOT);
295                 cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR);
296                 return freq / (1 + ((cbcdr & CBCDR_IPG_PODF_MASK) >>
297                                     CBCDR_IPG_PODF_SHIFT));
298
299         case IMX51CLK_PERCLK_ROOT:
300                 cbcmr = bus_read_4(ccm_softc->res[0], CCMC_CBCMR);
301                 if (cbcmr & CBCMR_PERCLK_IPG_SEL)
302                         return imx51_get_clock(IMX51CLK_IPG_CLK_ROOT);
303                 if (cbcmr & CBCMR_PERCLK_LP_APM_SEL)
304                         freq = imx51_get_clock(IMX51CLK_LP_APM);
305                 else
306                         freq = imx51_get_clock(IMX51CLK_MAIN_BUS_CLK_SRC);
307                 cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR);
308
309 #ifdef IMXCCMDEBUG
310                 printf("cbcmr=%x cbcdr=%x\n", cbcmr, cbcdr);
311 #endif
312
313                 freq /= 1 + ((cbcdr & CBCDR_PERCLK_PRED1_MASK) >>
314                         CBCDR_PERCLK_PRED1_SHIFT);
315                 freq /= 1 + ((cbcdr & CBCDR_PERCLK_PRED2_MASK) >>
316                         CBCDR_PERCLK_PRED2_SHIFT);
317                 freq /= 1 + ((cbcdr & CBCDR_PERCLK_PODF_MASK) >>
318                         CBCDR_PERCLK_PODF_SHIFT);
319                 return freq;
320         case IMX51CLK_UART_CLK_ROOT:
321                 cscdr1 = bus_read_4(ccm_softc->res[0], CCMC_CSCDR1);
322                 cscmr1 = bus_read_4(ccm_softc->res[0], CCMC_CSCMR1);
323
324 #ifdef IMXCCMDEBUG
325                 printf("cscdr1=%x cscmr1=%x\n", cscdr1, cscmr1);
326 #endif
327
328                 sel = (cscmr1 & CSCMR1_UART_CLK_SEL_MASK) >>
329                     CSCMR1_UART_CLK_SEL_SHIFT;
330
331                 freq = 0; /* shut up GCC */
332                 switch (sel) {
333                 case 0:
334                 case 1:
335                 case 2:
336                         freq = imx51_get_clock(IMX51CLK_PLL1SW + sel);
337                         break;
338                 case 3:
339                         freq = imx51_get_clock(IMX51CLK_LP_APM);
340                         break;
341                 }
342
343                 return freq / (1 + ((cscdr1 & CSCDR1_UART_CLK_PRED_MASK) >>
344                         CSCDR1_UART_CLK_PRED_SHIFT)) /
345                     (1 + ((cscdr1 & CSCDR1_UART_CLK_PODF_MASK) >>
346                         CSCDR1_UART_CLK_PODF_SHIFT));
347         case IMX51CLK_IPU_HSP_CLK_ROOT:
348                 freq = 0;
349                 cbcmr = bus_read_4(ccm_softc->res[0],  CCMC_CBCMR);
350                 switch ((cbcmr & CBCMR_IPU_HSP_CLK_SEL_MASK) >>
351                                 CBCMR_IPU_HSP_CLK_SEL_SHIFT) {
352                         case 0:
353                                 freq = imx51_get_clock(IMX51CLK_ARM_AXI_A_CLK);
354                                 break;
355                         case 1:
356                                 freq = imx51_get_clock(IMX51CLK_ARM_AXI_B_CLK);
357                                 break;
358                         case 2:
359                                 freq = imx51_get_clock(
360                                         IMX51CLK_EMI_SLOW_CLK_ROOT);
361                                 break;
362                         case 3:
363                                 freq = imx51_get_clock(IMX51CLK_AHB_CLK_ROOT);
364                                 break;
365                         }
366                 return freq;
367         default:
368                 device_printf(ccm_softc->sc_dev,
369                     "clock %d: not supported yet\n", clk);
370                 return 0;
371         }
372 }
373
374
375 static uint64_t
376 imx51_get_pll_freq(u_int pll_no)
377 {
378         uint32_t dp_ctrl;
379         uint32_t dp_op;
380         uint32_t dp_mfd;
381         uint32_t dp_mfn;
382         uint32_t mfi;
383         int32_t mfn;
384         uint32_t mfd;
385         uint32_t pdf;
386         uint32_t ccr;
387         uint64_t freq = 0;
388         u_int ref = 0;
389
390         KASSERT(1 <= pll_no && pll_no <= IMX51_N_DPLLS, ("Wrong PLL id"));
391
392         dp_ctrl = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_CTL);
393
394         if (dp_ctrl & DP_CTL_HFSM) {
395                 dp_op = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_HFS_OP);
396                 dp_mfd = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_HFS_MFD);
397                 dp_mfn = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_HFS_MFN);
398         } else {
399                 dp_op = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_OP);
400                 dp_mfd = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_MFD);
401                 dp_mfn = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_MFN);
402         }
403
404         pdf = dp_op & DP_OP_PDF_MASK;
405         mfi = max(5, (dp_op & DP_OP_MFI_MASK) >> DP_OP_MFI_SHIFT);
406         mfd = dp_mfd;
407         if (dp_mfn & 0x04000000)
408                 /* 27bit signed value */
409                 mfn = (uint32_t)(0xf8000000 | dp_mfn);
410         else
411                 mfn = dp_mfn;
412
413         switch (dp_ctrl &  DP_CTL_REF_CLK_SEL_MASK) {
414         case DP_CTL_REF_CLK_SEL_COSC:
415                 /* Internal Oscillator */
416                 /* TODO: get from FDT "fsl,imx-osc" */
417                 ref = 24000000; /* IMX51_OSC_FREQ */
418                 break;
419         case DP_CTL_REF_CLK_SEL_FPM:
420                 ccr = bus_read_4(ccm_softc->res[0], CCMC_CCR);
421                 if (ccr & CCR_FPM_MULT)
422                 /* TODO: get from FDT "fsl,imx-ckil" */
423                         ref = 32768 * 1024;
424                 else
425                 /* TODO: get from FDT "fsl,imx-ckil" */
426                         ref = 32768 * 512;
427                 break;
428         default:
429                 ref = 0;
430         }
431
432         if (dp_ctrl & DP_CTL_REF_CLK_DIV)
433                 ref /= 2;
434
435         ref *= 4;
436         freq = (int64_t)ref * mfi + (int64_t)ref * mfn / (mfd + 1);
437         freq /= pdf + 1;
438
439         if (!(dp_ctrl & DP_CTL_DPDCK0_2_EN))
440                 freq /= 2;
441
442 #ifdef IMXCCMDEBUG
443         printf("ref: %dKHz ", ref);
444         printf("dp_ctl: %08x ", dp_ctrl);
445         printf("pdf: %3d ", pdf);
446         printf("mfi: %3d ", mfi);
447         printf("mfd: %3d ", mfd);
448         printf("mfn: %3d ", mfn);
449         printf("pll: %d\n", (uint32_t)freq);
450 #endif
451
452         ccm_softc->pll_freq[pll_no-1] = freq;
453
454         return (freq);
455 }
456
457 void
458 imx51_clk_gating(int clk_src, int mode)
459 {
460         int field, group;
461         uint32_t reg;
462
463         group = CCMR_CCGR_MODULE(clk_src);
464         field = clk_src % CCMR_CCGR_NSOURCE;
465         reg = bus_read_4(ccm_softc->res[0], CCMC_CCGR(group));
466         reg &= ~(0x03 << field * 2);
467         reg |= (mode << field * 2);
468         bus_write_4(ccm_softc->res[0], CCMC_CCGR(group), reg);
469 }
470
471 int
472 imx51_get_clk_gating(int clk_src)
473 {
474         uint32_t reg;
475
476         reg = bus_read_4(ccm_softc->res[0],
477             CCMC_CCGR(CCMR_CCGR_MODULE(clk_src)));
478         return ((reg >> (clk_src % CCMR_CCGR_NSOURCE) * 2) & 0x03);
479 }
480
481 /*
482  * Code from here down is temporary, in lieu of a SoC-independent clock API.
483  */
484
485 void
486 imx_ccm_usb_enable(device_t dev)
487 {
488         uint32_t regval;
489
490         /*
491          * Select PLL2 as the source for the USB clock.
492          * The default is PLL3, but U-boot changes it to PLL2.
493          */
494         regval = bus_read_4(ccm_softc->res[0], CCMC_CSCMR1);
495         regval &= ~CSCMR1_USBOH3_CLK_SEL_MASK;
496         regval |= 1 << CSCMR1_USBOH3_CLK_SEL_SHIFT;
497         bus_write_4(ccm_softc->res[0], CCMC_CSCMR1, regval);
498
499         /*
500          * Set the USB clock pre-divider to div-by-5, post-divider to div-by-2.
501          */
502         regval = bus_read_4(ccm_softc->res[0], CCMC_CSCDR1);
503         regval &= ~CSCDR1_USBOH3_CLK_PODF_MASK;
504         regval &= ~CSCDR1_USBOH3_CLK_PRED_MASK;
505         regval |= 4 << CSCDR1_USBOH3_CLK_PRED_SHIFT;
506         regval |= 1 << CSCDR1_USBOH3_CLK_PODF_SHIFT;
507         bus_write_4(ccm_softc->res[0], CCMC_CSCDR1, regval);
508
509         /*
510          * The same two clocks gates are used on imx51 and imx53.
511          */
512         imx51_clk_gating(CCGR_USBOH3_IPG_AHB_CLK, CCGR_CLK_MODE_ALWAYS);
513         imx51_clk_gating(CCGR_USBOH3_60M_CLK, CCGR_CLK_MODE_ALWAYS);
514 }
515
516 void
517 imx_ccm_usbphy_enable(device_t dev)
518 {
519         uint32_t regval;
520
521         /*
522          * Select PLL3 as the source for the USBPHY clock.  U-boot does this 
523          * only for imx53, but the bit exists on imx51.  That seems a bit
524          * strange, but we'll go with it until more is known.
525          */
526         if (imx_soc_type() == IMXSOC_53) {
527                 regval = bus_read_4(ccm_softc->res[0], CCMC_CSCMR1);
528                 regval |= 1 << CSCMR1_USBPHY_CLK_SEL_SHIFT;
529                 bus_write_4(ccm_softc->res[0], CCMC_CSCMR1, regval);
530         }
531
532         /*
533          * For the imx51 there's just one phy gate control, enable it.
534          */
535         if (imx_soc_type() == IMXSOC_51) {
536                 imx51_clk_gating(CCGR_USB_PHY_CLK, CCGR_CLK_MODE_ALWAYS);
537                 return;
538         }
539
540         /*
541          * For imx53 we don't have a full set of clock defines yet, but the
542          * datasheet says:
543          *   gate reg 4, bits 13-12 usb ph2 clock (usb_phy2_clk_enable)
544          *   gate reg 4, bits 11-10 usb ph1 clock (usb_phy1_clk_enable)
545          *
546          * We should use the fdt data for the device to figure out which of
547          * the two we're working on, but for now just turn them both on.
548          */
549         if (imx_soc_type() == IMXSOC_53) {
550                 imx51_clk_gating(__CCGR_NUM(4, 5), CCGR_CLK_MODE_ALWAYS);
551                 imx51_clk_gating(__CCGR_NUM(4, 6), CCGR_CLK_MODE_ALWAYS);
552                 return;
553         }
554 }
555
556 uint32_t
557 imx_ccm_ipg_hz(void)
558 {
559
560         return (imx51_get_clock(IMX51CLK_IPG_CLK_ROOT));
561 }
562
563 uint32_t
564 imx_ccm_sdhci_hz(void)
565 {
566
567         return (imx51_get_clock(IMX51CLK_ESDHC1_CLK_ROOT));
568 }
569
570 uint32_t
571 imx_ccm_perclk_hz(void)
572 {
573
574         return (imx51_get_clock(IMX51CLK_PERCLK_ROOT));
575 }
576
577 uint32_t
578 imx_ccm_uart_hz(void)
579 {
580
581         return (imx51_get_clock(IMX51CLK_UART_CLK_ROOT));
582 }
583
584 uint32_t
585 imx_ccm_ahb_hz(void)
586 {
587
588         return (imx51_get_clock(IMX51CLK_AHB_CLK_ROOT));
589 }