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