1 /* $NetBSD: imx51_ccm.c,v 1.1 2012/04/17 09:33:31 bsh Exp $ */
3 * Copyright (c) 2010, 2011, 2012 Genetec Corporation. All rights reserved.
4 * Written by Hashimoto Kenichi for Genetec Corporation.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
29 * Copyright (c) 2012, 2013 The FreeBSD Foundation
30 * All rights reserved.
32 * Portions of this software were developed by Oleksandr Rybalko
33 * under sponsorship from the FreeBSD Foundation.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
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.
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
58 * Clock Controller Module (CCM)
61 #include <sys/cdefs.h>
62 __FBSDID("$FreeBSD$");
64 #include <sys/param.h>
65 #include <sys/systm.h>
67 #include <sys/kernel.h>
68 #include <sys/module.h>
69 #include <sys/malloc.h>
71 #include <machine/bus.h>
72 #include <machine/cpu.h>
73 #include <machine/intr.h>
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>
80 #include <machine/bus.h>
81 #include <machine/fdt.h>
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>
92 #ifndef IMX51_OSC_FREQ
93 #define IMX51_OSC_FREQ (24 * 1000 * 1000) /* 24MHz */
96 #ifndef IMX51_CKIL_FREQ
97 #define IMX51_CKIL_FREQ 32768
100 struct imxccm_softc {
102 struct resource *res[7];
103 u_int64_t pll_freq[IMX51_N_DPLLS];
106 struct imxccm_softc *ccm_softc = NULL;
108 static uint64_t imx51_get_pll_freq(u_int);
110 static int imxccm_match(device_t);
111 static int imxccm_attach(device_t);
113 static device_method_t imxccm_methods[] = {
114 DEVMETHOD(device_probe, imxccm_match),
115 DEVMETHOD(device_attach, imxccm_attach),
120 static driver_t imxccm_driver = {
123 sizeof(struct imxccm_softc),
126 static devclass_t imxccm_devclass;
128 EARLY_DRIVER_MODULE(imxccm, simplebus, imxccm_driver, imxccm_devclass, 0, 0,
131 static 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 */
142 imxccm_match(device_t dev)
145 if (!ofw_bus_status_okay(dev))
148 if (!ofw_bus_is_compatible(dev, "fsl,imx51-ccm") &&
149 !ofw_bus_is_compatible(dev, "fsl,imx53-ccm"))
152 device_set_desc(dev, "Freescale Clock Control Module");
153 return (BUS_PROBE_DEFAULT);
157 imxccm_attach(device_t dev)
159 struct imxccm_softc *sc;
161 sc = device_get_softc(dev);
164 if (bus_alloc_resources(dev, imxccm_spec, sc->res)) {
165 device_printf(dev, "could not allocate resources\n");
171 imx51_get_pll_freq(1);
172 imx51_get_pll_freq(2);
173 imx51_get_pll_freq(3);
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));
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));
194 imx51_get_clock(enum imx51_clock clk)
198 uint32_t cacrr; /* ARM clock root register */
206 if (ccm_softc == NULL)
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];
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) {
224 return imx51_get_clock(IMX51CLK_LP_APM);
226 return 0; /* XXX PLL bypass clock */
228 return ccm_softc->pll_freq[2-1] /
229 (1 + ((ccsr & CCSR_PLL2_DIV_PODF_MASK) >>
230 CCSR_PLL2_DIV_PODF_SHIFT));
232 return ccm_softc->pll_freq[3-1] /
233 (1 + ((ccsr & CCSR_PLL3_DIV_PODF_MASK) >>
234 CCSR_PLL3_DIV_PODF_SHIFT));
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 */
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;
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);
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);
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) {
269 freq = imx51_get_clock(IMX51CLK_PLL1SW);
272 freq = imx51_get_clock(IMX51CLK_PLL3SW);
275 freq = imx51_get_clock(IMX51CLK_LP_APM);
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));
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);
306 freq = imx51_get_clock(IMX51CLK_MAIN_BUS_CLK_SRC);
307 cbcdr = bus_read_4(ccm_softc->res[0], CCMC_CBCDR);
310 printf("cbcmr=%x cbcdr=%x\n", cbcmr, cbcdr);
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);
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);
325 printf("cscdr1=%x cscmr1=%x\n", cscdr1, cscmr1);
328 sel = (cscmr1 & CSCMR1_UART_CLK_SEL_MASK) >>
329 CSCMR1_UART_CLK_SEL_SHIFT;
331 freq = 0; /* shut up GCC */
336 freq = imx51_get_clock(IMX51CLK_PLL1SW + sel);
339 freq = imx51_get_clock(IMX51CLK_LP_APM);
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:
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) {
353 freq = imx51_get_clock(IMX51CLK_ARM_AXI_A_CLK);
356 freq = imx51_get_clock(IMX51CLK_ARM_AXI_B_CLK);
359 freq = imx51_get_clock(
360 IMX51CLK_EMI_SLOW_CLK_ROOT);
363 freq = imx51_get_clock(IMX51CLK_AHB_CLK_ROOT);
368 device_printf(ccm_softc->sc_dev,
369 "clock %d: not supported yet\n", clk);
376 imx51_get_pll_freq(u_int pll_no)
390 KASSERT(1 <= pll_no && pll_no <= IMX51_N_DPLLS, ("Wrong PLL id"));
392 dp_ctrl = bus_read_4(ccm_softc->res[pll_no], DPLL_DP_CTL);
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);
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);
404 pdf = dp_op & DP_OP_PDF_MASK;
405 mfi = max(5, (dp_op & DP_OP_MFI_MASK) >> DP_OP_MFI_SHIFT);
407 if (dp_mfn & 0x04000000)
408 /* 27bit signed value */
409 mfn = (uint32_t)(0xf8000000 | dp_mfn);
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 */
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" */
425 /* TODO: get from FDT "fsl,imx-ckil" */
432 if (dp_ctrl & DP_CTL_REF_CLK_DIV)
436 freq = (int64_t)ref * mfi + (int64_t)ref * mfn / (mfd + 1);
439 if (!(dp_ctrl & DP_CTL_DPDCK0_2_EN))
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);
452 ccm_softc->pll_freq[pll_no-1] = freq;
458 imx51_clk_gating(int clk_src, int mode)
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);
472 imx51_get_clk_gating(int clk_src)
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);
482 * Code from here down is temporary, in lieu of a SoC-independent clock API.
486 imx_ccm_usb_enable(device_t dev)
491 * Select PLL2 as the source for the USB clock.
492 * The default is PLL3, but U-boot changes it to PLL2.
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);
500 * Set the USB clock pre-divider to div-by-5, post-divider to div-by-2.
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);
510 * The same two clocks gates are used on imx51 and imx53.
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);
517 imx_ccm_usbphy_enable(device_t dev)
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.
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);
533 * For the imx51 there's just one phy gate control, enable it.
535 if (imx_soc_type() == IMXSOC_51) {
536 imx51_clk_gating(CCGR_USB_PHY_CLK, CCGR_CLK_MODE_ALWAYS);
541 * For imx53 we don't have a full set of clock defines yet, but the
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)
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.
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);
560 return (imx51_get_clock(IMX51CLK_IPG_CLK_ROOT));
564 imx_ccm_sdhci_hz(void)
567 return (imx51_get_clock(IMX51CLK_ESDHC1_CLK_ROOT));
571 imx_ccm_perclk_hz(void)
574 return (imx51_get_clock(IMX51CLK_PERCLK_ROOT));
578 imx_ccm_uart_hz(void)
581 return (imx51_get_clock(IMX51CLK_UART_CLK_ROOT));
588 return (imx51_get_clock(IMX51CLK_AHB_CLK_ROOT));