1/*	$NetBSD: imx51_ccm.c,v 1.1 2012/04/17 09:33:31 bsh Exp $	*/
2/*
3 * Copyright (c) 2010, 2011, 2012  Genetec Corporation.  All rights reserved.
4 * Written by Hashimoto Kenichi for Genetec Corporation.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/*-
29 * Copyright (c) 2012, 2013 The FreeBSD Foundation
30 * All rights reserved.
31 *
32 * Portions of this software were developed by Oleksandr Rybalko
33 * under sponsorship from the FreeBSD Foundation.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1.	Redistributions of source code must retain the above copyright
39 *	notice, this list of conditions and the following disclaimer.
40 * 2.	Redistributions in binary form must reproduce the above copyright
41 *	notice, this list of conditions and the following disclaimer in the
42 *	documentation and/or other materials provided with the distribution.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 */
56
57/*
58 * Clock Controller Module (CCM)
59 */
60
61#include <sys/cdefs.h>
62__FBSDID("$FreeBSD$");
63
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/fdt/fdt_common.h>
76#include <dev/ofw/openfirm.h>
77#include <dev/ofw/ofw_bus.h>
78#include <dev/ofw/ofw_bus_subr.h>
79
80#include <machine/bus.h>
81#include <machine/fdt.h>
82
83#include <arm/freescale/imx/imx51_ccmvar.h>
84#include <arm/freescale/imx/imx51_ccmreg.h>
85#include <arm/freescale/imx/imx51_dpllreg.h>
86#include <arm/freescale/imx/imx_ccmvar.h>
87#include <arm/freescale/imx/imx_machdep.h>
88
89#define	IMXCCMDEBUG
90#undef	IMXCCMDEBUG
91
92#ifndef	IMX51_OSC_FREQ
93#define	IMX51_OSC_FREQ	(24 * 1000 * 1000)	/* 24MHz */
94#endif
95
96#ifndef	IMX51_CKIL_FREQ
97#define	IMX51_CKIL_FREQ	32768
98#endif
99
100struct imxccm_softc {
101	device_t	sc_dev;
102	struct resource *res[7];
103	u_int64_t 	pll_freq[IMX51_N_DPLLS];
104};
105
106struct imxccm_softc *ccm_softc = NULL;
107
108static uint64_t imx51_get_pll_freq(u_int);
109
110static int imxccm_match(device_t);
111static int imxccm_attach(device_t);
112
113static device_method_t imxccm_methods[] = {
114	DEVMETHOD(device_probe, imxccm_match),
115	DEVMETHOD(device_attach, imxccm_attach),
116
117	DEVMETHOD_END
118};
119
120static driver_t imxccm_driver = {
121	"imxccm",
122	imxccm_methods,
123	sizeof(struct imxccm_softc),
124};
125
126static devclass_t imxccm_devclass;
127
128EARLY_DRIVER_MODULE(imxccm, simplebus, imxccm_driver, imxccm_devclass, 0, 0,
129    BUS_PASS_CPU);
130
131static struct resource_spec imxccm_spec[] = {
132	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },	/* Global registers */
133	{ SYS_RES_MEMORY,	1,	RF_ACTIVE },	/* DPLLIP1 */
134	{ SYS_RES_MEMORY,	2,	RF_ACTIVE },	/* DPLLIP2 */
135	{ SYS_RES_MEMORY,	3,	RF_ACTIVE },	/* DPLLIP3 */
136	{ SYS_RES_IRQ,		0,	RF_ACTIVE },    /* 71 */
137	{ SYS_RES_IRQ,		1,	RF_ACTIVE },    /* 72 */
138	{ -1, 0 }
139};
140
141static int
142imxccm_match(device_t dev)
143{
144
145	if (!ofw_bus_status_okay(dev))
146		return (ENXIO);
147
148	if (!ofw_bus_is_compatible(dev, "fsl,imx51-ccm") &&
149	    !ofw_bus_is_compatible(dev, "fsl,imx53-ccm"))
150		return (ENXIO);
151
152	device_set_desc(dev, "Freescale Clock Control Module");
153	return (BUS_PROBE_DEFAULT);
154}
155
156static int
157imxccm_attach(device_t dev)
158{
159	struct imxccm_softc *sc;
160
161	sc = device_get_softc(dev);
162	sc->sc_dev = dev;
163
164	if (bus_alloc_resources(dev, imxccm_spec, sc->res)) {
165		device_printf(dev, "could not allocate resources\n");
166		return (ENXIO);
167	}
168
169	ccm_softc = sc;
170
171	imx51_get_pll_freq(1);
172	imx51_get_pll_freq(2);
173	imx51_get_pll_freq(3);
174
175	device_printf(dev, "PLL1=%lluMHz, PLL2=%lluMHz, PLL3=%lluMHz\n",
176	    sc->pll_freq[0] / 1000000,
177	    sc->pll_freq[1] / 1000000,
178	    sc->pll_freq[2] / 1000000);
179	device_printf(dev, "CPU clock=%d, UART clock=%d\n",
180	    imx51_get_clock(IMX51CLK_ARM_ROOT),
181	    imx51_get_clock(IMX51CLK_UART_CLK_ROOT));
182	device_printf(dev,
183	    "mainbus clock=%d, ahb clock=%d ipg clock=%d perclk=%d\n",
184	    imx51_get_clock(IMX51CLK_MAIN_BUS_CLK),
185	    imx51_get_clock(IMX51CLK_AHB_CLK_ROOT),
186	    imx51_get_clock(IMX51CLK_IPG_CLK_ROOT),
187	    imx51_get_clock(IMX51CLK_PERCLK_ROOT));
188
189
190	return (0);
191}
192
193u_int
194imx51_get_clock(enum imx51_clock clk)
195{
196	u_int freq;
197	u_int sel;
198	uint32_t cacrr;	/* ARM clock root register */
199	uint32_t ccsr;
200	uint32_t cscdr1;
201	uint32_t cscmr1;
202	uint32_t cbcdr;
203	uint32_t cbcmr;
204	uint32_t cdcr;
205
206	if (ccm_softc == NULL)
207		return (0);
208
209	switch (clk) {
210	case IMX51CLK_PLL1:
211	case IMX51CLK_PLL2:
212	case IMX51CLK_PLL3:
213		return ccm_softc->pll_freq[clk-IMX51CLK_PLL1];
214	case IMX51CLK_PLL1SW:
215		ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
216		if ((ccsr & CCSR_PLL1_SW_CLK_SEL) == 0)
217			return ccm_softc->pll_freq[1-1];
218		/* step clock */
219		/* FALLTHROUGH */
220	case IMX51CLK_PLL1STEP:
221		ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
222		switch ((ccsr & CCSR_STEP_SEL_MASK) >> CCSR_STEP_SEL_SHIFT) {
223		case 0:
224			return imx51_get_clock(IMX51CLK_LP_APM);
225		case 1:
226			return 0; /* XXX PLL bypass clock */
227		case 2:
228			return ccm_softc->pll_freq[2-1] /
229			    (1 + ((ccsr & CCSR_PLL2_DIV_PODF_MASK) >>
230				CCSR_PLL2_DIV_PODF_SHIFT));
231		case 3:
232			return ccm_softc->pll_freq[3-1] /
233			    (1 + ((ccsr & CCSR_PLL3_DIV_PODF_MASK) >>
234				CCSR_PLL3_DIV_PODF_SHIFT));
235		}
236		/*NOTREACHED*/
237	case IMX51CLK_PLL2SW:
238		ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
239		if ((ccsr & CCSR_PLL2_SW_CLK_SEL) == 0)
240			return imx51_get_clock(IMX51CLK_PLL2);
241		return 0; /* XXX PLL2 bypass clk */
242	case IMX51CLK_PLL3SW:
243		ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
244		if ((ccsr & CCSR_PLL3_SW_CLK_SEL) == 0)
245			return imx51_get_clock(IMX51CLK_PLL3);
246		return 0; /* XXX PLL3 bypass clk */
247
248	case IMX51CLK_LP_APM:
249		ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
250		return (ccsr & CCSR_LP_APM) ?
251			    imx51_get_clock(IMX51CLK_FPM) : IMX51_OSC_FREQ;
252
253	case IMX51CLK_ARM_ROOT:
254		freq = imx51_get_clock(IMX51CLK_PLL1SW);
255		cacrr = bus_read_4(ccm_softc->res[0], CCMC_CACRR);
256		return freq / (cacrr + 1);
257
258		/* ... */
259	case IMX51CLK_MAIN_BUS_CLK_SRC:
260		cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR);
261		if ((cbcdr & CBCDR_PERIPH_CLK_SEL) == 0)
262			freq = imx51_get_clock(IMX51CLK_PLL2SW);
263		else {
264			freq = 0;
265			cbcmr = bus_read_4(ccm_softc->res[0],  CCMC_CBCMR);
266			switch ((cbcmr & CBCMR_PERIPH_APM_SEL_MASK) >>
267				CBCMR_PERIPH_APM_SEL_SHIFT) {
268			case 0:
269				freq = imx51_get_clock(IMX51CLK_PLL1SW);
270				break;
271			case 1:
272				freq = imx51_get_clock(IMX51CLK_PLL3SW);
273				break;
274			case 2:
275				freq = imx51_get_clock(IMX51CLK_LP_APM);
276				break;
277			case 3:
278				/* XXX: error */
279				break;
280			}
281		}
282		return freq;
283	case IMX51CLK_MAIN_BUS_CLK:
284		freq = imx51_get_clock(IMX51CLK_MAIN_BUS_CLK_SRC);
285		cdcr = bus_read_4(ccm_softc->res[0], CCMC_CDCR);
286		return freq / (1 + ((cdcr & CDCR_PERIPH_CLK_DVFS_PODF_MASK) >>
287			CDCR_PERIPH_CLK_DVFS_PODF_SHIFT));
288	case IMX51CLK_AHB_CLK_ROOT:
289		freq = imx51_get_clock(IMX51CLK_MAIN_BUS_CLK);
290		cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR);
291		return freq / (1 + ((cbcdr & CBCDR_AHB_PODF_MASK) >>
292				    CBCDR_AHB_PODF_SHIFT));
293	case IMX51CLK_IPG_CLK_ROOT:
294		freq = imx51_get_clock(IMX51CLK_AHB_CLK_ROOT);
295		cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR);
296		return freq / (1 + ((cbcdr & CBCDR_IPG_PODF_MASK) >>
297				    CBCDR_IPG_PODF_SHIFT));
298
299	case IMX51CLK_PERCLK_ROOT:
300		cbcmr = bus_read_4(ccm_softc->res[0], CCMC_CBCMR);
301		if (cbcmr & CBCMR_PERCLK_IPG_SEL)
302			return imx51_get_clock(IMX51CLK_IPG_CLK_ROOT);
303		if (cbcmr & CBCMR_PERCLK_LP_APM_SEL)
304			freq = imx51_get_clock(IMX51CLK_LP_APM);
305		else
306			freq = imx51_get_clock(IMX51CLK_MAIN_BUS_CLK_SRC);
307		cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR);
308
309#ifdef IMXCCMDEBUG
310		printf("cbcmr=%x cbcdr=%x\n", cbcmr, cbcdr);
311#endif
312
313		freq /= 1 + ((cbcdr & CBCDR_PERCLK_PRED1_MASK) >>
314			CBCDR_PERCLK_PRED1_SHIFT);
315		freq /= 1 + ((cbcdr & CBCDR_PERCLK_PRED2_MASK) >>
316			CBCDR_PERCLK_PRED2_SHIFT);
317		freq /= 1 + ((cbcdr & CBCDR_PERCLK_PODF_MASK) >>
318			CBCDR_PERCLK_PODF_SHIFT);
319		return freq;
320	case IMX51CLK_UART_CLK_ROOT:
321		cscdr1 = bus_read_4(ccm_softc->res[0], CCMC_CSCDR1);
322		cscmr1 = bus_read_4(ccm_softc->res[0], CCMC_CSCMR1);
323
324#ifdef IMXCCMDEBUG
325		printf("cscdr1=%x cscmr1=%x\n", cscdr1, cscmr1);
326#endif
327
328		sel = (cscmr1 & CSCMR1_UART_CLK_SEL_MASK) >>
329		    CSCMR1_UART_CLK_SEL_SHIFT;
330
331		freq = 0; /* shut up GCC */
332		switch (sel) {
333		case 0:
334		case 1:
335		case 2:
336			freq = imx51_get_clock(IMX51CLK_PLL1SW + sel);
337			break;
338		case 3:
339			freq = imx51_get_clock(IMX51CLK_LP_APM);
340			break;
341		}
342
343		return freq / (1 + ((cscdr1 & CSCDR1_UART_CLK_PRED_MASK) >>
344			CSCDR1_UART_CLK_PRED_SHIFT)) /
345		    (1 + ((cscdr1 & CSCDR1_UART_CLK_PODF_MASK) >>
346			CSCDR1_UART_CLK_PODF_SHIFT));
347	case IMX51CLK_IPU_HSP_CLK_ROOT:
348		freq = 0;
349		cbcmr = bus_read_4(ccm_softc->res[0],  CCMC_CBCMR);
350		switch ((cbcmr & CBCMR_IPU_HSP_CLK_SEL_MASK) >>
351				CBCMR_IPU_HSP_CLK_SEL_SHIFT) {
352			case 0:
353				freq = imx51_get_clock(IMX51CLK_ARM_AXI_A_CLK);
354				break;
355			case 1:
356				freq = imx51_get_clock(IMX51CLK_ARM_AXI_B_CLK);
357				break;
358			case 2:
359				freq = imx51_get_clock(
360					IMX51CLK_EMI_SLOW_CLK_ROOT);
361				break;
362			case 3:
363				freq = imx51_get_clock(IMX51CLK_AHB_CLK_ROOT);
364				break;
365			}
366		return freq;
367	default:
368		device_printf(ccm_softc->sc_dev,
369		    "clock %d: not supported yet\n", clk);
370		return 0;
371	}
372}
373
374
375static uint64_t
376imx51_get_pll_freq(u_int pll_no)
377{
378	uint32_t dp_ctrl;
379	uint32_t dp_op;
380	uint32_t dp_mfd;
381	uint32_t dp_mfn;
382	uint32_t mfi;
383	int32_t mfn;
384	uint32_t mfd;
385	uint32_t pdf;
386	uint32_t ccr;
387	uint64_t freq = 0;
388	u_int ref = 0;
389
390	KASSERT(1 <= pll_no && pll_no <= IMX51_N_DPLLS, ("Wrong PLL id"));
391
392	dp_ctrl = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_CTL);
393
394	if (dp_ctrl & DP_CTL_HFSM) {
395		dp_op = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_HFS_OP);
396		dp_mfd = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_HFS_MFD);
397		dp_mfn = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_HFS_MFN);
398	} else {
399		dp_op = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_OP);
400		dp_mfd = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_MFD);
401		dp_mfn = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_MFN);
402	}
403
404	pdf = dp_op & DP_OP_PDF_MASK;
405	mfi = max(5, (dp_op & DP_OP_MFI_MASK) >> DP_OP_MFI_SHIFT);
406	mfd = dp_mfd;
407	if (dp_mfn & 0x04000000)
408		/* 27bit signed value */
409		mfn = (uint32_t)(0xf8000000 | dp_mfn);
410	else
411		mfn = dp_mfn;
412
413	switch (dp_ctrl &  DP_CTL_REF_CLK_SEL_MASK) {
414	case DP_CTL_REF_CLK_SEL_COSC:
415		/* Internal Oscillator */
416		/* TODO: get from FDT "fsl,imx-osc" */
417		ref = 24000000; /* IMX51_OSC_FREQ */
418		break;
419	case DP_CTL_REF_CLK_SEL_FPM:
420		ccr = bus_read_4(ccm_softc->res[0], CCMC_CCR);
421		if (ccr & CCR_FPM_MULT)
422		/* TODO: get from FDT "fsl,imx-ckil" */
423			ref = 32768 * 1024;
424		else
425		/* TODO: get from FDT "fsl,imx-ckil" */
426			ref = 32768 * 512;
427		break;
428	default:
429		ref = 0;
430	}
431
432	if (dp_ctrl & DP_CTL_REF_CLK_DIV)
433		ref /= 2;
434
435	ref *= 4;
436	freq = (int64_t)ref * mfi + (int64_t)ref * mfn / (mfd + 1);
437	freq /= pdf + 1;
438
439	if (!(dp_ctrl & DP_CTL_DPDCK0_2_EN))
440		freq /= 2;
441
442#ifdef IMXCCMDEBUG
443	printf("ref: %dKHz ", ref);
444	printf("dp_ctl: %08x ", dp_ctrl);
445	printf("pdf: %3d ", pdf);
446	printf("mfi: %3d ", mfi);
447	printf("mfd: %3d ", mfd);
448	printf("mfn: %3d ", mfn);
449	printf("pll: %d\n", (uint32_t)freq);
450#endif
451
452	ccm_softc->pll_freq[pll_no-1] = freq;
453
454	return (freq);
455}
456
457void
458imx51_clk_gating(int clk_src, int mode)
459{
460	int field, group;
461	uint32_t reg;
462
463	group = CCMR_CCGR_MODULE(clk_src);
464	field = clk_src % CCMR_CCGR_NSOURCE;
465	reg = bus_read_4(ccm_softc->res[0], CCMC_CCGR(group));
466	reg &= ~(0x03 << field * 2);
467	reg |= (mode << field * 2);
468	bus_write_4(ccm_softc->res[0], CCMC_CCGR(group), reg);
469}
470
471int
472imx51_get_clk_gating(int clk_src)
473{
474	uint32_t reg;
475
476	reg = bus_read_4(ccm_softc->res[0],
477	    CCMC_CCGR(CCMR_CCGR_MODULE(clk_src)));
478	return ((reg >> (clk_src % CCMR_CCGR_NSOURCE) * 2) & 0x03);
479}
480
481/*
482 * Code from here down is temporary, in lieu of a SoC-independent clock API.
483 */
484
485void
486imx_ccm_usb_enable(device_t dev)
487{
488	uint32_t regval;
489
490	/*
491	 * Select PLL2 as the source for the USB clock.
492	 * The default is PLL3, but U-boot changes it to PLL2.
493	 */
494	regval = bus_read_4(ccm_softc->res[0], CCMC_CSCMR1);
495	regval &= ~CSCMR1_USBOH3_CLK_SEL_MASK;
496	regval |= 1 << CSCMR1_USBOH3_CLK_SEL_SHIFT;
497	bus_write_4(ccm_softc->res[0], CCMC_CSCMR1, regval);
498
499	/*
500	 * Set the USB clock pre-divider to div-by-5, post-divider to div-by-2.
501	 */
502	regval = bus_read_4(ccm_softc->res[0], CCMC_CSCDR1);
503	regval &= ~CSCDR1_USBOH3_CLK_PODF_MASK;
504	regval &= ~CSCDR1_USBOH3_CLK_PRED_MASK;
505	regval |= 4 << CSCDR1_USBOH3_CLK_PRED_SHIFT;
506	regval |= 1 << CSCDR1_USBOH3_CLK_PODF_SHIFT;
507	bus_write_4(ccm_softc->res[0], CCMC_CSCDR1, regval);
508
509	/*
510	 * The same two clocks gates are used on imx51 and imx53.
511	 */
512	imx51_clk_gating(CCGR_USBOH3_IPG_AHB_CLK, CCGR_CLK_MODE_ALWAYS);
513	imx51_clk_gating(CCGR_USBOH3_60M_CLK, CCGR_CLK_MODE_ALWAYS);
514}
515
516void
517imx_ccm_usbphy_enable(device_t dev)
518{
519	uint32_t regval;
520
521	/*
522	 * Select PLL3 as the source for the USBPHY clock.  U-boot does this
523	 * only for imx53, but the bit exists on imx51.  That seems a bit
524	 * strange, but we'll go with it until more is known.
525	 */
526	if (imx_soc_type() == IMXSOC_53) {
527		regval = bus_read_4(ccm_softc->res[0], CCMC_CSCMR1);
528		regval |= 1 << CSCMR1_USBPHY_CLK_SEL_SHIFT;
529		bus_write_4(ccm_softc->res[0], CCMC_CSCMR1, regval);
530	}
531
532	/*
533	 * For the imx51 there's just one phy gate control, enable it.
534	 */
535	if (imx_soc_type() == IMXSOC_51) {
536		imx51_clk_gating(CCGR_USB_PHY_CLK, CCGR_CLK_MODE_ALWAYS);
537		return;
538	}
539
540	/*
541	 * For imx53 we don't have a full set of clock defines yet, but the
542	 * datasheet says:
543	 *   gate reg 4, bits 13-12 usb ph2 clock (usb_phy2_clk_enable)
544	 *   gate reg 4, bits 11-10 usb ph1 clock (usb_phy1_clk_enable)
545	 *
546	 * We should use the fdt data for the device to figure out which of
547	 * the two we're working on, but for now just turn them both on.
548	 */
549	if (imx_soc_type() == IMXSOC_53) {
550		imx51_clk_gating(__CCGR_NUM(4, 5), CCGR_CLK_MODE_ALWAYS);
551		imx51_clk_gating(__CCGR_NUM(4, 6), CCGR_CLK_MODE_ALWAYS);
552		return;
553	}
554}
555
556uint32_t
557imx_ccm_ipg_hz(void)
558{
559
560	return (imx51_get_clock(IMX51CLK_IPG_CLK_ROOT));
561}
562
563uint32_t
564imx_ccm_sdhci_hz(void)
565{
566
567	return (imx51_get_clock(IMX51CLK_ESDHC1_CLK_ROOT));
568}
569
570uint32_t
571imx_ccm_perclk_hz(void)
572{
573
574	return (imx51_get_clock(IMX51CLK_PERCLK_ROOT));
575}
576
577uint32_t
578imx_ccm_uart_hz(void)
579{
580
581	return (imx51_get_clock(IMX51CLK_UART_CLK_ROOT));
582}
583
584uint32_t
585imx_ccm_ahb_hz(void)
586{
587
588	return (imx51_get_clock(IMX51CLK_AHB_CLK_ROOT));
589}
590