imx51_ccm.c revision 257383
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: head/sys/arm/freescale/imx/imx51_ccm.c 257383 2013-10-30 14:33:15Z ian $");
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_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
99struct imxccm_softc {
100	device_t	sc_dev;
101	struct resource *res[7];
102	u_int64_t 	pll_freq[IMX51_N_DPLLS];
103};
104
105struct imxccm_softc *ccm_softc = NULL;
106
107static uint64_t imx51_get_pll_freq(u_int);
108
109static int imxccm_match(device_t);
110static int imxccm_attach(device_t);
111
112static device_method_t imxccm_methods[] = {
113	DEVMETHOD(device_probe, imxccm_match),
114	DEVMETHOD(device_attach, imxccm_attach),
115
116	DEVMETHOD_END
117};
118
119static driver_t imxccm_driver = {
120	"imxccm",
121	imxccm_methods,
122	sizeof(struct imxccm_softc),
123};
124
125static devclass_t imxccm_devclass;
126
127EARLY_DRIVER_MODULE(imxccm, simplebus, imxccm_driver, imxccm_devclass, 0, 0,
128    BUS_PASS_CPU);
129
130static struct resource_spec imxccm_spec[] = {
131	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },	/* Global registers */
132	{ SYS_RES_MEMORY,	1,	RF_ACTIVE },	/* DPLLIP1 */
133	{ SYS_RES_MEMORY,	2,	RF_ACTIVE },	/* DPLLIP2 */
134	{ SYS_RES_MEMORY,	3,	RF_ACTIVE },	/* DPLLIP3 */
135	{ SYS_RES_IRQ,		0,	RF_ACTIVE },    /* 71 */
136	{ SYS_RES_IRQ,		1,	RF_ACTIVE },    /* 72 */
137	{ -1, 0 }
138};
139
140static int
141imxccm_match(device_t dev)
142{
143
144	if (!ofw_bus_is_compatible(dev, "fsl,imx51-ccm") &&
145	    !ofw_bus_is_compatible(dev, "fsl,imx53-ccm"))
146		return (ENXIO);
147
148	device_set_desc(dev, "Freescale Clock Control Module");
149	return (BUS_PROBE_DEFAULT);
150}
151
152static int
153imxccm_attach(device_t dev)
154{
155	struct imxccm_softc *sc;
156
157	sc = device_get_softc(dev);
158	sc->sc_dev = dev;
159
160	if (bus_alloc_resources(dev, imxccm_spec, sc->res)) {
161		device_printf(dev, "could not allocate resources\n");
162		return (ENXIO);
163	}
164
165	ccm_softc = sc;
166
167	imx51_get_pll_freq(1);
168	imx51_get_pll_freq(2);
169	imx51_get_pll_freq(3);
170
171	device_printf(dev, "PLL1=%lluMHz, PLL2=%lluMHz, PLL3=%lluMHz\n",
172	    sc->pll_freq[0] / 1000000,
173	    sc->pll_freq[1] / 1000000,
174	    sc->pll_freq[2] / 1000000);
175	device_printf(dev, "CPU clock=%d, UART clock=%d\n",
176	    imx51_get_clock(IMX51CLK_ARM_ROOT),
177	    imx51_get_clock(IMX51CLK_UART_CLK_ROOT));
178	device_printf(dev,
179	    "mainbus clock=%d, ahb clock=%d ipg clock=%d perclk=%d\n",
180	    imx51_get_clock(IMX51CLK_MAIN_BUS_CLK),
181	    imx51_get_clock(IMX51CLK_AHB_CLK_ROOT),
182	    imx51_get_clock(IMX51CLK_IPG_CLK_ROOT),
183	    imx51_get_clock(IMX51CLK_PERCLK_ROOT));
184
185
186	return (0);
187}
188
189u_int
190imx51_get_clock(enum imx51_clock clk)
191{
192	u_int freq;
193	u_int sel;
194	uint32_t cacrr;	/* ARM clock root register */
195	uint32_t ccsr;
196	uint32_t cscdr1;
197	uint32_t cscmr1;
198	uint32_t cbcdr;
199	uint32_t cbcmr;
200	uint32_t cdcr;
201
202	if (ccm_softc == NULL)
203		return (0);
204
205	switch (clk) {
206	case IMX51CLK_PLL1:
207	case IMX51CLK_PLL2:
208	case IMX51CLK_PLL3:
209		return ccm_softc->pll_freq[clk-IMX51CLK_PLL1];
210	case IMX51CLK_PLL1SW:
211		ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
212		if ((ccsr & CCSR_PLL1_SW_CLK_SEL) == 0)
213			return ccm_softc->pll_freq[1-1];
214		/* step clock */
215		/* FALLTHROUGH */
216	case IMX51CLK_PLL1STEP:
217		ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
218		switch ((ccsr & CCSR_STEP_SEL_MASK) >> CCSR_STEP_SEL_SHIFT) {
219		case 0:
220			return imx51_get_clock(IMX51CLK_LP_APM);
221		case 1:
222			return 0; /* XXX PLL bypass clock */
223		case 2:
224			return ccm_softc->pll_freq[2-1] /
225			    (1 + ((ccsr & CCSR_PLL2_DIV_PODF_MASK) >>
226				CCSR_PLL2_DIV_PODF_SHIFT));
227		case 3:
228			return ccm_softc->pll_freq[3-1] /
229			    (1 + ((ccsr & CCSR_PLL3_DIV_PODF_MASK) >>
230				CCSR_PLL3_DIV_PODF_SHIFT));
231		}
232		/*NOTREACHED*/
233	case IMX51CLK_PLL2SW:
234		ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
235		if ((ccsr & CCSR_PLL2_SW_CLK_SEL) == 0)
236			return imx51_get_clock(IMX51CLK_PLL2);
237		return 0; /* XXX PLL2 bypass clk */
238	case IMX51CLK_PLL3SW:
239		ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
240		if ((ccsr & CCSR_PLL3_SW_CLK_SEL) == 0)
241			return imx51_get_clock(IMX51CLK_PLL3);
242		return 0; /* XXX PLL3 bypass clk */
243
244	case IMX51CLK_LP_APM:
245		ccsr = bus_read_4(ccm_softc->res[0], CCMC_CCSR);
246		return (ccsr & CCSR_LP_APM) ?
247			    imx51_get_clock(IMX51CLK_FPM) : IMX51_OSC_FREQ;
248
249	case IMX51CLK_ARM_ROOT:
250		freq = imx51_get_clock(IMX51CLK_PLL1SW);
251		cacrr = bus_read_4(ccm_softc->res[0], CCMC_CACRR);
252		return freq / (cacrr + 1);
253
254		/* ... */
255	case IMX51CLK_MAIN_BUS_CLK_SRC:
256		cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR);
257		if ((cbcdr & CBCDR_PERIPH_CLK_SEL) == 0)
258			freq = imx51_get_clock(IMX51CLK_PLL2SW);
259		else {
260			freq = 0;
261			cbcmr = bus_read_4(ccm_softc->res[0],  CCMC_CBCMR);
262			switch ((cbcmr & CBCMR_PERIPH_APM_SEL_MASK) >>
263				CBCMR_PERIPH_APM_SEL_SHIFT) {
264			case 0:
265				freq = imx51_get_clock(IMX51CLK_PLL1SW);
266				break;
267			case 1:
268				freq = imx51_get_clock(IMX51CLK_PLL3SW);
269				break;
270			case 2:
271				freq = imx51_get_clock(IMX51CLK_LP_APM);
272				break;
273			case 3:
274				/* XXX: error */
275				break;
276			}
277		}
278		return freq;
279	case IMX51CLK_MAIN_BUS_CLK:
280		freq = imx51_get_clock(IMX51CLK_MAIN_BUS_CLK_SRC);
281		cdcr = bus_read_4(ccm_softc->res[0], CCMC_CDCR);
282		return freq / (1 + ((cdcr & CDCR_PERIPH_CLK_DVFS_PODF_MASK) >>
283			CDCR_PERIPH_CLK_DVFS_PODF_SHIFT));
284	case IMX51CLK_AHB_CLK_ROOT:
285		freq = imx51_get_clock(IMX51CLK_MAIN_BUS_CLK);
286		cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR);
287		return freq / (1 + ((cbcdr & CBCDR_AHB_PODF_MASK) >>
288				    CBCDR_AHB_PODF_SHIFT));
289	case IMX51CLK_IPG_CLK_ROOT:
290		freq = imx51_get_clock(IMX51CLK_AHB_CLK_ROOT);
291		cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR);
292		return freq / (1 + ((cbcdr & CBCDR_IPG_PODF_MASK) >>
293				    CBCDR_IPG_PODF_SHIFT));
294
295	case IMX51CLK_PERCLK_ROOT:
296		cbcmr = bus_read_4(ccm_softc->res[0], CCMC_CBCMR);
297		if (cbcmr & CBCMR_PERCLK_IPG_SEL)
298			return imx51_get_clock(IMX51CLK_IPG_CLK_ROOT);
299		if (cbcmr & CBCMR_PERCLK_LP_APM_SEL)
300			freq = imx51_get_clock(IMX51CLK_LP_APM);
301		else
302			freq = imx51_get_clock(IMX51CLK_MAIN_BUS_CLK_SRC);
303		cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR);
304
305#ifdef IMXCCMDEBUG
306		printf("cbcmr=%x cbcdr=%x\n", cbcmr, cbcdr);
307#endif
308
309		freq /= 1 + ((cbcdr & CBCDR_PERCLK_PRED1_MASK) >>
310			CBCDR_PERCLK_PRED1_SHIFT);
311		freq /= 1 + ((cbcdr & CBCDR_PERCLK_PRED2_MASK) >>
312			CBCDR_PERCLK_PRED2_SHIFT);
313		freq /= 1 + ((cbcdr & CBCDR_PERCLK_PODF_MASK) >>
314			CBCDR_PERCLK_PODF_SHIFT);
315		return freq;
316	case IMX51CLK_UART_CLK_ROOT:
317		cscdr1 = bus_read_4(ccm_softc->res[0], CCMC_CSCDR1);
318		cscmr1 = bus_read_4(ccm_softc->res[0], CCMC_CSCMR1);
319
320#ifdef IMXCCMDEBUG
321		printf("cscdr1=%x cscmr1=%x\n", cscdr1, cscmr1);
322#endif
323
324		sel = (cscmr1 & CSCMR1_UART_CLK_SEL_MASK) >>
325		    CSCMR1_UART_CLK_SEL_SHIFT;
326
327		freq = 0; /* shut up GCC */
328		switch (sel) {
329		case 0:
330		case 1:
331		case 2:
332			freq = imx51_get_clock(IMX51CLK_PLL1SW + sel);
333			break;
334		case 3:
335			freq = imx51_get_clock(IMX51CLK_LP_APM);
336			break;
337		}
338
339		return freq / (1 + ((cscdr1 & CSCDR1_UART_CLK_PRED_MASK) >>
340			CSCDR1_UART_CLK_PRED_SHIFT)) /
341		    (1 + ((cscdr1 & CSCDR1_UART_CLK_PODF_MASK) >>
342			CSCDR1_UART_CLK_PODF_SHIFT));
343	case IMX51CLK_IPU_HSP_CLK_ROOT:
344		freq = 0;
345		cbcmr = bus_read_4(ccm_softc->res[0],  CCMC_CBCMR);
346		switch ((cbcmr & CBCMR_IPU_HSP_CLK_SEL_MASK) >>
347				CBCMR_IPU_HSP_CLK_SEL_SHIFT) {
348			case 0:
349				freq = imx51_get_clock(IMX51CLK_ARM_AXI_A_CLK);
350				break;
351			case 1:
352				freq = imx51_get_clock(IMX51CLK_ARM_AXI_B_CLK);
353				break;
354			case 2:
355				freq = imx51_get_clock(
356					IMX51CLK_EMI_SLOW_CLK_ROOT);
357				break;
358			case 3:
359				freq = imx51_get_clock(IMX51CLK_AHB_CLK_ROOT);
360				break;
361			}
362		return freq;
363	default:
364		device_printf(ccm_softc->sc_dev,
365		    "clock %d: not supported yet\n", clk);
366		return 0;
367	}
368}
369
370
371static uint64_t
372imx51_get_pll_freq(u_int pll_no)
373{
374	uint32_t dp_ctrl;
375	uint32_t dp_op;
376	uint32_t dp_mfd;
377	uint32_t dp_mfn;
378	uint32_t mfi;
379	int32_t mfn;
380	uint32_t mfd;
381	uint32_t pdf;
382	uint32_t ccr;
383	uint64_t freq = 0;
384	u_int ref = 0;
385
386	KASSERT(1 <= pll_no && pll_no <= IMX51_N_DPLLS, ("Wrong PLL id"));
387
388	dp_ctrl = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_CTL);
389
390	if (dp_ctrl & DP_CTL_HFSM) {
391		dp_op = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_HFS_OP);
392		dp_mfd = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_HFS_MFD);
393		dp_mfn = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_HFS_MFN);
394	} else {
395		dp_op = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_OP);
396		dp_mfd = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_MFD);
397		dp_mfn = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_MFN);
398	}
399
400	pdf = dp_op & DP_OP_PDF_MASK;
401	mfi = max(5, (dp_op & DP_OP_MFI_MASK) >> DP_OP_MFI_SHIFT);
402	mfd = dp_mfd;
403	if (dp_mfn & 0x04000000)
404		/* 27bit signed value */
405		mfn = (uint32_t)(0xf8000000 | dp_mfn);
406	else
407		mfn = dp_mfn;
408
409	switch (dp_ctrl &  DP_CTL_REF_CLK_SEL_MASK) {
410	case DP_CTL_REF_CLK_SEL_COSC:
411		/* Internal Oscillator */
412		/* TODO: get from FDT "fsl,imx-osc" */
413		ref = 24000000; /* IMX51_OSC_FREQ */
414		break;
415	case DP_CTL_REF_CLK_SEL_FPM:
416		ccr = bus_read_4(ccm_softc->res[0], CCMC_CCR);
417		if (ccr & CCR_FPM_MULT)
418		/* TODO: get from FDT "fsl,imx-ckil" */
419			ref = 32768 * 1024;
420		else
421		/* TODO: get from FDT "fsl,imx-ckil" */
422			ref = 32768 * 512;
423		break;
424	default:
425		ref = 0;
426	}
427
428	if (dp_ctrl & DP_CTL_REF_CLK_DIV)
429		ref /= 2;
430
431	ref *= 4;
432	freq = (int64_t)ref * mfi + (int64_t)ref * mfn / (mfd + 1);
433	freq /= pdf + 1;
434
435	if (!(dp_ctrl & DP_CTL_DPDCK0_2_EN))
436		freq /= 2;
437
438#ifdef IMXCCMDEBUG
439	printf("ref: %dKHz ", ref);
440	printf("dp_ctl: %08x ", dp_ctrl);
441	printf("pdf: %3d ", pdf);
442	printf("mfi: %3d ", mfi);
443	printf("mfd: %3d ", mfd);
444	printf("mfn: %3d ", mfn);
445	printf("pll: %d\n", (uint32_t)freq);
446#endif
447
448	ccm_softc->pll_freq[pll_no-1] = freq;
449
450	return (freq);
451}
452
453void
454imx51_clk_gating(int clk_src, int mode)
455{
456	int field, group;
457	uint32_t reg;
458
459	group = CCMR_CCGR_MODULE(clk_src);
460	field = clk_src % CCMR_CCGR_NSOURCE;
461	reg = bus_read_4(ccm_softc->res[0], CCMC_CCGR(group));
462	reg &= ~(0x03 << field * 2);
463	reg |= (mode << field * 2);
464	bus_write_4(ccm_softc->res[0], CCMC_CCGR(group), reg);
465}
466
467int
468imx51_get_clk_gating(int clk_src)
469{
470	uint32_t reg;
471
472	reg = bus_read_4(ccm_softc->res[0],
473	    CCMC_CCGR(CCMR_CCGR_MODULE(clk_src)));
474	return ((reg >> (clk_src % CCMR_CCGR_NSOURCE) * 2) & 0x03);
475}
476
477/*
478 * Code from here down is temporary, in lieu of a SoC-independent clock API.
479 */
480
481void
482imx_ccm_usb_enable(device_t dev)
483{
484	uint32_t regval;
485
486	/*
487	 * Select PLL2 as the source for the USB clock.
488	 * The default is PLL3, but U-boot changes it to PLL2.
489	 */
490	regval = bus_read_4(ccm_softc->res[0], CCMC_CSCMR1);
491	regval &= ~CSCMR1_USBOH3_CLK_SEL_MASK;
492	regval |= 1 << CSCMR1_USBOH3_CLK_SEL_SHIFT;
493	bus_write_4(ccm_softc->res[0], CCMC_CSCMR1, regval);
494
495	/*
496	 * Set the USB clock pre-divider to div-by-5, post-divider to div-by-2.
497	 */
498	regval = bus_read_4(ccm_softc->res[0], CCMC_CSCDR1);
499	regval &= ~CSCDR1_USBOH3_CLK_PODF_MASK;
500	regval &= ~CSCDR1_USBOH3_CLK_PRED_MASK;
501	regval |= 4 << CSCDR1_USBOH3_CLK_PRED_SHIFT;
502	regval |= 1 << CSCDR1_USBOH3_CLK_PODF_SHIFT;
503	bus_write_4(ccm_softc->res[0], CCMC_CSCDR1, regval);
504
505	/*
506	 * The same two clocks gates are used on imx51 and imx53.
507	 */
508	imx51_clk_gating(CCGR_USBOH3_IPG_AHB_CLK, CCGR_CLK_MODE_ALWAYS);
509	imx51_clk_gating(CCGR_USBOH3_60M_CLK, CCGR_CLK_MODE_ALWAYS);
510}
511
512void
513imx_ccm_usbphy_enable(device_t dev)
514{
515	uint32_t regval;
516
517	/*
518	 * Select PLL3 as the source for the USBPHY clock.  U-boot does this
519	 * only for imx53, but the bit exists on imx51.  That seems a bit
520	 * strange, but we'll go with it until more is known.
521	 */
522	if (imx_soc_type() == IMXSOC_53) {
523		regval = bus_read_4(ccm_softc->res[0], CCMC_CSCMR1);
524		regval |= 1 << CSCMR1_USBPHY_CLK_SEL_SHIFT;
525		bus_write_4(ccm_softc->res[0], CCMC_CSCMR1, regval);
526	}
527
528	/*
529	 * For the imx51 there's just one phy gate control, enable it.
530	 */
531	if (imx_soc_type() == IMXSOC_51) {
532		imx51_clk_gating(CCGR_USB_PHY_CLK, CCGR_CLK_MODE_ALWAYS);
533		return;
534	}
535
536	/*
537	 * For imx53 we don't have a full set of clock defines yet, but the
538	 * datasheet says:
539	 *   gate reg 4, bits 13-12 usb ph2 clock (usb_phy2_clk_enable)
540	 *   gate reg 4, bits 11-10 usb ph1 clock (usb_phy1_clk_enable)
541	 *
542	 * We should use the fdt data for the device to figure out which of
543	 * the two we're working on, but for now just turn them both on.
544	 */
545	if (imx_soc_type() == IMXSOC_53) {
546		imx51_clk_gating(__CCGR_NUM(4, 5), CCGR_CLK_MODE_ALWAYS);
547		imx51_clk_gating(__CCGR_NUM(4, 6), CCGR_CLK_MODE_ALWAYS);
548		return;
549	}
550}
551
552