xref: /freebsd-14.2/sys/arm/freescale/imx/imx51_ccm.c (revision 685dc743)
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