xref: /f-stack/freebsd/arm/freescale/imx/imx51_ccm.c (revision 22ce4aff)
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