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