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