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