1 /* $OpenBSD: imxccm.c,v 1.15 2019/04/01 08:49:35 patrick Exp $ */ 2 /* 3 * Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/queue.h> 21 #include <sys/malloc.h> 22 #include <sys/sysctl.h> 23 #include <sys/device.h> 24 #include <sys/evcount.h> 25 #include <sys/socket.h> 26 #include <sys/timeout.h> 27 28 #include <machine/intr.h> 29 #include <machine/bus.h> 30 #include <machine/fdt.h> 31 32 #include <dev/ofw/openfirm.h> 33 #include <dev/ofw/ofw_clock.h> 34 #include <dev/ofw/ofw_misc.h> 35 #include <dev/ofw/ofw_regulator.h> 36 #include <dev/ofw/fdt.h> 37 38 #include <dev/fdt/imxanatopvar.h> 39 40 /* registers */ 41 #define CCM_CCR 0x00 42 #define CCM_CCDR 0x04 43 #define CCM_CSR 0x08 44 #define CCM_CCSR 0x0c 45 #define CCM_CACRR 0x10 46 #define CCM_CBCDR 0x14 47 #define CCM_CBCMR 0x18 48 #define CCM_CSCMR1 0x1c 49 #define CCM_CSCMR2 0x20 50 #define CCM_CSCDR1 0x24 51 #define CCM_CS1CDR 0x28 52 #define CCM_CS2CDR 0x2c 53 #define CCM_CDCDR 0x30 54 #define CCM_CHSCCDR 0x34 55 #define CCM_CSCDR2 0x38 56 #define CCM_CSCDR3 0x3c 57 #define CCM_CSCDR4 0x40 58 #define CCM_CDHIPR 0x48 59 #define CCM_CDCR 0x4c 60 #define CCM_CTOR 0x50 61 #define CCM_CLPCR 0x54 62 #define CCM_CISR 0x58 63 #define CCM_CIMR 0x5c 64 #define CCM_CCOSR 0x60 65 #define CCM_CGPR 0x64 66 #define CCM_CCGR0 0x68 67 #define CCM_CCGR1 0x6c 68 #define CCM_CCGR2 0x70 69 #define CCM_CCGR3 0x74 70 #define CCM_CCGR4 0x78 71 #define CCM_CCGR5 0x7c 72 #define CCM_CCGR6 0x80 73 #define CCM_CCGR7 0x84 74 #define CCM_CMEOR 0x88 75 76 /* bits and bytes */ 77 #define CCM_CCSR_PLL3_SW_CLK_SEL (1 << 0) 78 #define CCM_CCSR_PLL2_SW_CLK_SEL (1 << 1) 79 #define CCM_CCSR_PLL1_SW_CLK_SEL (1 << 2) 80 #define CCM_CCSR_STEP_SEL (1 << 8) 81 #define CCM_CBCDR_IPG_PODF_SHIFT 8 82 #define CCM_CBCDR_IPG_PODF_MASK 0x3 83 #define CCM_CBCDR_AHB_PODF_SHIFT 10 84 #define CCM_CBCDR_AHB_PODF_MASK 0x7 85 #define CCM_CBCDR_PERIPH_CLK_SEL_SHIFT 25 86 #define CCM_CBCDR_PERIPH_CLK_SEL_MASK 0x1 87 #define CCM_CBCMR_PERIPH_CLK2_SEL_SHIFT 12 88 #define CCM_CBCMR_PERIPH_CLK2_SEL_MASK 0x3 89 #define CCM_CBCMR_PRE_PERIPH_CLK_SEL_SHIFT 18 90 #define CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK 0x3 91 #define CCM_CSCDR1_USDHCx_CLK_SEL_SHIFT(x) ((x) + 15) 92 #define CCM_CSCDR1_USDHCx_CLK_SEL_MASK 0x1 93 #define CCM_CSCDR1_USDHCx_PODF_MASK 0x7 94 #define CCM_CSCDR1_UART_PODF_MASK 0x7 95 #define CCM_CSCDR2_ECSPI_PODF_SHIFT 19 96 #define CCM_CSCDR2_ECSPI_PODF_MASK 0x7 97 #define CCM_CCGR1_ENET (3 << 10) 98 #define CCM_CCGR4_125M_PCIE (3 << 0) 99 #define CCM_CCGR5_100M_SATA (3 << 4) 100 #define CCM_CSCMR1_PERCLK_CLK_PODF_MASK 0x1f 101 #define CCM_CSCMR1_PERCLK_CLK_SEL_MASK (1 << 6) 102 103 /* Analog registers */ 104 #define CCM_ANALOG_PLL_USB1 0x0010 105 #define CCM_ANALOG_PLL_USB1_SET 0x0014 106 #define CCM_ANALOG_PLL_USB1_CLR 0x0018 107 #define CCM_ANALOG_PLL_USB1_LOCK (1U << 31) 108 #define CCM_ANALOG_PLL_USB1_BYPASS (1 << 16) 109 #define CCM_ANALOG_PLL_USB1_ENABLE (1 << 13) 110 #define CCM_ANALOG_PLL_USB1_POWER (1 << 12) 111 #define CCM_ANALOG_PLL_USB1_EN_USB_CLKS (1 << 6) 112 #define CCM_ANALOG_PLL_USB2 0x0020 113 #define CCM_ANALOG_PLL_USB2_SET 0x0024 114 #define CCM_ANALOG_PLL_USB2_CLR 0x0028 115 #define CCM_ANALOG_PLL_USB2_LOCK (1U << 31) 116 #define CCM_ANALOG_PLL_USB2_BYPASS (1 << 16) 117 #define CCM_ANALOG_PLL_USB2_ENABLE (1 << 13) 118 #define CCM_ANALOG_PLL_USB2_POWER (1 << 12) 119 #define CCM_ANALOG_PLL_USB2_EN_USB_CLKS (1 << 6) 120 #define CCM_ANALOG_PLL_ENET 0x00e0 121 #define CCM_ANALOG_PLL_ENET_SET 0x00e4 122 #define CCM_ANALOG_PLL_ENET_CLR 0x00e8 123 #define CCM_ANALOG_PLL_ENET_LOCK (1U << 31) 124 #define CCM_ANALOG_PLL_ENET_ENABLE_100M (1 << 20) /* i.MX6 */ 125 #define CCM_ANALOG_PLL_ENET_BYPASS (1 << 16) 126 #define CCM_ANALOG_PLL_ENET_ENABLE (1 << 13) /* i.MX6 */ 127 #define CCM_ANALOG_PLL_ENET_POWERDOWN (1 << 12) /* i.MX6 */ 128 #define CCM_ANALOG_PLL_ENET_ENABLE_CLK_125MHZ (1 << 10) /* i.MX7 */ 129 130 /* Frac PLL */ 131 #define CCM_FRAC_IMX8M_ARM_PLL0 0x28 132 #define CCM_FRAC_IMX8M_ARM_PLL1 0x2c 133 #define CCM_FRAC_PLL_LOCK (1 << 31) 134 #define CCM_FRAC_PLL_ENABLE (1 << 21) 135 #define CCM_FRAC_PLL_POWERDOWN (1 << 19) 136 #define CCM_FRAC_PLL_REFCLK_SEL_SHIFT 16 137 #define CCM_FRAC_PLL_REFCLK_SEL_MASK 0x3 138 #define CCM_FRAC_PLL_LOCK_SEL (1 << 15) 139 #define CCM_FRAC_PLL_BYPASS (1 << 14) 140 #define CCM_FRAC_PLL_COUNTCLK_SEL (1 << 13) 141 #define CCM_FRAC_PLL_NEWDIV_VAL (1 << 12) 142 #define CCM_FRAC_PLL_NEWDIV_ACK (1 << 11) 143 #define CCM_FRAC_PLL_REFCLK_DIV_VAL_SHIFT 5 144 #define CCM_FRAC_PLL_REFCLK_DIV_VAL_MASK 0x3f 145 #define CCM_FRAC_PLL_OUTPUT_DIV_VAL_SHIFT 0 146 #define CCM_FRAC_PLL_OUTPUT_DIV_VAL_MASK 0x1f 147 #define CCM_FRAC_PLL_FRAC_DIV_CTL_SHIFT 7 148 #define CCM_FRAC_PLL_FRAC_DIV_CTL_MASK 0x1ffffff 149 #define CCM_FRAC_PLL_INT_DIV_CTL_SHIFT 0 150 #define CCM_FRAC_PLL_INT_DIV_CTL_MASK 0x7f 151 #define CCM_FRAC_PLL_DENOM (1 << 24) 152 #define CCM_FRAC_IMX8M_PLLOUT_DIV_CFG 0x78 153 #define CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_SHIFT 20 154 #define CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_MASK 0x7 155 156 #define HCLK_FREQ 24000000 157 #define PLL3_60M 60000000 158 #define PLL3_80M 80000000 159 160 #define HREAD4(sc, reg) \ 161 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) 162 #define HWRITE4(sc, reg, val) \ 163 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 164 #define HSET4(sc, reg, bits) \ 165 HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits)) 166 #define HCLR4(sc, reg, bits) \ 167 HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits)) 168 169 struct imxccm_gate { 170 uint16_t reg; 171 uint8_t pos; 172 uint16_t parent; 173 }; 174 175 struct imxccm_divider { 176 uint16_t reg; 177 uint16_t shift; 178 uint16_t mask; 179 uint16_t parent; 180 uint16_t fixed; 181 }; 182 183 struct imxccm_mux { 184 uint16_t reg; 185 uint16_t shift; 186 uint16_t mask; 187 }; 188 189 #include "imxccm_clocks.h" 190 191 struct imxccm_softc { 192 struct device sc_dev; 193 bus_space_tag_t sc_iot; 194 bus_space_handle_t sc_ioh; 195 int sc_node; 196 uint32_t sc_phandle; 197 198 struct regmap *sc_anatop; 199 200 struct imxccm_gate *sc_gates; 201 int sc_ngates; 202 struct imxccm_divider *sc_divs; 203 int sc_ndivs; 204 struct imxccm_mux *sc_muxs; 205 int sc_nmuxs; 206 struct imxccm_divider *sc_predivs; 207 int sc_npredivs; 208 struct clock_device sc_cd; 209 }; 210 211 int imxccm_match(struct device *, void *, void *); 212 void imxccm_attach(struct device *parent, struct device *self, void *args); 213 214 struct cfattach imxccm_ca = { 215 sizeof (struct imxccm_softc), imxccm_match, imxccm_attach 216 }; 217 218 struct cfdriver imxccm_cd = { 219 NULL, "imxccm", DV_DULL 220 }; 221 222 uint32_t imxccm_get_armclk(struct imxccm_softc *); 223 void imxccm_armclk_set_parent(struct imxccm_softc *, enum imxanatop_clocks); 224 uint32_t imxccm_get_usdhx(struct imxccm_softc *, int x); 225 uint32_t imxccm_get_periphclk(struct imxccm_softc *); 226 uint32_t imxccm_get_ahbclk(struct imxccm_softc *); 227 uint32_t imxccm_get_ipgclk(struct imxccm_softc *); 228 uint32_t imxccm_get_ipg_perclk(struct imxccm_softc *); 229 uint32_t imxccm_get_uartclk(struct imxccm_softc *); 230 uint32_t imxccm_imx8mq_ecspi(struct imxccm_softc *sc, uint32_t); 231 uint32_t imxccm_imx8mq_enet(struct imxccm_softc *sc, uint32_t); 232 uint32_t imxccm_imx8mq_i2c(struct imxccm_softc *sc, uint32_t); 233 uint32_t imxccm_imx8mq_pwm(struct imxccm_softc *sc, uint32_t); 234 uint32_t imxccm_imx8mq_uart(struct imxccm_softc *sc, uint32_t); 235 uint32_t imxccm_imx8mq_usdhc(struct imxccm_softc *sc, uint32_t); 236 uint32_t imxccm_imx8mq_usb(struct imxccm_softc *sc, uint32_t); 237 void imxccm_enable(void *, uint32_t *, int); 238 uint32_t imxccm_get_frequency(void *, uint32_t *); 239 int imxccm_set_frequency(void *, uint32_t *, uint32_t); 240 int imxccm_set_parent(void *, uint32_t *, uint32_t *); 241 242 int 243 imxccm_match(struct device *parent, void *match, void *aux) 244 { 245 struct fdt_attach_args *faa = aux; 246 247 return (OF_is_compatible(faa->fa_node, "fsl,imx6q-ccm") || 248 OF_is_compatible(faa->fa_node, "fsl,imx6sl-ccm") || 249 OF_is_compatible(faa->fa_node, "fsl,imx6sx-ccm") || 250 OF_is_compatible(faa->fa_node, "fsl,imx6ul-ccm") || 251 OF_is_compatible(faa->fa_node, "fsl,imx7d-ccm") || 252 OF_is_compatible(faa->fa_node, "fsl,imx8mq-ccm")); 253 } 254 255 void 256 imxccm_attach(struct device *parent, struct device *self, void *aux) 257 { 258 struct imxccm_softc *sc = (struct imxccm_softc *)self; 259 struct fdt_attach_args *faa = aux; 260 261 KASSERT(faa->fa_nreg >= 1); 262 263 sc->sc_node = faa->fa_node; 264 sc->sc_iot = faa->fa_iot; 265 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 266 faa->fa_reg[0].size, 0, &sc->sc_ioh)) 267 panic("%s: bus_space_map failed!", __func__); 268 269 sc->sc_phandle = OF_getpropint(sc->sc_node, "phandle", 0); 270 271 if (OF_is_compatible(sc->sc_node, "fsl,imx8mq-ccm")) { 272 sc->sc_anatop = regmap_bycompatible("fsl,imx8mq-anatop"); 273 KASSERT(sc->sc_anatop != NULL); 274 sc->sc_gates = imx8mq_gates; 275 sc->sc_ngates = nitems(imx8mq_gates); 276 sc->sc_divs = imx8mq_divs; 277 sc->sc_ndivs = nitems(imx8mq_divs); 278 sc->sc_muxs = imx8mq_muxs; 279 sc->sc_nmuxs = nitems(imx8mq_muxs); 280 sc->sc_predivs = imx8mq_predivs; 281 sc->sc_npredivs = nitems(imx8mq_predivs); 282 } else if (OF_is_compatible(sc->sc_node, "fsl,imx7d-ccm")) { 283 sc->sc_gates = imx7d_gates; 284 sc->sc_ngates = nitems(imx7d_gates); 285 sc->sc_divs = imx7d_divs; 286 sc->sc_ndivs = nitems(imx7d_divs); 287 sc->sc_muxs = imx7d_muxs; 288 sc->sc_nmuxs = nitems(imx7d_muxs); 289 } else if (OF_is_compatible(sc->sc_node, "fsl,imx6ul-ccm")) { 290 sc->sc_gates = imx6ul_gates; 291 sc->sc_ngates = nitems(imx6ul_gates); 292 } else { 293 sc->sc_gates = imx6_gates; 294 sc->sc_ngates = nitems(imx6_gates); 295 } 296 297 printf("\n"); 298 299 sc->sc_cd.cd_node = faa->fa_node; 300 sc->sc_cd.cd_cookie = sc; 301 sc->sc_cd.cd_enable = imxccm_enable; 302 sc->sc_cd.cd_get_frequency = imxccm_get_frequency; 303 sc->sc_cd.cd_set_frequency = imxccm_set_frequency; 304 sc->sc_cd.cd_set_parent = imxccm_set_parent; 305 clock_register(&sc->sc_cd); 306 } 307 308 uint32_t 309 imxccm_get_armclk(struct imxccm_softc *sc) 310 { 311 uint32_t ccsr = HREAD4(sc, CCM_CCSR); 312 313 if (!(ccsr & CCM_CCSR_PLL1_SW_CLK_SEL)) 314 return imxanatop_decode_pll(ARM_PLL1, HCLK_FREQ); 315 else if (ccsr & CCM_CCSR_STEP_SEL) 316 return imxanatop_get_pll2_pfd(2); 317 else 318 return HCLK_FREQ; 319 } 320 321 void 322 imxccm_armclk_set_parent(struct imxccm_softc *sc, enum imxanatop_clocks clock) 323 { 324 switch (clock) 325 { 326 case ARM_PLL1: 327 /* jump onto pll1 */ 328 HCLR4(sc, CCM_CCSR, CCM_CCSR_PLL1_SW_CLK_SEL); 329 /* put step clk on OSC, power saving */ 330 HCLR4(sc, CCM_CCSR, CCM_CCSR_STEP_SEL); 331 break; 332 case OSC: 333 /* put step clk on OSC */ 334 HCLR4(sc, CCM_CCSR, CCM_CCSR_STEP_SEL); 335 /* jump onto step clk */ 336 HSET4(sc, CCM_CCSR, CCM_CCSR_PLL1_SW_CLK_SEL); 337 break; 338 case SYS_PLL2_PFD2: 339 /* put step clk on pll2-pfd2 400 MHz */ 340 HSET4(sc, CCM_CCSR, CCM_CCSR_STEP_SEL); 341 /* jump onto step clk */ 342 HSET4(sc, CCM_CCSR, CCM_CCSR_PLL1_SW_CLK_SEL); 343 break; 344 default: 345 panic("%s: parent not possible for arm clk", __func__); 346 } 347 } 348 349 uint32_t 350 imxccm_get_ecspiclk(struct imxccm_softc *sc) 351 { 352 uint32_t clkroot = PLL3_60M; 353 uint32_t podf = HREAD4(sc, CCM_CSCDR2); 354 355 podf >>= CCM_CSCDR2_ECSPI_PODF_SHIFT; 356 podf &= CCM_CSCDR2_ECSPI_PODF_MASK; 357 358 return clkroot / (podf + 1); 359 } 360 361 unsigned int 362 imxccm_get_usdhx(struct imxccm_softc *sc, int x) 363 { 364 uint32_t cscmr1 = HREAD4(sc, CCM_CSCMR1); 365 uint32_t cscdr1 = HREAD4(sc, CCM_CSCDR1); 366 uint32_t podf, clkroot; 367 368 // Odd bitsetting. Damn you. 369 if (x == 1) 370 podf = ((cscdr1 >> 11) & CCM_CSCDR1_USDHCx_PODF_MASK); 371 else 372 podf = ((cscdr1 >> (10 + 3*x)) & CCM_CSCDR1_USDHCx_PODF_MASK); 373 374 if (cscmr1 & (1 << CCM_CSCDR1_USDHCx_CLK_SEL_SHIFT(x))) 375 clkroot = imxanatop_get_pll2_pfd(0); // 352 MHz 376 else 377 clkroot = imxanatop_get_pll2_pfd(2); // 396 MHz 378 379 return clkroot / (podf + 1); 380 } 381 382 uint32_t 383 imxccm_get_uartclk(struct imxccm_softc *sc) 384 { 385 uint32_t clkroot = PLL3_80M; 386 uint32_t podf = HREAD4(sc, CCM_CSCDR1) & CCM_CSCDR1_UART_PODF_MASK; 387 388 return clkroot / (podf + 1); 389 } 390 391 uint32_t 392 imxccm_get_periphclk(struct imxccm_softc *sc) 393 { 394 if ((HREAD4(sc, CCM_CBCDR) >> CCM_CBCDR_PERIPH_CLK_SEL_SHIFT) 395 & CCM_CBCDR_PERIPH_CLK_SEL_MASK) { 396 switch((HREAD4(sc, CCM_CBCMR) 397 >> CCM_CBCMR_PERIPH_CLK2_SEL_SHIFT) & CCM_CBCMR_PERIPH_CLK2_SEL_MASK) { 398 case 0: 399 return imxanatop_decode_pll(USB1_PLL3, HCLK_FREQ); 400 case 1: 401 case 2: 402 return HCLK_FREQ; 403 default: 404 return 0; 405 } 406 407 } else { 408 switch((HREAD4(sc, CCM_CBCMR) 409 >> CCM_CBCMR_PRE_PERIPH_CLK_SEL_SHIFT) & CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK) { 410 default: 411 case 0: 412 return imxanatop_decode_pll(SYS_PLL2, HCLK_FREQ); 413 case 1: 414 return imxanatop_get_pll2_pfd(2); // 396 MHz 415 case 2: 416 return imxanatop_get_pll2_pfd(0); // 352 MHz 417 case 3: 418 return imxanatop_get_pll2_pfd(2) / 2; // 198 MHz 419 } 420 } 421 } 422 423 uint32_t 424 imxccm_get_ahbclk(struct imxccm_softc *sc) 425 { 426 uint32_t ahb_podf; 427 428 ahb_podf = (HREAD4(sc, CCM_CBCDR) >> CCM_CBCDR_AHB_PODF_SHIFT) 429 & CCM_CBCDR_AHB_PODF_MASK; 430 return imxccm_get_periphclk(sc) / (ahb_podf + 1); 431 } 432 433 uint32_t 434 imxccm_get_ipgclk(struct imxccm_softc *sc) 435 { 436 uint32_t ipg_podf; 437 438 ipg_podf = (HREAD4(sc, CCM_CBCDR) >> CCM_CBCDR_IPG_PODF_SHIFT) 439 & CCM_CBCDR_IPG_PODF_MASK; 440 return imxccm_get_ahbclk(sc) / (ipg_podf + 1); 441 } 442 443 uint32_t 444 imxccm_get_ipg_perclk(struct imxccm_softc *sc) 445 { 446 uint32_t cscmr1 = HREAD4(sc, CCM_CSCMR1); 447 uint32_t freq, ipg_podf; 448 449 if (sc->sc_gates == imx6ul_gates && 450 cscmr1 & CCM_CSCMR1_PERCLK_CLK_SEL_MASK) 451 freq = HCLK_FREQ; 452 else 453 freq = imxccm_get_ipgclk(sc); 454 455 ipg_podf = cscmr1 & CCM_CSCMR1_PERCLK_CLK_PODF_MASK; 456 457 return freq / (ipg_podf + 1); 458 } 459 460 void 461 imxccm_imx6_enable_pll_enet(struct imxccm_softc *sc, int on) 462 { 463 KASSERT(on); 464 465 regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_ENET_CLR, 466 CCM_ANALOG_PLL_ENET_POWERDOWN); 467 468 /* Wait for the PLL to lock. */ 469 while ((regmap_read_4(sc->sc_anatop, 470 CCM_ANALOG_PLL_ENET) & CCM_ANALOG_PLL_ENET_LOCK) == 0) 471 ; 472 473 regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_ENET_CLR, 474 CCM_ANALOG_PLL_ENET_BYPASS); 475 } 476 477 void 478 imxccm_imx6_enable_pll_usb1(struct imxccm_softc *sc, int on) 479 { 480 KASSERT(on); 481 482 regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB1_SET, 483 CCM_ANALOG_PLL_USB1_POWER); 484 485 /* Wait for the PLL to lock. */ 486 while ((regmap_read_4(sc->sc_anatop, 487 CCM_ANALOG_PLL_USB1) & CCM_ANALOG_PLL_USB1_LOCK) == 0) 488 ; 489 490 regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB1_CLR, 491 CCM_ANALOG_PLL_USB1_BYPASS); 492 } 493 494 void 495 imxccm_imx6_enable_pll_usb2(struct imxccm_softc *sc, int on) 496 { 497 KASSERT(on); 498 499 regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB2_SET, 500 CCM_ANALOG_PLL_USB2_POWER); 501 502 /* Wait for the PLL to lock. */ 503 while ((regmap_read_4(sc->sc_anatop, 504 CCM_ANALOG_PLL_USB2) & CCM_ANALOG_PLL_USB2_LOCK) == 0) 505 ; 506 507 regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB2_CLR, 508 CCM_ANALOG_PLL_USB2_BYPASS); 509 } 510 511 uint32_t 512 imxccm_imx7d_enet(struct imxccm_softc *sc, uint32_t idx) 513 { 514 uint32_t mux; 515 516 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 517 return 0; 518 519 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 520 mux >>= sc->sc_muxs[idx].shift; 521 mux &= sc->sc_muxs[idx].mask; 522 523 switch (mux) { 524 case 0: 525 return clock_get_frequency(sc->sc_node, "osc"); 526 case 7: 527 return 392000000; /* pll_sys_pfd4_clk XXX not fixed */ 528 default: 529 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 530 return 0; 531 } 532 } 533 534 uint32_t 535 imxccm_imx7d_i2c(struct imxccm_softc *sc, uint32_t idx) 536 { 537 uint32_t mux; 538 539 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 540 return 0; 541 542 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 543 mux >>= sc->sc_muxs[idx].shift; 544 mux &= sc->sc_muxs[idx].mask; 545 546 switch (mux) { 547 case 0: 548 return clock_get_frequency(sc->sc_node, "osc"); 549 case 1: 550 return 120000000; /* pll_sys_main_120m_clk */ 551 default: 552 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 553 return 0; 554 } 555 } 556 557 uint32_t 558 imxccm_imx7d_uart(struct imxccm_softc *sc, uint32_t idx) 559 { 560 uint32_t mux; 561 562 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 563 return 0; 564 565 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 566 mux >>= sc->sc_muxs[idx].shift; 567 mux &= sc->sc_muxs[idx].mask; 568 569 switch (mux) { 570 case 0: 571 return clock_get_frequency(sc->sc_node, "osc"); 572 default: 573 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 574 return 0; 575 } 576 } 577 578 uint32_t 579 imxccm_imx7d_usdhc(struct imxccm_softc *sc, uint32_t idx) 580 { 581 uint32_t mux; 582 583 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 584 return 0; 585 586 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 587 mux >>= sc->sc_muxs[idx].shift; 588 mux &= sc->sc_muxs[idx].mask; 589 590 switch (mux) { 591 case 0: 592 return clock_get_frequency(sc->sc_node, "osc"); 593 case 1: 594 return 392000000; /* pll_sys_pfd0_392m_clk */ 595 default: 596 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 597 return 0; 598 } 599 } 600 601 uint32_t 602 imxccm_imx8mq_ecspi(struct imxccm_softc *sc, uint32_t idx) 603 { 604 uint32_t mux; 605 606 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 607 return 0; 608 609 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 610 mux >>= sc->sc_muxs[idx].shift; 611 mux &= sc->sc_muxs[idx].mask; 612 613 switch (mux) { 614 case 0: 615 return clock_get_frequency(sc->sc_node, "osc_25m"); 616 case 1: 617 return 200 * 1000 * 1000; /* sys2_pll_200m */ 618 default: 619 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 620 return 0; 621 } 622 } 623 624 uint32_t 625 imxccm_imx8mq_enet(struct imxccm_softc *sc, uint32_t idx) 626 { 627 uint32_t mux; 628 629 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 630 return 0; 631 632 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 633 mux >>= sc->sc_muxs[idx].shift; 634 mux &= sc->sc_muxs[idx].mask; 635 636 switch (mux) { 637 case 0: 638 return clock_get_frequency(sc->sc_node, "osc_25m"); 639 case 1: 640 return 266 * 1000 * 1000; /* sys1_pll_266m */ 641 default: 642 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 643 return 0; 644 } 645 } 646 647 uint32_t 648 imxccm_imx8mq_i2c(struct imxccm_softc *sc, uint32_t idx) 649 { 650 uint32_t mux; 651 652 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 653 return 0; 654 655 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 656 mux >>= sc->sc_muxs[idx].shift; 657 mux &= sc->sc_muxs[idx].mask; 658 659 switch (mux) { 660 case 0: 661 return clock_get_frequency(sc->sc_node, "osc_25m"); 662 default: 663 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 664 return 0; 665 } 666 } 667 668 uint32_t 669 imxccm_imx8mq_pwm(struct imxccm_softc *sc, uint32_t idx) 670 { 671 uint32_t mux; 672 673 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 674 return 0; 675 676 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 677 mux >>= sc->sc_muxs[idx].shift; 678 mux &= sc->sc_muxs[idx].mask; 679 680 switch (mux) { 681 case 0: 682 return clock_get_frequency(sc->sc_node, "osc_25m"); 683 case 1: 684 return 100 * 1000 * 1000; /* sys1_pll_100m */ 685 case 2: 686 return 160 * 1000 * 1000; /* sys1_pll_160m */ 687 case 3: 688 return 40 * 1000 * 1000; /* sys1_pll_40m */ 689 default: 690 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 691 return 0; 692 } 693 } 694 695 uint32_t 696 imxccm_imx8mq_uart(struct imxccm_softc *sc, uint32_t idx) 697 { 698 uint32_t mux; 699 700 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 701 return 0; 702 703 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 704 mux >>= sc->sc_muxs[idx].shift; 705 mux &= sc->sc_muxs[idx].mask; 706 707 switch (mux) { 708 case 0: 709 return clock_get_frequency(sc->sc_node, "osc_25m"); 710 default: 711 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 712 return 0; 713 } 714 } 715 716 uint32_t 717 imxccm_imx8mq_usdhc(struct imxccm_softc *sc, uint32_t idx) 718 { 719 uint32_t mux; 720 721 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 722 return 0; 723 724 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 725 mux >>= sc->sc_muxs[idx].shift; 726 mux &= sc->sc_muxs[idx].mask; 727 728 switch (mux) { 729 case 0: 730 return clock_get_frequency(sc->sc_node, "osc_25m"); 731 case 1: 732 return 400 * 1000 * 1000; /* sys1_pll_400m */ 733 default: 734 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 735 return 0; 736 } 737 } 738 739 uint32_t 740 imxccm_imx8mq_usb(struct imxccm_softc *sc, uint32_t idx) 741 { 742 uint32_t mux; 743 744 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 745 return 0; 746 747 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 748 mux >>= sc->sc_muxs[idx].shift; 749 mux &= sc->sc_muxs[idx].mask; 750 751 switch (mux) { 752 case 0: 753 return clock_get_frequency(sc->sc_node, "osc_25m"); 754 case 1: 755 if (idx == IMX8MQ_CLK_USB_CORE_REF || 756 idx == IMX8MQ_CLK_USB_PHY_REF) 757 return 100 * 1000 * 1000; /* sys1_pll_100m */ 758 if (idx == IMX8MQ_CLK_USB_BUS) 759 return 500 * 1000 * 1000; /* sys2_pll_500m */ 760 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 761 return 0; 762 default: 763 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 764 return 0; 765 } 766 } 767 768 uint32_t 769 imxccm_imx8mq_get_pll(struct imxccm_softc *sc, uint32_t idx) 770 { 771 uint32_t divr_val, divq_val, divf_val; 772 uint32_t divff, divfi; 773 uint32_t pllout_div; 774 uint32_t pll0, pll1; 775 uint32_t freq; 776 uint32_t mux; 777 778 pllout_div = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_PLLOUT_DIV_CFG); 779 780 switch (idx) { 781 case IMX8MQ_ARM_PLL: 782 pll0 = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_ARM_PLL0); 783 pll1 = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_ARM_PLL1); 784 pllout_div >>= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_SHIFT; 785 pllout_div &= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_MASK; 786 break; 787 default: 788 printf("%s: 0x%08x\n", __func__, idx); 789 return 0; 790 } 791 792 if (pll0 & CCM_FRAC_PLL_POWERDOWN) 793 return 0; 794 795 if ((pll0 & CCM_FRAC_PLL_ENABLE) == 0) 796 return 0; 797 798 mux = (pll0 >> CCM_FRAC_PLL_REFCLK_SEL_SHIFT) & 799 CCM_FRAC_PLL_REFCLK_SEL_MASK; 800 switch (mux) { 801 case 0: 802 freq = clock_get_frequency(sc->sc_node, "osc_25m"); 803 break; 804 case 1: 805 case 2: 806 freq = clock_get_frequency(sc->sc_node, "osc_27m"); 807 break; 808 default: 809 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 810 return 0; 811 } 812 813 if (pll0 & CCM_FRAC_PLL_BYPASS) 814 return freq; 815 816 divr_val = (pll0 >> CCM_FRAC_PLL_REFCLK_DIV_VAL_SHIFT) & 817 CCM_FRAC_PLL_REFCLK_DIV_VAL_MASK; 818 divq_val = pll0 & CCM_FRAC_PLL_OUTPUT_DIV_VAL_MASK; 819 divff = (pll1 >> CCM_FRAC_PLL_FRAC_DIV_CTL_SHIFT) & 820 CCM_FRAC_PLL_FRAC_DIV_CTL_MASK; 821 divfi = pll1 & CCM_FRAC_PLL_INT_DIV_CTL_MASK; 822 divf_val = 1 + divfi + divff / CCM_FRAC_PLL_DENOM; 823 824 freq = freq / (divr_val + 1) * 8 * divf_val / ((divq_val + 1) * 2); 825 return freq / (pllout_div + 1); 826 } 827 828 int 829 imxccm_imx8mq_set_pll(struct imxccm_softc *sc, uint32_t idx, uint64_t freq) 830 { 831 uint64_t divff, divfi, divr; 832 uint32_t pllout_div; 833 uint32_t pll0, pll1; 834 uint32_t mux, reg; 835 uint64_t pfreq; 836 int i; 837 838 pllout_div = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_PLLOUT_DIV_CFG); 839 840 switch (idx) { 841 case IMX8MQ_ARM_PLL: 842 pll0 = CCM_FRAC_IMX8M_ARM_PLL0; 843 pll1 = CCM_FRAC_IMX8M_ARM_PLL1; 844 pllout_div >>= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_SHIFT; 845 pllout_div &= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_MASK; 846 /* XXX: Assume fixed divider to ease math. */ 847 KASSERT(pllout_div == 0); 848 divr = 5; 849 break; 850 default: 851 printf("%s: 0x%08x\n", __func__, idx); 852 return -1; 853 } 854 855 reg = regmap_read_4(sc->sc_anatop, pll0); 856 mux = (reg >> CCM_FRAC_PLL_REFCLK_SEL_SHIFT) & 857 CCM_FRAC_PLL_REFCLK_SEL_MASK; 858 switch (mux) { 859 case 0: 860 pfreq = clock_get_frequency(sc->sc_node, "osc_25m"); 861 break; 862 case 1: 863 case 2: 864 pfreq = clock_get_frequency(sc->sc_node, "osc_27m"); 865 break; 866 default: 867 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 868 return -1; 869 } 870 871 /* Frac divider follows the PLL */ 872 freq *= divr; 873 874 /* PLL calculation */ 875 freq *= 2; 876 pfreq *= 8; 877 divfi = freq / pfreq; 878 divff = (uint64_t)(freq - divfi * pfreq); 879 divff = (divff * CCM_FRAC_PLL_DENOM) / pfreq; 880 881 reg = regmap_read_4(sc->sc_anatop, pll1); 882 reg &= ~(CCM_FRAC_PLL_FRAC_DIV_CTL_MASK << CCM_FRAC_PLL_FRAC_DIV_CTL_SHIFT); 883 reg |= divff << CCM_FRAC_PLL_FRAC_DIV_CTL_SHIFT; 884 reg &= ~(CCM_FRAC_PLL_INT_DIV_CTL_MASK << CCM_FRAC_PLL_INT_DIV_CTL_SHIFT); 885 reg |= (divfi - 1) << CCM_FRAC_PLL_INT_DIV_CTL_SHIFT; 886 regmap_write_4(sc->sc_anatop, pll1, reg); 887 888 reg = regmap_read_4(sc->sc_anatop, pll0); 889 reg &= ~CCM_FRAC_PLL_OUTPUT_DIV_VAL_MASK; 890 reg &= ~(CCM_FRAC_PLL_REFCLK_DIV_VAL_MASK << CCM_FRAC_PLL_REFCLK_DIV_VAL_SHIFT); 891 reg |= (divr - 1) << CCM_FRAC_PLL_REFCLK_DIV_VAL_SHIFT; 892 regmap_write_4(sc->sc_anatop, pll0, reg); 893 894 reg = regmap_read_4(sc->sc_anatop, pll0); 895 reg |= CCM_FRAC_PLL_NEWDIV_VAL; 896 regmap_write_4(sc->sc_anatop, pll0, reg); 897 898 for (i = 0; i < 5000; i++) { 899 reg = regmap_read_4(sc->sc_anatop, pll0); 900 if (reg & CCM_FRAC_PLL_BYPASS) 901 break; 902 if (reg & CCM_FRAC_PLL_POWERDOWN) 903 break; 904 if (reg & CCM_FRAC_PLL_NEWDIV_ACK) 905 break; 906 delay(10); 907 } 908 if (i == 5000) 909 printf("%s: timeout\n", __func__); 910 911 reg = regmap_read_4(sc->sc_anatop, pll0); 912 reg &= ~CCM_FRAC_PLL_NEWDIV_VAL; 913 regmap_write_4(sc->sc_anatop, pll0, reg); 914 915 return 0; 916 } 917 918 void 919 imxccm_enable_parent(struct imxccm_softc *sc, uint32_t parent, int on) 920 { 921 if (on) 922 imxccm_enable(sc, &parent, on); 923 } 924 925 void 926 imxccm_enable(void *cookie, uint32_t *cells, int on) 927 { 928 struct imxccm_softc *sc = cookie; 929 uint32_t idx = cells[0], parent; 930 uint16_t reg; 931 uint8_t pos; 932 933 /* Dummy clock. */ 934 if (idx == 0) 935 return; 936 937 if (sc->sc_gates == imx7d_gates) { 938 if (sc->sc_anatop == NULL) { 939 sc->sc_anatop = regmap_bycompatible("fsl,imx7d-anatop"); 940 KASSERT(sc->sc_anatop); 941 } 942 943 switch (idx) { 944 case IMX7D_PLL_ENET_MAIN_125M_CLK: 945 regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_ENET_SET, 946 CCM_ANALOG_PLL_ENET_ENABLE_CLK_125MHZ); 947 return; 948 default: 949 break; 950 } 951 } else if (sc->sc_gates == imx6_gates) { 952 if (sc->sc_anatop == NULL) { 953 sc->sc_anatop = regmap_bycompatible("fsl,imx6q-anatop"); 954 KASSERT(sc->sc_anatop); 955 } 956 957 switch (idx) { 958 case IMX6_CLK_PLL3: 959 imxccm_imx6_enable_pll_usb1(sc, on); 960 return; 961 case IMX6_CLK_PLL6: 962 imxccm_imx6_enable_pll_enet(sc, on); 963 return; 964 case IMX6_CLK_PLL7: 965 imxccm_imx6_enable_pll_usb2(sc, on); 966 return; 967 case IMX6_CLK_PLL3_USB_OTG: 968 imxccm_enable_parent(sc, IMX6_CLK_PLL3, on); 969 regmap_write_4(sc->sc_anatop, 970 on ? CCM_ANALOG_PLL_USB1_SET : CCM_ANALOG_PLL_USB1_CLR, 971 CCM_ANALOG_PLL_USB1_ENABLE); 972 return; 973 case IMX6_CLK_PLL6_ENET: 974 imxccm_enable_parent(sc, IMX6_CLK_PLL6, on); 975 regmap_write_4(sc->sc_anatop, 976 on ? CCM_ANALOG_PLL_ENET_SET : CCM_ANALOG_PLL_ENET_CLR, 977 CCM_ANALOG_PLL_ENET_ENABLE); 978 return; 979 case IMX6_CLK_PLL7_USB_HOST: 980 imxccm_enable_parent(sc, IMX6_CLK_PLL7, on); 981 regmap_write_4(sc->sc_anatop, 982 on ? CCM_ANALOG_PLL_USB2_SET : CCM_ANALOG_PLL_USB2_CLR, 983 CCM_ANALOG_PLL_USB2_ENABLE); 984 return; 985 case IMX6_CLK_USBPHY1: 986 /* PLL outputs should alwas be on. */ 987 regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB1_SET, 988 CCM_ANALOG_PLL_USB1_EN_USB_CLKS); 989 imxccm_enable_parent(sc, IMX6_CLK_PLL3_USB_OTG, on); 990 return; 991 case IMX6_CLK_USBPHY2: 992 /* PLL outputs should alwas be on. */ 993 regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB2_SET, 994 CCM_ANALOG_PLL_USB2_EN_USB_CLKS); 995 imxccm_enable_parent(sc, IMX6_CLK_PLL7_USB_HOST, on); 996 return; 997 case IMX6_CLK_SATA_REF_100: 998 imxccm_enable_parent(sc, IMX6_CLK_PLL6_ENET, on); 999 regmap_write_4(sc->sc_anatop, 1000 on ? CCM_ANALOG_PLL_ENET_SET : CCM_ANALOG_PLL_ENET_CLR, 1001 CCM_ANALOG_PLL_ENET_ENABLE_100M); 1002 return; 1003 case IMX6_CLK_ENET_REF: 1004 imxccm_enable_parent(sc, IMX6_CLK_PLL6_ENET, on); 1005 return; 1006 case IMX6_CLK_IPG: 1007 case IMX6_CLK_IPG_PER: 1008 case IMX6_CLK_ECSPI_ROOT: 1009 /* always on */ 1010 return; 1011 default: 1012 break; 1013 } 1014 } 1015 1016 if (on) { 1017 if (idx < sc->sc_ngates && sc->sc_gates[idx].parent) { 1018 parent = sc->sc_gates[idx].parent; 1019 imxccm_enable(sc, &parent, on); 1020 } 1021 1022 if (idx < sc->sc_ndivs && sc->sc_divs[idx].parent) { 1023 parent = sc->sc_divs[idx].parent; 1024 imxccm_enable(sc, &parent, on); 1025 } 1026 } 1027 1028 if (idx >= sc->sc_ngates || sc->sc_gates[idx].reg == 0) { 1029 if ((idx < sc->sc_ndivs && sc->sc_divs[idx].reg != 0) || 1030 (idx < sc->sc_nmuxs && sc->sc_muxs[idx].reg != 0)) 1031 return; 1032 printf("%s: 0x%08x\n", __func__, idx); 1033 return; 1034 } 1035 1036 reg = sc->sc_gates[idx].reg; 1037 pos = sc->sc_gates[idx].pos; 1038 1039 if (on) 1040 HSET4(sc, reg, 0x3 << (2 * pos)); 1041 else 1042 HCLR4(sc, reg, 0x3 << (2 * pos)); 1043 } 1044 1045 uint32_t 1046 imxccm_get_frequency(void *cookie, uint32_t *cells) 1047 { 1048 struct imxccm_softc *sc = cookie; 1049 uint32_t idx = cells[0]; 1050 uint32_t div, pre, reg, parent; 1051 uint32_t freq; 1052 1053 /* Dummy clock. */ 1054 if (idx == 0) 1055 return 0; 1056 1057 if (idx < sc->sc_ngates && sc->sc_gates[idx].parent) { 1058 parent = sc->sc_gates[idx].parent; 1059 return imxccm_get_frequency(sc, &parent); 1060 } 1061 1062 if (idx < sc->sc_ndivs && sc->sc_divs[idx].parent) { 1063 div = HREAD4(sc, sc->sc_divs[idx].reg); 1064 div = div >> sc->sc_divs[idx].shift; 1065 div = div & sc->sc_divs[idx].mask; 1066 parent = sc->sc_divs[idx].parent; 1067 return imxccm_get_frequency(sc, &parent) / (div + 1); 1068 } 1069 1070 if (sc->sc_gates == imx8mq_gates) { 1071 switch (idx) { 1072 case IMX8MQ_CLK_ARM: 1073 parent = IMX8MQ_ARM_PLL; 1074 return imxccm_get_frequency(sc, &parent); 1075 case IMX8MQ_ARM_PLL: 1076 return imxccm_imx8mq_get_pll(sc, idx); 1077 } 1078 1079 /* These are composite clocks. */ 1080 if (idx < sc->sc_ngates && sc->sc_gates[idx].reg && 1081 idx < sc->sc_ndivs && sc->sc_divs[idx].reg && 1082 idx < sc->sc_npredivs && sc->sc_predivs[idx].reg) { 1083 switch (idx) { 1084 case IMX8MQ_CLK_ENET_AXI: 1085 freq = imxccm_imx8mq_enet(sc, idx); 1086 break; 1087 case IMX8MQ_CLK_I2C1: 1088 case IMX8MQ_CLK_I2C2: 1089 case IMX8MQ_CLK_I2C3: 1090 case IMX8MQ_CLK_I2C4: 1091 freq = imxccm_imx8mq_i2c(sc, idx); 1092 break; 1093 case IMX8MQ_CLK_UART1: 1094 case IMX8MQ_CLK_UART2: 1095 case IMX8MQ_CLK_UART3: 1096 case IMX8MQ_CLK_UART4: 1097 freq = imxccm_imx8mq_uart(sc, idx); 1098 break; 1099 case IMX8MQ_CLK_USDHC1: 1100 case IMX8MQ_CLK_USDHC2: 1101 freq = imxccm_imx8mq_usdhc(sc, idx); 1102 break; 1103 case IMX8MQ_CLK_USB_BUS: 1104 case IMX8MQ_CLK_USB_CORE_REF: 1105 case IMX8MQ_CLK_USB_PHY_REF: 1106 freq = imxccm_imx8mq_usb(sc, idx); 1107 break; 1108 case IMX8MQ_CLK_ECSPI1: 1109 case IMX8MQ_CLK_ECSPI2: 1110 case IMX8MQ_CLK_ECSPI3: 1111 freq = imxccm_imx8mq_ecspi(sc, idx); 1112 break; 1113 case IMX8MQ_CLK_PWM1: 1114 case IMX8MQ_CLK_PWM2: 1115 case IMX8MQ_CLK_PWM3: 1116 case IMX8MQ_CLK_PWM4: 1117 freq = imxccm_imx8mq_pwm(sc, idx); 1118 break; 1119 default: 1120 printf("%s: 0x%08x\n", __func__, idx); 1121 return 0; 1122 } 1123 1124 reg = HREAD4(sc, sc->sc_divs[idx].reg); 1125 div = reg >> sc->sc_divs[idx].shift; 1126 div = div & sc->sc_divs[idx].mask; 1127 pre = reg >> sc->sc_predivs[idx].shift; 1128 pre = pre & sc->sc_predivs[idx].mask; 1129 return ((freq / (pre + 1)) / (div + 1)); 1130 } 1131 1132 } else if (sc->sc_gates == imx7d_gates) { 1133 switch (idx) { 1134 case IMX7D_ENET_AXI_ROOT_SRC: 1135 return imxccm_imx7d_enet(sc, idx); 1136 case IMX7D_I2C1_ROOT_SRC: 1137 case IMX7D_I2C2_ROOT_SRC: 1138 case IMX7D_I2C3_ROOT_SRC: 1139 case IMX7D_I2C4_ROOT_SRC: 1140 return imxccm_imx7d_i2c(sc, idx); 1141 case IMX7D_UART1_ROOT_SRC: 1142 case IMX7D_UART2_ROOT_SRC: 1143 case IMX7D_UART3_ROOT_SRC: 1144 case IMX7D_UART4_ROOT_SRC: 1145 case IMX7D_UART5_ROOT_SRC: 1146 case IMX7D_UART6_ROOT_SRC: 1147 case IMX7D_UART7_ROOT_SRC: 1148 return imxccm_imx7d_uart(sc, idx); 1149 case IMX7D_USDHC1_ROOT_SRC: 1150 case IMX7D_USDHC2_ROOT_SRC: 1151 case IMX7D_USDHC3_ROOT_SRC: 1152 return imxccm_imx7d_usdhc(sc, idx); 1153 } 1154 } else if (sc->sc_gates == imx6ul_gates) { 1155 switch (idx) { 1156 case IMX6UL_CLK_ARM: 1157 return imxccm_get_armclk(sc); 1158 case IMX6UL_CLK_IPG: 1159 return imxccm_get_ipgclk(sc); 1160 case IMX6UL_CLK_PERCLK: 1161 return imxccm_get_ipg_perclk(sc); 1162 case IMX6UL_CLK_UART1_SERIAL: 1163 return imxccm_get_uartclk(sc); 1164 case IMX6UL_CLK_USDHC1: 1165 case IMX6UL_CLK_USDHC2: 1166 return imxccm_get_usdhx(sc, idx - IMX6UL_CLK_USDHC1 + 1); 1167 } 1168 } else if (sc->sc_gates == imx6_gates) { 1169 switch (idx) { 1170 case IMX6_CLK_AHB: 1171 return imxccm_get_ahbclk(sc); 1172 case IMX6_CLK_ARM: 1173 return imxccm_get_armclk(sc); 1174 case IMX6_CLK_IPG: 1175 return imxccm_get_ipgclk(sc); 1176 case IMX6_CLK_IPG_PER: 1177 return imxccm_get_ipg_perclk(sc); 1178 case IMX6_CLK_ECSPI_ROOT: 1179 return imxccm_get_ecspiclk(sc); 1180 case IMX6_CLK_UART_SERIAL: 1181 return imxccm_get_uartclk(sc); 1182 case IMX6_CLK_USDHC1: 1183 case IMX6_CLK_USDHC2: 1184 case IMX6_CLK_USDHC3: 1185 case IMX6_CLK_USDHC4: 1186 return imxccm_get_usdhx(sc, idx - IMX6_CLK_USDHC1 + 1); 1187 } 1188 } 1189 1190 printf("%s: 0x%08x\n", __func__, idx); 1191 return 0; 1192 } 1193 1194 int 1195 imxccm_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) 1196 { 1197 struct imxccm_softc *sc = cookie; 1198 uint32_t idx = cells[0]; 1199 uint32_t reg, div, parent, parent_freq; 1200 uint32_t pcells[2]; 1201 int ret; 1202 1203 if (sc->sc_divs == imx8mq_divs) { 1204 switch (idx) { 1205 case IMX8MQ_CLK_ARM: 1206 parent = IMX8MQ_CLK_A53_SRC; 1207 return imxccm_set_frequency(cookie, &parent, freq); 1208 case IMX8MQ_CLK_A53_SRC: 1209 pcells[0] = sc->sc_phandle; 1210 pcells[1] = IMX8MQ_SYS1_PLL_800M; 1211 ret = imxccm_set_parent(cookie, &idx, pcells); 1212 if (ret) 1213 return ret; 1214 ret = imxccm_imx8mq_set_pll(sc, IMX8MQ_ARM_PLL, freq); 1215 pcells[0] = sc->sc_phandle; 1216 pcells[1] = IMX8MQ_ARM_PLL_OUT; 1217 imxccm_set_parent(cookie, &idx, pcells); 1218 return ret; 1219 case IMX8MQ_CLK_USB_BUS: 1220 case IMX8MQ_CLK_USB_CORE_REF: 1221 case IMX8MQ_CLK_USB_PHY_REF: 1222 if (imxccm_get_frequency(sc, cells) != freq) 1223 break; 1224 return 0; 1225 case IMX8MQ_CLK_USDHC1: 1226 imxccm_enable(cookie, &idx, 1); 1227 reg = HREAD4(sc, sc->sc_divs[idx].reg); 1228 reg &= ~(sc->sc_divs[idx].mask << sc->sc_divs[idx].shift); 1229 HWRITE4(sc, sc->sc_divs[idx].reg, reg); 1230 reg = HREAD4(sc, sc->sc_predivs[idx].reg); 1231 reg &= ~(sc->sc_predivs[idx].mask << sc->sc_predivs[idx].shift); 1232 HWRITE4(sc, sc->sc_predivs[idx].reg, reg); 1233 return 0; 1234 } 1235 } else if (sc->sc_divs == imx7d_divs) { 1236 switch (idx) { 1237 case IMX7D_USDHC1_ROOT_CLK: 1238 case IMX7D_USDHC2_ROOT_CLK: 1239 case IMX7D_USDHC3_ROOT_CLK: 1240 parent = sc->sc_gates[idx].parent; 1241 return imxccm_set_frequency(sc, &parent, freq); 1242 case IMX7D_USDHC1_ROOT_DIV: 1243 case IMX7D_USDHC2_ROOT_DIV: 1244 case IMX7D_USDHC3_ROOT_DIV: 1245 parent = sc->sc_divs[idx].parent; 1246 parent_freq = imxccm_get_frequency(sc, &parent); 1247 div = 0; 1248 while (parent_freq / (div + 1) > freq) 1249 div++; 1250 reg = HREAD4(sc, sc->sc_divs[idx].reg); 1251 reg &= ~(sc->sc_divs[idx].mask << sc->sc_divs[idx].shift); 1252 reg |= (div << sc->sc_divs[idx].shift); 1253 HWRITE4(sc, sc->sc_divs[idx].reg, reg); 1254 return 0; 1255 } 1256 } 1257 1258 printf("%s: 0x%08x %x\n", __func__, idx, freq); 1259 return -1; 1260 } 1261 1262 int 1263 imxccm_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells) 1264 { 1265 struct imxccm_softc *sc = cookie; 1266 uint32_t idx = cells[0]; 1267 uint32_t pidx; 1268 uint32_t mux; 1269 1270 if (pcells[0] != sc->sc_phandle) { 1271 printf("%s: 0x%08x parent 0x%08x\n", __func__, idx, pcells[0]); 1272 return -1; 1273 } 1274 1275 pidx = pcells[1]; 1276 1277 if (sc->sc_muxs == imx8mq_muxs) { 1278 switch (idx) { 1279 case IMX8MQ_CLK_A53_SRC: 1280 if (pidx != IMX8MQ_ARM_PLL_OUT && 1281 pidx != IMX8MQ_SYS1_PLL_800M) 1282 break; 1283 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 1284 mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift); 1285 if (pidx == IMX8MQ_ARM_PLL_OUT) 1286 mux |= (0x1 << sc->sc_muxs[idx].shift); 1287 if (pidx == IMX8MQ_SYS1_PLL_800M) 1288 mux |= (0x4 << sc->sc_muxs[idx].shift); 1289 HWRITE4(sc, sc->sc_muxs[idx].reg, mux); 1290 return 0; 1291 case IMX8MQ_CLK_USB_BUS: 1292 if (pidx != IMX8MQ_SYS2_PLL_500M) 1293 break; 1294 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 1295 mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift); 1296 mux |= (0x1 << sc->sc_muxs[idx].shift); 1297 HWRITE4(sc, sc->sc_muxs[idx].reg, mux); 1298 return 0; 1299 case IMX8MQ_CLK_USB_CORE_REF: 1300 case IMX8MQ_CLK_USB_PHY_REF: 1301 if (pidx != IMX8MQ_SYS1_PLL_100M) 1302 break; 1303 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 1304 mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift); 1305 mux |= (0x1 << sc->sc_muxs[idx].shift); 1306 HWRITE4(sc, sc->sc_muxs[idx].reg, mux); 1307 return 0; 1308 case IMX8MQ_CLK_PCIE1_CTRL: 1309 case IMX8MQ_CLK_PCIE2_CTRL: 1310 if (pidx != IMX8MQ_SYS2_PLL_250M) 1311 break; 1312 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 1313 mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift); 1314 mux |= (0x1 << sc->sc_muxs[idx].shift); 1315 HWRITE4(sc, sc->sc_muxs[idx].reg, mux); 1316 return 0; 1317 case IMX8MQ_CLK_PCIE1_PHY: 1318 case IMX8MQ_CLK_PCIE2_PHY: 1319 if (pidx != IMX8MQ_SYS2_PLL_100M) 1320 break; 1321 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 1322 mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift); 1323 mux |= (0x1 << sc->sc_muxs[idx].shift); 1324 HWRITE4(sc, sc->sc_muxs[idx].reg, mux); 1325 return 0; 1326 } 1327 } 1328 1329 printf("%s: 0x%08x 0x%08x\n", __func__, idx, pidx); 1330 return -1; 1331 } 1332