imx51_ccm.c revision 331722
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: stable/11/sys/arm/freescale/imx/imx51_ccm.c 331722 2018-03-29 02:50:57Z eadler $");
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
100/*
101 * The fdt data does not provide reg properties describing the DPLL register
102 * blocks we need to access, presumably because the needed addresses are
103 * hard-coded within the linux driver.  That leaves us with no choice but to do
104 * the same thing, if we want to run with vendor-supplied fdt data.  So here we
105 * have tables of the physical addresses we need for each soc, and we'll use
106 * bus_space_map() at attach() time to get access to them.
107 */
108static uint32_t imx51_dpll_addrs[IMX51_N_DPLLS] = {
109	0x83f80000,	/* DPLL1 */
110	0x83f84000,	/* DPLL2 */
111	0x83f88000,	/* DPLL3 */
112};
113
114static uint32_t imx53_dpll_addrs[IMX51_N_DPLLS] = {
115	0x63f80000,     /* DPLL1 */
116	0x63f84000,     /* DPLL2 */
117	0x63f88000,     /* DPLL3 */
118};
119
120#define	DPLL_REGS_SZ	(16 * 1024)
121
122struct imxccm_softc {
123	device_t	sc_dev;
124	struct resource *ccmregs;
125	u_int64_t 	pll_freq[IMX51_N_DPLLS];
126	bus_space_tag_t    pllbst;
127	bus_space_handle_t pllbsh[IMX51_N_DPLLS];
128};
129
130struct imxccm_softc *ccm_softc = NULL;
131
132static uint64_t imx51_get_pll_freq(u_int);
133
134static int imxccm_match(device_t);
135static int imxccm_attach(device_t);
136
137static device_method_t imxccm_methods[] = {
138	DEVMETHOD(device_probe, imxccm_match),
139	DEVMETHOD(device_attach, imxccm_attach),
140
141	DEVMETHOD_END
142};
143
144static driver_t imxccm_driver = {
145	"imxccm",
146	imxccm_methods,
147	sizeof(struct imxccm_softc),
148};
149
150static devclass_t imxccm_devclass;
151
152EARLY_DRIVER_MODULE(imxccm, simplebus, imxccm_driver, imxccm_devclass, 0, 0,
153    BUS_PASS_CPU);
154
155static inline uint32_t
156pll_read_4(struct imxccm_softc *sc, int pll, int reg)
157{
158
159	return (bus_space_read_4(sc->pllbst, sc->pllbsh[pll - 1], reg));
160}
161
162static inline uint32_t
163ccm_read_4(struct imxccm_softc *sc, int reg)
164{
165
166	return (bus_read_4(sc->ccmregs, reg));
167}
168
169static inline void
170ccm_write_4(struct imxccm_softc *sc, int reg, uint32_t val)
171{
172
173	bus_write_4(sc->ccmregs, reg, val);
174}
175
176static int
177imxccm_match(device_t dev)
178{
179
180	if (!ofw_bus_status_okay(dev))
181		return (ENXIO);
182
183	if (!ofw_bus_is_compatible(dev, "fsl,imx51-ccm") &&
184	    !ofw_bus_is_compatible(dev, "fsl,imx53-ccm"))
185		return (ENXIO);
186
187	device_set_desc(dev, "Freescale Clock Control Module");
188	return (BUS_PROBE_DEFAULT);
189}
190
191static int
192imxccm_attach(device_t dev)
193{
194	struct imxccm_softc *sc;
195	int idx;
196	u_int soc;
197	uint32_t *pll_addrs;
198
199	sc = device_get_softc(dev);
200	sc->sc_dev = dev;
201
202	switch ((soc = imx_soc_type())) {
203	case IMXSOC_51:
204		pll_addrs = imx51_dpll_addrs;
205		break;
206	case IMXSOC_53:
207		pll_addrs = imx53_dpll_addrs;
208		break;
209	default:
210		device_printf(dev, "No support for SoC type 0x%08x\n", soc);
211		goto noclocks;
212	}
213
214	idx = 0;
215	sc->ccmregs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &idx,
216	    RF_ACTIVE);
217	if (sc->ccmregs == NULL) {
218		device_printf(dev, "could not allocate resources\n");
219		goto noclocks;
220	}
221
222	sc->pllbst = fdtbus_bs_tag;
223	for (idx = 0; idx < IMX51_N_DPLLS; ++idx) {
224		if (bus_space_map(sc->pllbst, pll_addrs[idx], DPLL_REGS_SZ, 0,
225		    &sc->pllbsh[idx]) != 0) {
226			device_printf(dev, "Cannot map DPLL registers\n");
227			goto noclocks;
228		}
229	}
230
231	ccm_softc = sc;
232
233	imx51_get_pll_freq(1);
234	imx51_get_pll_freq(2);
235	imx51_get_pll_freq(3);
236
237	device_printf(dev, "PLL1=%lluMHz, PLL2=%lluMHz, PLL3=%lluMHz\n",
238	    sc->pll_freq[0] / 1000000,
239	    sc->pll_freq[1] / 1000000,
240	    sc->pll_freq[2] / 1000000);
241	device_printf(dev, "CPU clock=%d, UART clock=%d\n",
242	    imx51_get_clock(IMX51CLK_ARM_ROOT),
243	    imx51_get_clock(IMX51CLK_UART_CLK_ROOT));
244	device_printf(dev,
245	    "mainbus clock=%d, ahb clock=%d ipg clock=%d perclk=%d\n",
246	    imx51_get_clock(IMX51CLK_MAIN_BUS_CLK),
247	    imx51_get_clock(IMX51CLK_AHB_CLK_ROOT),
248	    imx51_get_clock(IMX51CLK_IPG_CLK_ROOT),
249	    imx51_get_clock(IMX51CLK_PERCLK_ROOT));
250
251
252	return (0);
253
254noclocks:
255
256	panic("Cannot continue without clock support");
257}
258
259u_int
260imx51_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
441static uint64_t
442imx51_get_pll_freq(u_int pll_no)
443{
444	uint32_t dp_ctrl;
445	uint32_t dp_op;
446	uint32_t dp_mfd;
447	uint32_t dp_mfn;
448	uint32_t mfi;
449	int32_t mfn;
450	uint32_t mfd;
451	uint32_t pdf;
452	uint32_t ccr;
453	uint64_t freq = 0;
454	u_int ref = 0;
455
456	KASSERT(1 <= pll_no && pll_no <= IMX51_N_DPLLS, ("Wrong PLL id"));
457
458	dp_ctrl = pll_read_4(ccm_softc, pll_no, DPLL_DP_CTL);
459
460	if (dp_ctrl & DP_CTL_HFSM) {
461		dp_op  = pll_read_4(ccm_softc, pll_no, DPLL_DP_HFS_OP);
462		dp_mfd = pll_read_4(ccm_softc, pll_no, DPLL_DP_HFS_MFD);
463		dp_mfn = pll_read_4(ccm_softc, pll_no, DPLL_DP_HFS_MFN);
464	} else {
465		dp_op  = pll_read_4(ccm_softc, pll_no, DPLL_DP_OP);
466		dp_mfd = pll_read_4(ccm_softc, pll_no, DPLL_DP_MFD);
467		dp_mfn = pll_read_4(ccm_softc, pll_no, DPLL_DP_MFN);
468	}
469
470	pdf = dp_op & DP_OP_PDF_MASK;
471	mfi = max(5, (dp_op & DP_OP_MFI_MASK) >> DP_OP_MFI_SHIFT);
472	mfd = dp_mfd;
473	if (dp_mfn & 0x04000000)
474		/* 27bit signed value */
475		mfn = (uint32_t)(0xf8000000 | dp_mfn);
476	else
477		mfn = dp_mfn;
478
479	switch (dp_ctrl &  DP_CTL_REF_CLK_SEL_MASK) {
480	case DP_CTL_REF_CLK_SEL_COSC:
481		/* Internal Oscillator */
482		/* TODO: get from FDT "fsl,imx-osc" */
483		ref = 24000000; /* IMX51_OSC_FREQ */
484		break;
485	case DP_CTL_REF_CLK_SEL_FPM:
486		ccr = ccm_read_4(ccm_softc, CCMC_CCR);
487		if (ccr & CCR_FPM_MULT)
488		/* TODO: get from FDT "fsl,imx-ckil" */
489			ref = 32768 * 1024;
490		else
491		/* TODO: get from FDT "fsl,imx-ckil" */
492			ref = 32768 * 512;
493		break;
494	default:
495		ref = 0;
496	}
497
498	if (dp_ctrl & DP_CTL_REF_CLK_DIV)
499		ref /= 2;
500
501	ref *= 4;
502	freq = (int64_t)ref * mfi + (int64_t)ref * mfn / (mfd + 1);
503	freq /= pdf + 1;
504
505	if (!(dp_ctrl & DP_CTL_DPDCK0_2_EN))
506		freq /= 2;
507
508#ifdef IMXCCMDEBUG
509	printf("ref: %dKHz ", ref);
510	printf("dp_ctl: %08x ", dp_ctrl);
511	printf("pdf: %3d ", pdf);
512	printf("mfi: %3d ", mfi);
513	printf("mfd: %3d ", mfd);
514	printf("mfn: %3d ", mfn);
515	printf("pll: %d\n", (uint32_t)freq);
516#endif
517
518	ccm_softc->pll_freq[pll_no-1] = freq;
519
520	return (freq);
521}
522
523void
524imx51_clk_gating(int clk_src, int mode)
525{
526	int field, group;
527	uint32_t reg;
528
529	group = CCMR_CCGR_MODULE(clk_src);
530	field = clk_src % CCMR_CCGR_NSOURCE;
531	reg = ccm_read_4(ccm_softc, CCMC_CCGR(group));
532	reg &= ~(0x03 << field * 2);
533	reg |= (mode << field * 2);
534	ccm_write_4(ccm_softc, CCMC_CCGR(group), reg);
535}
536
537int
538imx51_get_clk_gating(int clk_src)
539{
540	uint32_t reg;
541
542	reg = ccm_read_4(ccm_softc,
543	    CCMC_CCGR(CCMR_CCGR_MODULE(clk_src)));
544	return ((reg >> (clk_src % CCMR_CCGR_NSOURCE) * 2) & 0x03);
545}
546
547/*
548 * Code from here down is temporary, in lieu of a SoC-independent clock API.
549 */
550
551void
552imx_ccm_usb_enable(device_t dev)
553{
554	uint32_t regval;
555
556	/*
557	 * Select PLL2 as the source for the USB clock.
558	 * The default is PLL3, but U-boot changes it to PLL2.
559	 */
560	regval = ccm_read_4(ccm_softc, CCMC_CSCMR1);
561	regval &= ~CSCMR1_USBOH3_CLK_SEL_MASK;
562	regval |= 1 << CSCMR1_USBOH3_CLK_SEL_SHIFT;
563	ccm_write_4(ccm_softc, CCMC_CSCMR1, regval);
564
565	/*
566	 * Set the USB clock pre-divider to div-by-5, post-divider to div-by-2.
567	 */
568	regval = ccm_read_4(ccm_softc, CCMC_CSCDR1);
569	regval &= ~CSCDR1_USBOH3_CLK_PODF_MASK;
570	regval &= ~CSCDR1_USBOH3_CLK_PRED_MASK;
571	regval |= 4 << CSCDR1_USBOH3_CLK_PRED_SHIFT;
572	regval |= 1 << CSCDR1_USBOH3_CLK_PODF_SHIFT;
573	ccm_write_4(ccm_softc, CCMC_CSCDR1, regval);
574
575	/*
576	 * The same two clocks gates are used on imx51 and imx53.
577	 */
578	imx51_clk_gating(CCGR_USBOH3_IPG_AHB_CLK, CCGR_CLK_MODE_ALWAYS);
579	imx51_clk_gating(CCGR_USBOH3_60M_CLK, CCGR_CLK_MODE_ALWAYS);
580}
581
582void
583imx_ccm_usbphy_enable(device_t dev)
584{
585	uint32_t regval;
586
587	/*
588	 * Select PLL3 as the source for the USBPHY clock.  U-boot does this
589	 * only for imx53, but the bit exists on imx51.  That seems a bit
590	 * strange, but we'll go with it until more is known.
591	 */
592	if (imx_soc_type() == IMXSOC_53) {
593		regval = ccm_read_4(ccm_softc, CCMC_CSCMR1);
594		regval |= 1 << CSCMR1_USBPHY_CLK_SEL_SHIFT;
595		ccm_write_4(ccm_softc, CCMC_CSCMR1, regval);
596	}
597
598	/*
599	 * For the imx51 there's just one phy gate control, enable it.
600	 */
601	if (imx_soc_type() == IMXSOC_51) {
602		imx51_clk_gating(CCGR_USB_PHY_CLK, CCGR_CLK_MODE_ALWAYS);
603		return;
604	}
605
606	/*
607	 * For imx53 we don't have a full set of clock defines yet, but the
608	 * datasheet says:
609	 *   gate reg 4, bits 13-12 usb ph2 clock (usb_phy2_clk_enable)
610	 *   gate reg 4, bits 11-10 usb ph1 clock (usb_phy1_clk_enable)
611	 *
612	 * We should use the fdt data for the device to figure out which of
613	 * the two we're working on, but for now just turn them both on.
614	 */
615	if (imx_soc_type() == IMXSOC_53) {
616		imx51_clk_gating(__CCGR_NUM(4, 5), CCGR_CLK_MODE_ALWAYS);
617		imx51_clk_gating(__CCGR_NUM(4, 6), CCGR_CLK_MODE_ALWAYS);
618		return;
619	}
620}
621
622uint32_t
623imx_ccm_ecspi_hz(void)
624{
625
626	return (imx51_get_clock(IMX51CLK_CSPI_CLK_ROOT));
627}
628
629uint32_t
630imx_ccm_ipg_hz(void)
631{
632
633	return (imx51_get_clock(IMX51CLK_IPG_CLK_ROOT));
634}
635
636uint32_t
637imx_ccm_sdhci_hz(void)
638{
639
640	return (imx51_get_clock(IMX51CLK_ESDHC1_CLK_ROOT));
641}
642
643uint32_t
644imx_ccm_perclk_hz(void)
645{
646
647	return (imx51_get_clock(IMX51CLK_PERCLK_ROOT));
648}
649
650uint32_t
651imx_ccm_uart_hz(void)
652{
653
654	return (imx51_get_clock(IMX51CLK_UART_CLK_ROOT));
655}
656
657uint32_t
658imx_ccm_ahb_hz(void)
659{
660
661	return (imx51_get_clock(IMX51CLK_AHB_CLK_ROOT));
662}
663
664