xref: /freebsd-12.1/sys/arm/freescale/imx/imx51_ccm.c (revision a0fd2339)
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 
253 	return (0);
254 
255 noclocks:
256 
257 	panic("Cannot continue without clock support");
258 }
259 
260 u_int
imx51_get_clock(enum imx51_clock clk)261 imx51_get_clock(enum imx51_clock clk)
262 {
263 	u_int freq;
264 	u_int sel;
265 	uint32_t cacrr;	/* ARM clock root register */
266 	uint32_t ccsr;
267 	uint32_t cscdr1;
268 	uint32_t cscmr1;
269 	uint32_t cbcdr;
270 	uint32_t cbcmr;
271 	uint32_t cdcr;
272 
273 	if (ccm_softc == NULL)
274 		return (0);
275 
276 	switch (clk) {
277 	case IMX51CLK_PLL1:
278 	case IMX51CLK_PLL2:
279 	case IMX51CLK_PLL3:
280 		return ccm_softc->pll_freq[clk-IMX51CLK_PLL1];
281 	case IMX51CLK_PLL1SW:
282 		ccsr = ccm_read_4(ccm_softc, CCMC_CCSR);
283 		if ((ccsr & CCSR_PLL1_SW_CLK_SEL) == 0)
284 			return ccm_softc->pll_freq[1-1];
285 		/* step clock */
286 		/* FALLTHROUGH */
287 	case IMX51CLK_PLL1STEP:
288 		ccsr = ccm_read_4(ccm_softc, CCMC_CCSR);
289 		switch ((ccsr & CCSR_STEP_SEL_MASK) >> CCSR_STEP_SEL_SHIFT) {
290 		case 0:
291 			return imx51_get_clock(IMX51CLK_LP_APM);
292 		case 1:
293 			return 0; /* XXX PLL bypass clock */
294 		case 2:
295 			return ccm_softc->pll_freq[2-1] /
296 			    (1 + ((ccsr & CCSR_PLL2_DIV_PODF_MASK) >>
297 				CCSR_PLL2_DIV_PODF_SHIFT));
298 		case 3:
299 			return ccm_softc->pll_freq[3-1] /
300 			    (1 + ((ccsr & CCSR_PLL3_DIV_PODF_MASK) >>
301 				CCSR_PLL3_DIV_PODF_SHIFT));
302 		}
303 		/*NOTREACHED*/
304 	case IMX51CLK_PLL2SW:
305 		ccsr = ccm_read_4(ccm_softc, CCMC_CCSR);
306 		if ((ccsr & CCSR_PLL2_SW_CLK_SEL) == 0)
307 			return imx51_get_clock(IMX51CLK_PLL2);
308 		return 0; /* XXX PLL2 bypass clk */
309 	case IMX51CLK_PLL3SW:
310 		ccsr = ccm_read_4(ccm_softc, CCMC_CCSR);
311 		if ((ccsr & CCSR_PLL3_SW_CLK_SEL) == 0)
312 			return imx51_get_clock(IMX51CLK_PLL3);
313 		return 0; /* XXX PLL3 bypass clk */
314 
315 	case IMX51CLK_LP_APM:
316 		ccsr = ccm_read_4(ccm_softc, CCMC_CCSR);
317 		return (ccsr & CCSR_LP_APM) ?
318 			    imx51_get_clock(IMX51CLK_FPM) : IMX51_OSC_FREQ;
319 
320 	case IMX51CLK_ARM_ROOT:
321 		freq = imx51_get_clock(IMX51CLK_PLL1SW);
322 		cacrr = ccm_read_4(ccm_softc, CCMC_CACRR);
323 		return freq / (cacrr + 1);
324 
325 		/* ... */
326 	case IMX51CLK_MAIN_BUS_CLK_SRC:
327 		cbcdr = ccm_read_4(ccm_softc, CCMC_CBCDR);
328 		if ((cbcdr & CBCDR_PERIPH_CLK_SEL) == 0)
329 			freq = imx51_get_clock(IMX51CLK_PLL2SW);
330 		else {
331 			freq = 0;
332 			cbcmr = ccm_read_4(ccm_softc,  CCMC_CBCMR);
333 			switch ((cbcmr & CBCMR_PERIPH_APM_SEL_MASK) >>
334 				CBCMR_PERIPH_APM_SEL_SHIFT) {
335 			case 0:
336 				freq = imx51_get_clock(IMX51CLK_PLL1SW);
337 				break;
338 			case 1:
339 				freq = imx51_get_clock(IMX51CLK_PLL3SW);
340 				break;
341 			case 2:
342 				freq = imx51_get_clock(IMX51CLK_LP_APM);
343 				break;
344 			case 3:
345 				/* XXX: error */
346 				break;
347 			}
348 		}
349 		return freq;
350 	case IMX51CLK_MAIN_BUS_CLK:
351 		freq = imx51_get_clock(IMX51CLK_MAIN_BUS_CLK_SRC);
352 		cdcr = ccm_read_4(ccm_softc, CCMC_CDCR);
353 		return freq / (1 + ((cdcr & CDCR_PERIPH_CLK_DVFS_PODF_MASK) >>
354 			CDCR_PERIPH_CLK_DVFS_PODF_SHIFT));
355 	case IMX51CLK_AHB_CLK_ROOT:
356 		freq = imx51_get_clock(IMX51CLK_MAIN_BUS_CLK);
357 		cbcdr = ccm_read_4(ccm_softc, CCMC_CBCDR);
358 		return freq / (1 + ((cbcdr & CBCDR_AHB_PODF_MASK) >>
359 				    CBCDR_AHB_PODF_SHIFT));
360 	case IMX51CLK_IPG_CLK_ROOT:
361 		freq = imx51_get_clock(IMX51CLK_AHB_CLK_ROOT);
362 		cbcdr = ccm_read_4(ccm_softc, CCMC_CBCDR);
363 		return freq / (1 + ((cbcdr & CBCDR_IPG_PODF_MASK) >>
364 				    CBCDR_IPG_PODF_SHIFT));
365 
366 	case IMX51CLK_PERCLK_ROOT:
367 		cbcmr = ccm_read_4(ccm_softc, CCMC_CBCMR);
368 		if (cbcmr & CBCMR_PERCLK_IPG_SEL)
369 			return imx51_get_clock(IMX51CLK_IPG_CLK_ROOT);
370 		if (cbcmr & CBCMR_PERCLK_LP_APM_SEL)
371 			freq = imx51_get_clock(IMX51CLK_LP_APM);
372 		else
373 			freq = imx51_get_clock(IMX51CLK_MAIN_BUS_CLK_SRC);
374 		cbcdr = ccm_read_4(ccm_softc, CCMC_CBCDR);
375 
376 #ifdef IMXCCMDEBUG
377 		printf("cbcmr=%x cbcdr=%x\n", cbcmr, cbcdr);
378 #endif
379 
380 		freq /= 1 + ((cbcdr & CBCDR_PERCLK_PRED1_MASK) >>
381 			CBCDR_PERCLK_PRED1_SHIFT);
382 		freq /= 1 + ((cbcdr & CBCDR_PERCLK_PRED2_MASK) >>
383 			CBCDR_PERCLK_PRED2_SHIFT);
384 		freq /= 1 + ((cbcdr & CBCDR_PERCLK_PODF_MASK) >>
385 			CBCDR_PERCLK_PODF_SHIFT);
386 		return freq;
387 	case IMX51CLK_UART_CLK_ROOT:
388 		cscdr1 = ccm_read_4(ccm_softc, CCMC_CSCDR1);
389 		cscmr1 = ccm_read_4(ccm_softc, CCMC_CSCMR1);
390 
391 #ifdef IMXCCMDEBUG
392 		printf("cscdr1=%x cscmr1=%x\n", cscdr1, cscmr1);
393 #endif
394 
395 		sel = (cscmr1 & CSCMR1_UART_CLK_SEL_MASK) >>
396 		    CSCMR1_UART_CLK_SEL_SHIFT;
397 
398 		freq = 0; /* shut up GCC */
399 		switch (sel) {
400 		case 0:
401 		case 1:
402 		case 2:
403 			freq = imx51_get_clock(IMX51CLK_PLL1SW + sel);
404 			break;
405 		case 3:
406 			freq = imx51_get_clock(IMX51CLK_LP_APM);
407 			break;
408 		}
409 
410 		return freq / (1 + ((cscdr1 & CSCDR1_UART_CLK_PRED_MASK) >>
411 			CSCDR1_UART_CLK_PRED_SHIFT)) /
412 		    (1 + ((cscdr1 & CSCDR1_UART_CLK_PODF_MASK) >>
413 			CSCDR1_UART_CLK_PODF_SHIFT));
414 	case IMX51CLK_IPU_HSP_CLK_ROOT:
415 		freq = 0;
416 		cbcmr = ccm_read_4(ccm_softc,  CCMC_CBCMR);
417 		switch ((cbcmr & CBCMR_IPU_HSP_CLK_SEL_MASK) >>
418 				CBCMR_IPU_HSP_CLK_SEL_SHIFT) {
419 			case 0:
420 				freq = imx51_get_clock(IMX51CLK_ARM_AXI_A_CLK);
421 				break;
422 			case 1:
423 				freq = imx51_get_clock(IMX51CLK_ARM_AXI_B_CLK);
424 				break;
425 			case 2:
426 				freq = imx51_get_clock(
427 					IMX51CLK_EMI_SLOW_CLK_ROOT);
428 				break;
429 			case 3:
430 				freq = imx51_get_clock(IMX51CLK_AHB_CLK_ROOT);
431 				break;
432 			}
433 		return freq;
434 	default:
435 		device_printf(ccm_softc->sc_dev,
436 		    "clock %d: not supported yet\n", clk);
437 		return 0;
438 	}
439 }
440 
441 
442 static uint64_t
imx51_get_pll_freq(u_int pll_no)443 imx51_get_pll_freq(u_int pll_no)
444 {
445 	uint32_t dp_ctrl;
446 	uint32_t dp_op;
447 	uint32_t dp_mfd;
448 	uint32_t dp_mfn;
449 	uint32_t mfi;
450 	int32_t mfn;
451 	uint32_t mfd;
452 	uint32_t pdf;
453 	uint32_t ccr;
454 	uint64_t freq = 0;
455 	u_int ref = 0;
456 
457 	KASSERT(1 <= pll_no && pll_no <= IMX51_N_DPLLS, ("Wrong PLL id"));
458 
459 	dp_ctrl = pll_read_4(ccm_softc, pll_no, DPLL_DP_CTL);
460 
461 	if (dp_ctrl & DP_CTL_HFSM) {
462 		dp_op  = pll_read_4(ccm_softc, pll_no, DPLL_DP_HFS_OP);
463 		dp_mfd = pll_read_4(ccm_softc, pll_no, DPLL_DP_HFS_MFD);
464 		dp_mfn = pll_read_4(ccm_softc, pll_no, DPLL_DP_HFS_MFN);
465 	} else {
466 		dp_op  = pll_read_4(ccm_softc, pll_no, DPLL_DP_OP);
467 		dp_mfd = pll_read_4(ccm_softc, pll_no, DPLL_DP_MFD);
468 		dp_mfn = pll_read_4(ccm_softc, pll_no, DPLL_DP_MFN);
469 	}
470 
471 	pdf = dp_op & DP_OP_PDF_MASK;
472 	mfi = max(5, (dp_op & DP_OP_MFI_MASK) >> DP_OP_MFI_SHIFT);
473 	mfd = dp_mfd;
474 	if (dp_mfn & 0x04000000)
475 		/* 27bit signed value */
476 		mfn = (uint32_t)(0xf8000000 | dp_mfn);
477 	else
478 		mfn = dp_mfn;
479 
480 	switch (dp_ctrl &  DP_CTL_REF_CLK_SEL_MASK) {
481 	case DP_CTL_REF_CLK_SEL_COSC:
482 		/* Internal Oscillator */
483 		/* TODO: get from FDT "fsl,imx-osc" */
484 		ref = 24000000; /* IMX51_OSC_FREQ */
485 		break;
486 	case DP_CTL_REF_CLK_SEL_FPM:
487 		ccr = ccm_read_4(ccm_softc, CCMC_CCR);
488 		if (ccr & CCR_FPM_MULT)
489 		/* TODO: get from FDT "fsl,imx-ckil" */
490 			ref = 32768 * 1024;
491 		else
492 		/* TODO: get from FDT "fsl,imx-ckil" */
493 			ref = 32768 * 512;
494 		break;
495 	default:
496 		ref = 0;
497 	}
498 
499 	if (dp_ctrl & DP_CTL_REF_CLK_DIV)
500 		ref /= 2;
501 
502 	ref *= 4;
503 	freq = (int64_t)ref * mfi + (int64_t)ref * mfn / (mfd + 1);
504 	freq /= pdf + 1;
505 
506 	if (!(dp_ctrl & DP_CTL_DPDCK0_2_EN))
507 		freq /= 2;
508 
509 #ifdef IMXCCMDEBUG
510 	printf("ref: %dKHz ", ref);
511 	printf("dp_ctl: %08x ", dp_ctrl);
512 	printf("pdf: %3d ", pdf);
513 	printf("mfi: %3d ", mfi);
514 	printf("mfd: %3d ", mfd);
515 	printf("mfn: %3d ", mfn);
516 	printf("pll: %d\n", (uint32_t)freq);
517 #endif
518 
519 	ccm_softc->pll_freq[pll_no-1] = freq;
520 
521 	return (freq);
522 }
523 
524 void
imx51_clk_gating(int clk_src,int mode)525 imx51_clk_gating(int clk_src, int mode)
526 {
527 	int field, group;
528 	uint32_t reg;
529 
530 	group = CCMR_CCGR_MODULE(clk_src);
531 	field = clk_src % CCMR_CCGR_NSOURCE;
532 	reg = ccm_read_4(ccm_softc, CCMC_CCGR(group));
533 	reg &= ~(0x03 << field * 2);
534 	reg |= (mode << field * 2);
535 	ccm_write_4(ccm_softc, CCMC_CCGR(group), reg);
536 }
537 
538 int
imx51_get_clk_gating(int clk_src)539 imx51_get_clk_gating(int clk_src)
540 {
541 	uint32_t reg;
542 
543 	reg = ccm_read_4(ccm_softc,
544 	    CCMC_CCGR(CCMR_CCGR_MODULE(clk_src)));
545 	return ((reg >> (clk_src % CCMR_CCGR_NSOURCE) * 2) & 0x03);
546 }
547 
548 /*
549  * Code from here down is temporary, in lieu of a SoC-independent clock API.
550  */
551 
552 void
imx_ccm_usb_enable(device_t dev)553 imx_ccm_usb_enable(device_t dev)
554 {
555 	uint32_t regval;
556 
557 	/*
558 	 * Select PLL2 as the source for the USB clock.
559 	 * The default is PLL3, but U-boot changes it to PLL2.
560 	 */
561 	regval = ccm_read_4(ccm_softc, CCMC_CSCMR1);
562 	regval &= ~CSCMR1_USBOH3_CLK_SEL_MASK;
563 	regval |= 1 << CSCMR1_USBOH3_CLK_SEL_SHIFT;
564 	ccm_write_4(ccm_softc, CCMC_CSCMR1, regval);
565 
566 	/*
567 	 * Set the USB clock pre-divider to div-by-5, post-divider to div-by-2.
568 	 */
569 	regval = ccm_read_4(ccm_softc, CCMC_CSCDR1);
570 	regval &= ~CSCDR1_USBOH3_CLK_PODF_MASK;
571 	regval &= ~CSCDR1_USBOH3_CLK_PRED_MASK;
572 	regval |= 4 << CSCDR1_USBOH3_CLK_PRED_SHIFT;
573 	regval |= 1 << CSCDR1_USBOH3_CLK_PODF_SHIFT;
574 	ccm_write_4(ccm_softc, CCMC_CSCDR1, regval);
575 
576 	/*
577 	 * The same two clocks gates are used on imx51 and imx53.
578 	 */
579 	imx51_clk_gating(CCGR_USBOH3_IPG_AHB_CLK, CCGR_CLK_MODE_ALWAYS);
580 	imx51_clk_gating(CCGR_USBOH3_60M_CLK, CCGR_CLK_MODE_ALWAYS);
581 }
582 
583 void
imx_ccm_usbphy_enable(device_t dev)584 imx_ccm_usbphy_enable(device_t dev)
585 {
586 	uint32_t regval;
587 
588 	/*
589 	 * Select PLL3 as the source for the USBPHY clock.  U-boot does this
590 	 * only for imx53, but the bit exists on imx51.  That seems a bit
591 	 * strange, but we'll go with it until more is known.
592 	 */
593 	if (imx_soc_type() == IMXSOC_53) {
594 		regval = ccm_read_4(ccm_softc, CCMC_CSCMR1);
595 		regval |= 1 << CSCMR1_USBPHY_CLK_SEL_SHIFT;
596 		ccm_write_4(ccm_softc, CCMC_CSCMR1, regval);
597 	}
598 
599 	/*
600 	 * For the imx51 there's just one phy gate control, enable it.
601 	 */
602 	if (imx_soc_type() == IMXSOC_51) {
603 		imx51_clk_gating(CCGR_USB_PHY_CLK, CCGR_CLK_MODE_ALWAYS);
604 		return;
605 	}
606 
607 	/*
608 	 * For imx53 we don't have a full set of clock defines yet, but the
609 	 * datasheet says:
610 	 *   gate reg 4, bits 13-12 usb ph2 clock (usb_phy2_clk_enable)
611 	 *   gate reg 4, bits 11-10 usb ph1 clock (usb_phy1_clk_enable)
612 	 *
613 	 * We should use the fdt data for the device to figure out which of
614 	 * the two we're working on, but for now just turn them both on.
615 	 */
616 	if (imx_soc_type() == IMXSOC_53) {
617 		imx51_clk_gating(__CCGR_NUM(4, 5), CCGR_CLK_MODE_ALWAYS);
618 		imx51_clk_gating(__CCGR_NUM(4, 6), CCGR_CLK_MODE_ALWAYS);
619 		return;
620 	}
621 }
622 
623 uint32_t
imx_ccm_ecspi_hz(void)624 imx_ccm_ecspi_hz(void)
625 {
626 
627 	return (imx51_get_clock(IMX51CLK_CSPI_CLK_ROOT));
628 }
629 
630 uint32_t
imx_ccm_ipg_hz(void)631 imx_ccm_ipg_hz(void)
632 {
633 
634 	return (imx51_get_clock(IMX51CLK_IPG_CLK_ROOT));
635 }
636 
637 uint32_t
imx_ccm_sdhci_hz(void)638 imx_ccm_sdhci_hz(void)
639 {
640 
641 	return (imx51_get_clock(IMX51CLK_ESDHC1_CLK_ROOT));
642 }
643 
644 uint32_t
imx_ccm_perclk_hz(void)645 imx_ccm_perclk_hz(void)
646 {
647 
648 	return (imx51_get_clock(IMX51CLK_PERCLK_ROOT));
649 }
650 
651 uint32_t
imx_ccm_uart_hz(void)652 imx_ccm_uart_hz(void)
653 {
654 
655 	return (imx51_get_clock(IMX51CLK_UART_CLK_ROOT));
656 }
657 
658 uint32_t
imx_ccm_ahb_hz(void)659 imx_ccm_ahb_hz(void)
660 {
661 
662 	return (imx51_get_clock(IMX51CLK_AHB_CLK_ROOT));
663 }
664 
665