1 /* $OpenBSD: imxccm.c,v 1.22 2020/10/12 17:38:28 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 /* Int PLL */ 131 #define CCM_14XX_IMX8M_ARM_PLL_GNRL_CTL 0x84 132 #define CCM_14XX_IMX8M_ARM_PLL_DIV_CTL 0x88 133 #define CCM_14XX_IMX8M_SYS_PLL1_GNRL_CTL 0x94 134 #define CCM_14XX_IMX8M_SYS_PLL1_DIV_CTL 0x98 135 #define CCM_INT_PLL_LOCK (1U << 31) 136 #define CCM_INT_PLL_LOCK_SEL (1 << 29) 137 #define CCM_INT_PLL_RST (1 << 9) 138 #define CCM_INT_PLL_BYPASS (1 << 4) 139 #define CCM_INT_PLL_MAIN_DIV_SHIFT 12 140 #define CCM_INT_PLL_MAIN_DIV_MASK 0x3ff 141 #define CCM_INT_PLL_PRE_DIV_SHIFT 4 142 #define CCM_INT_PLL_PRE_DIV_MASK 0x3f 143 #define CCM_INT_PLL_POST_DIV_SHIFT 0 144 #define CCM_INT_PLL_POST_DIV_MASK 0x7 145 146 /* Frac PLL */ 147 #define CCM_FRAC_IMX8M_ARM_PLL0 0x28 148 #define CCM_FRAC_IMX8M_ARM_PLL1 0x2c 149 #define CCM_FRAC_PLL_LOCK (1U << 31) 150 #define CCM_FRAC_PLL_ENABLE (1 << 21) 151 #define CCM_FRAC_PLL_POWERDOWN (1 << 19) 152 #define CCM_FRAC_PLL_REFCLK_SEL_SHIFT 16 153 #define CCM_FRAC_PLL_REFCLK_SEL_MASK 0x3 154 #define CCM_FRAC_PLL_LOCK_SEL (1 << 15) 155 #define CCM_FRAC_PLL_BYPASS (1 << 14) 156 #define CCM_FRAC_PLL_COUNTCLK_SEL (1 << 13) 157 #define CCM_FRAC_PLL_NEWDIV_VAL (1 << 12) 158 #define CCM_FRAC_PLL_NEWDIV_ACK (1 << 11) 159 #define CCM_FRAC_PLL_REFCLK_DIV_VAL_SHIFT 5 160 #define CCM_FRAC_PLL_REFCLK_DIV_VAL_MASK 0x3f 161 #define CCM_FRAC_PLL_OUTPUT_DIV_VAL_SHIFT 0 162 #define CCM_FRAC_PLL_OUTPUT_DIV_VAL_MASK 0x1f 163 #define CCM_FRAC_PLL_FRAC_DIV_CTL_SHIFT 7 164 #define CCM_FRAC_PLL_FRAC_DIV_CTL_MASK 0x1ffffff 165 #define CCM_FRAC_PLL_INT_DIV_CTL_SHIFT 0 166 #define CCM_FRAC_PLL_INT_DIV_CTL_MASK 0x7f 167 #define CCM_FRAC_PLL_DENOM (1 << 24) 168 #define CCM_FRAC_IMX8M_PLLOUT_DIV_CFG 0x78 169 #define CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_SHIFT 20 170 #define CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_MASK 0x7 171 172 #define HCLK_FREQ 24000000 173 #define PLL3_60M 60000000 174 #define PLL3_80M 80000000 175 176 #define HREAD4(sc, reg) \ 177 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) 178 #define HWRITE4(sc, reg, val) \ 179 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 180 #define HSET4(sc, reg, bits) \ 181 HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits)) 182 #define HCLR4(sc, reg, bits) \ 183 HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits)) 184 185 struct imxccm_gate { 186 uint16_t reg; 187 uint8_t pos; 188 uint16_t parent; 189 }; 190 191 struct imxccm_divider { 192 uint16_t reg; 193 uint16_t shift; 194 uint16_t mask; 195 uint16_t parent; 196 uint16_t fixed; 197 }; 198 199 struct imxccm_mux { 200 uint16_t reg; 201 uint16_t shift; 202 uint16_t mask; 203 }; 204 205 #include "imxccm_clocks.h" 206 207 struct imxccm_softc { 208 struct device sc_dev; 209 bus_space_tag_t sc_iot; 210 bus_space_handle_t sc_ioh; 211 int sc_node; 212 uint32_t sc_phandle; 213 214 struct regmap *sc_anatop; 215 216 struct imxccm_gate *sc_gates; 217 int sc_ngates; 218 struct imxccm_divider *sc_divs; 219 int sc_ndivs; 220 struct imxccm_mux *sc_muxs; 221 int sc_nmuxs; 222 struct imxccm_divider *sc_predivs; 223 int sc_npredivs; 224 struct clock_device sc_cd; 225 }; 226 227 int imxccm_match(struct device *, void *, void *); 228 void imxccm_attach(struct device *parent, struct device *self, void *args); 229 230 struct cfattach imxccm_ca = { 231 sizeof (struct imxccm_softc), imxccm_match, imxccm_attach 232 }; 233 234 struct cfdriver imxccm_cd = { 235 NULL, "imxccm", DV_DULL 236 }; 237 238 uint32_t imxccm_get_armclk(struct imxccm_softc *); 239 void imxccm_armclk_set_parent(struct imxccm_softc *, enum imxanatop_clocks); 240 uint32_t imxccm_get_usdhx(struct imxccm_softc *, int x); 241 uint32_t imxccm_get_periphclk(struct imxccm_softc *); 242 uint32_t imxccm_get_ahbclk(struct imxccm_softc *); 243 uint32_t imxccm_get_ipgclk(struct imxccm_softc *); 244 uint32_t imxccm_get_ipg_perclk(struct imxccm_softc *); 245 uint32_t imxccm_get_uartclk(struct imxccm_softc *); 246 uint32_t imxccm_imx8mm_enet(struct imxccm_softc *sc, uint32_t); 247 uint32_t imxccm_imx8mm_ahb(struct imxccm_softc *sc, uint32_t); 248 uint32_t imxccm_imx8mm_i2c(struct imxccm_softc *sc, uint32_t); 249 uint32_t imxccm_imx8mm_uart(struct imxccm_softc *sc, uint32_t); 250 uint32_t imxccm_imx8mm_usdhc(struct imxccm_softc *sc, uint32_t); 251 uint32_t imxccm_imx8mq_ecspi(struct imxccm_softc *sc, uint32_t); 252 uint32_t imxccm_imx8mq_enet(struct imxccm_softc *sc, uint32_t); 253 uint32_t imxccm_imx8mq_ahb(struct imxccm_softc *sc, uint32_t); 254 uint32_t imxccm_imx8mq_i2c(struct imxccm_softc *sc, uint32_t); 255 uint32_t imxccm_imx8mq_pwm(struct imxccm_softc *sc, uint32_t); 256 uint32_t imxccm_imx8mq_uart(struct imxccm_softc *sc, uint32_t); 257 uint32_t imxccm_imx8mq_usdhc(struct imxccm_softc *sc, uint32_t); 258 uint32_t imxccm_imx8mq_usb(struct imxccm_softc *sc, uint32_t); 259 int imxccm_imx8m_set_div(struct imxccm_softc *, uint32_t, uint64_t, uint64_t); 260 void imxccm_enable(void *, uint32_t *, int); 261 uint32_t imxccm_get_frequency(void *, uint32_t *); 262 int imxccm_set_frequency(void *, uint32_t *, uint32_t); 263 int imxccm_set_parent(void *, uint32_t *, uint32_t *); 264 265 int 266 imxccm_match(struct device *parent, void *match, void *aux) 267 { 268 struct fdt_attach_args *faa = aux; 269 270 return (OF_is_compatible(faa->fa_node, "fsl,imx6q-ccm") || 271 OF_is_compatible(faa->fa_node, "fsl,imx6sl-ccm") || 272 OF_is_compatible(faa->fa_node, "fsl,imx6sx-ccm") || 273 OF_is_compatible(faa->fa_node, "fsl,imx6ul-ccm") || 274 OF_is_compatible(faa->fa_node, "fsl,imx7d-ccm") || 275 OF_is_compatible(faa->fa_node, "fsl,imx8mm-ccm") || 276 OF_is_compatible(faa->fa_node, "fsl,imx8mq-ccm")); 277 } 278 279 void 280 imxccm_attach(struct device *parent, struct device *self, void *aux) 281 { 282 struct imxccm_softc *sc = (struct imxccm_softc *)self; 283 struct fdt_attach_args *faa = aux; 284 285 KASSERT(faa->fa_nreg >= 1); 286 287 sc->sc_node = faa->fa_node; 288 sc->sc_iot = faa->fa_iot; 289 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 290 faa->fa_reg[0].size, 0, &sc->sc_ioh)) 291 panic("%s: bus_space_map failed!", __func__); 292 293 sc->sc_phandle = OF_getpropint(sc->sc_node, "phandle", 0); 294 295 if (OF_is_compatible(sc->sc_node, "fsl,imx8mm-ccm")) { 296 sc->sc_anatop = regmap_bycompatible("fsl,imx8mm-anatop"); 297 KASSERT(sc->sc_anatop != NULL); 298 sc->sc_gates = imx8mm_gates; 299 sc->sc_ngates = nitems(imx8mm_gates); 300 sc->sc_divs = imx8mm_divs; 301 sc->sc_ndivs = nitems(imx8mm_divs); 302 sc->sc_muxs = imx8mm_muxs; 303 sc->sc_nmuxs = nitems(imx8mm_muxs); 304 sc->sc_predivs = imx8mm_predivs; 305 sc->sc_npredivs = nitems(imx8mm_predivs); 306 } else if (OF_is_compatible(sc->sc_node, "fsl,imx8mq-ccm")) { 307 sc->sc_anatop = regmap_bycompatible("fsl,imx8mq-anatop"); 308 KASSERT(sc->sc_anatop != NULL); 309 sc->sc_gates = imx8mq_gates; 310 sc->sc_ngates = nitems(imx8mq_gates); 311 sc->sc_divs = imx8mq_divs; 312 sc->sc_ndivs = nitems(imx8mq_divs); 313 sc->sc_muxs = imx8mq_muxs; 314 sc->sc_nmuxs = nitems(imx8mq_muxs); 315 sc->sc_predivs = imx8mq_predivs; 316 sc->sc_npredivs = nitems(imx8mq_predivs); 317 } else if (OF_is_compatible(sc->sc_node, "fsl,imx7d-ccm")) { 318 sc->sc_gates = imx7d_gates; 319 sc->sc_ngates = nitems(imx7d_gates); 320 sc->sc_divs = imx7d_divs; 321 sc->sc_ndivs = nitems(imx7d_divs); 322 sc->sc_muxs = imx7d_muxs; 323 sc->sc_nmuxs = nitems(imx7d_muxs); 324 } else if (OF_is_compatible(sc->sc_node, "fsl,imx6ul-ccm")) { 325 sc->sc_gates = imx6ul_gates; 326 sc->sc_ngates = nitems(imx6ul_gates); 327 } else { 328 sc->sc_gates = imx6_gates; 329 sc->sc_ngates = nitems(imx6_gates); 330 } 331 332 printf("\n"); 333 334 sc->sc_cd.cd_node = faa->fa_node; 335 sc->sc_cd.cd_cookie = sc; 336 sc->sc_cd.cd_enable = imxccm_enable; 337 sc->sc_cd.cd_get_frequency = imxccm_get_frequency; 338 sc->sc_cd.cd_set_frequency = imxccm_set_frequency; 339 sc->sc_cd.cd_set_parent = imxccm_set_parent; 340 clock_register(&sc->sc_cd); 341 } 342 343 uint32_t 344 imxccm_get_armclk(struct imxccm_softc *sc) 345 { 346 uint32_t ccsr = HREAD4(sc, CCM_CCSR); 347 348 if (!(ccsr & CCM_CCSR_PLL1_SW_CLK_SEL)) 349 return imxanatop_decode_pll(ARM_PLL1, HCLK_FREQ); 350 else if (ccsr & CCM_CCSR_STEP_SEL) 351 return imxanatop_get_pll2_pfd(2); 352 else 353 return HCLK_FREQ; 354 } 355 356 void 357 imxccm_armclk_set_parent(struct imxccm_softc *sc, enum imxanatop_clocks clock) 358 { 359 switch (clock) 360 { 361 case ARM_PLL1: 362 /* jump onto pll1 */ 363 HCLR4(sc, CCM_CCSR, CCM_CCSR_PLL1_SW_CLK_SEL); 364 /* put step clk on OSC, power saving */ 365 HCLR4(sc, CCM_CCSR, CCM_CCSR_STEP_SEL); 366 break; 367 case OSC: 368 /* put step clk on OSC */ 369 HCLR4(sc, CCM_CCSR, CCM_CCSR_STEP_SEL); 370 /* jump onto step clk */ 371 HSET4(sc, CCM_CCSR, CCM_CCSR_PLL1_SW_CLK_SEL); 372 break; 373 case SYS_PLL2_PFD2: 374 /* put step clk on pll2-pfd2 400 MHz */ 375 HSET4(sc, CCM_CCSR, CCM_CCSR_STEP_SEL); 376 /* jump onto step clk */ 377 HSET4(sc, CCM_CCSR, CCM_CCSR_PLL1_SW_CLK_SEL); 378 break; 379 default: 380 panic("%s: parent not possible for arm clk", __func__); 381 } 382 } 383 384 uint32_t 385 imxccm_get_ecspiclk(struct imxccm_softc *sc) 386 { 387 uint32_t clkroot = PLL3_60M; 388 uint32_t podf = HREAD4(sc, CCM_CSCDR2); 389 390 podf >>= CCM_CSCDR2_ECSPI_PODF_SHIFT; 391 podf &= CCM_CSCDR2_ECSPI_PODF_MASK; 392 393 return clkroot / (podf + 1); 394 } 395 396 unsigned int 397 imxccm_get_usdhx(struct imxccm_softc *sc, int x) 398 { 399 uint32_t cscmr1 = HREAD4(sc, CCM_CSCMR1); 400 uint32_t cscdr1 = HREAD4(sc, CCM_CSCDR1); 401 uint32_t podf, clkroot; 402 403 // Odd bitsetting. Damn you. 404 if (x == 1) 405 podf = ((cscdr1 >> 11) & CCM_CSCDR1_USDHCx_PODF_MASK); 406 else 407 podf = ((cscdr1 >> (10 + 3*x)) & CCM_CSCDR1_USDHCx_PODF_MASK); 408 409 if (cscmr1 & (1 << CCM_CSCDR1_USDHCx_CLK_SEL_SHIFT(x))) 410 clkroot = imxanatop_get_pll2_pfd(0); // 352 MHz 411 else 412 clkroot = imxanatop_get_pll2_pfd(2); // 396 MHz 413 414 return clkroot / (podf + 1); 415 } 416 417 uint32_t 418 imxccm_get_uartclk(struct imxccm_softc *sc) 419 { 420 uint32_t clkroot = PLL3_80M; 421 uint32_t podf = HREAD4(sc, CCM_CSCDR1) & CCM_CSCDR1_UART_PODF_MASK; 422 423 return clkroot / (podf + 1); 424 } 425 426 uint32_t 427 imxccm_get_periphclk(struct imxccm_softc *sc) 428 { 429 if ((HREAD4(sc, CCM_CBCDR) >> CCM_CBCDR_PERIPH_CLK_SEL_SHIFT) 430 & CCM_CBCDR_PERIPH_CLK_SEL_MASK) { 431 switch((HREAD4(sc, CCM_CBCMR) 432 >> CCM_CBCMR_PERIPH_CLK2_SEL_SHIFT) & CCM_CBCMR_PERIPH_CLK2_SEL_MASK) { 433 case 0: 434 return imxanatop_decode_pll(USB1_PLL3, HCLK_FREQ); 435 case 1: 436 case 2: 437 return HCLK_FREQ; 438 default: 439 return 0; 440 } 441 442 } else { 443 switch((HREAD4(sc, CCM_CBCMR) 444 >> CCM_CBCMR_PRE_PERIPH_CLK_SEL_SHIFT) & CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK) { 445 default: 446 case 0: 447 return imxanatop_decode_pll(SYS_PLL2, HCLK_FREQ); 448 case 1: 449 return imxanatop_get_pll2_pfd(2); // 396 MHz 450 case 2: 451 return imxanatop_get_pll2_pfd(0); // 352 MHz 452 case 3: 453 return imxanatop_get_pll2_pfd(2) / 2; // 198 MHz 454 } 455 } 456 } 457 458 uint32_t 459 imxccm_get_ahbclk(struct imxccm_softc *sc) 460 { 461 uint32_t ahb_podf; 462 463 ahb_podf = (HREAD4(sc, CCM_CBCDR) >> CCM_CBCDR_AHB_PODF_SHIFT) 464 & CCM_CBCDR_AHB_PODF_MASK; 465 return imxccm_get_periphclk(sc) / (ahb_podf + 1); 466 } 467 468 uint32_t 469 imxccm_get_ipgclk(struct imxccm_softc *sc) 470 { 471 uint32_t ipg_podf; 472 473 ipg_podf = (HREAD4(sc, CCM_CBCDR) >> CCM_CBCDR_IPG_PODF_SHIFT) 474 & CCM_CBCDR_IPG_PODF_MASK; 475 return imxccm_get_ahbclk(sc) / (ipg_podf + 1); 476 } 477 478 uint32_t 479 imxccm_get_ipg_perclk(struct imxccm_softc *sc) 480 { 481 uint32_t cscmr1 = HREAD4(sc, CCM_CSCMR1); 482 uint32_t freq, ipg_podf; 483 484 if (sc->sc_gates == imx6ul_gates && 485 cscmr1 & CCM_CSCMR1_PERCLK_CLK_SEL_MASK) 486 freq = HCLK_FREQ; 487 else 488 freq = imxccm_get_ipgclk(sc); 489 490 ipg_podf = cscmr1 & CCM_CSCMR1_PERCLK_CLK_PODF_MASK; 491 492 return freq / (ipg_podf + 1); 493 } 494 495 void 496 imxccm_imx6_enable_pll_enet(struct imxccm_softc *sc, int on) 497 { 498 KASSERT(on); 499 500 regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_ENET_CLR, 501 CCM_ANALOG_PLL_ENET_POWERDOWN); 502 503 /* Wait for the PLL to lock. */ 504 while ((regmap_read_4(sc->sc_anatop, 505 CCM_ANALOG_PLL_ENET) & CCM_ANALOG_PLL_ENET_LOCK) == 0) 506 ; 507 508 regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_ENET_CLR, 509 CCM_ANALOG_PLL_ENET_BYPASS); 510 } 511 512 void 513 imxccm_imx6_enable_pll_usb1(struct imxccm_softc *sc, int on) 514 { 515 KASSERT(on); 516 517 regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB1_SET, 518 CCM_ANALOG_PLL_USB1_POWER); 519 520 /* Wait for the PLL to lock. */ 521 while ((regmap_read_4(sc->sc_anatop, 522 CCM_ANALOG_PLL_USB1) & CCM_ANALOG_PLL_USB1_LOCK) == 0) 523 ; 524 525 regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB1_CLR, 526 CCM_ANALOG_PLL_USB1_BYPASS); 527 } 528 529 void 530 imxccm_imx6_enable_pll_usb2(struct imxccm_softc *sc, int on) 531 { 532 KASSERT(on); 533 534 regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB2_SET, 535 CCM_ANALOG_PLL_USB2_POWER); 536 537 /* Wait for the PLL to lock. */ 538 while ((regmap_read_4(sc->sc_anatop, 539 CCM_ANALOG_PLL_USB2) & CCM_ANALOG_PLL_USB2_LOCK) == 0) 540 ; 541 542 regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB2_CLR, 543 CCM_ANALOG_PLL_USB2_BYPASS); 544 } 545 546 uint32_t 547 imxccm_imx7d_enet(struct imxccm_softc *sc, uint32_t idx) 548 { 549 uint32_t mux; 550 551 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 552 return 0; 553 554 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 555 mux >>= sc->sc_muxs[idx].shift; 556 mux &= sc->sc_muxs[idx].mask; 557 558 switch (mux) { 559 case 0: 560 return clock_get_frequency(sc->sc_node, "osc"); 561 case 7: 562 return 392000000; /* pll_sys_pfd4_clk XXX not fixed */ 563 default: 564 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 565 return 0; 566 } 567 } 568 569 uint32_t 570 imxccm_imx7d_i2c(struct imxccm_softc *sc, uint32_t idx) 571 { 572 uint32_t mux; 573 574 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 575 return 0; 576 577 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 578 mux >>= sc->sc_muxs[idx].shift; 579 mux &= sc->sc_muxs[idx].mask; 580 581 switch (mux) { 582 case 0: 583 return clock_get_frequency(sc->sc_node, "osc"); 584 case 1: 585 return 120000000; /* pll_sys_main_120m_clk */ 586 default: 587 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 588 return 0; 589 } 590 } 591 592 uint32_t 593 imxccm_imx7d_uart(struct imxccm_softc *sc, uint32_t idx) 594 { 595 uint32_t mux; 596 597 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 598 return 0; 599 600 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 601 mux >>= sc->sc_muxs[idx].shift; 602 mux &= sc->sc_muxs[idx].mask; 603 604 switch (mux) { 605 case 0: 606 return clock_get_frequency(sc->sc_node, "osc"); 607 default: 608 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 609 return 0; 610 } 611 } 612 613 uint32_t 614 imxccm_imx7d_usdhc(struct imxccm_softc *sc, uint32_t idx) 615 { 616 uint32_t mux; 617 618 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 619 return 0; 620 621 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 622 mux >>= sc->sc_muxs[idx].shift; 623 mux &= sc->sc_muxs[idx].mask; 624 625 switch (mux) { 626 case 0: 627 return clock_get_frequency(sc->sc_node, "osc"); 628 case 1: 629 return 392000000; /* pll_sys_pfd0_392m_clk */ 630 default: 631 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 632 return 0; 633 } 634 } 635 636 uint32_t 637 imxccm_imx8mm_get_pll(struct imxccm_softc *sc, uint32_t idx) 638 { 639 uint64_t main_div, pre_div, post_div, div; 640 uint32_t pll0, pll1; 641 uint64_t freq; 642 643 switch (idx) { 644 case IMX8MM_ARM_PLL: 645 pll0 = regmap_read_4(sc->sc_anatop, 646 CCM_14XX_IMX8M_ARM_PLL_GNRL_CTL); 647 pll1 = regmap_read_4(sc->sc_anatop, 648 CCM_14XX_IMX8M_ARM_PLL_DIV_CTL); 649 div = 1; 650 break; 651 default: 652 printf("%s: 0x%08x\n", __func__, idx); 653 return 0; 654 } 655 656 freq = clock_get_frequency(sc->sc_node, "osc_24m"); 657 if (pll0 & CCM_INT_PLL_BYPASS) 658 return freq; 659 660 main_div = (pll1 >> CCM_INT_PLL_MAIN_DIV_SHIFT) & 661 CCM_INT_PLL_MAIN_DIV_MASK; 662 pre_div = (pll1 >> CCM_INT_PLL_PRE_DIV_SHIFT) & 663 CCM_INT_PLL_PRE_DIV_MASK; 664 post_div = (pll1 >> CCM_INT_PLL_POST_DIV_SHIFT) & 665 CCM_INT_PLL_POST_DIV_MASK; 666 667 freq = freq * main_div; 668 freq = freq / (pre_div * (1 << post_div) * div); 669 return freq; 670 } 671 672 int 673 imxccm_imx8mm_set_pll(struct imxccm_softc *sc, uint32_t idx, uint64_t freq) 674 { 675 uint64_t main_div, pre_div, post_div; 676 uint32_t pll0, pll1, reg; 677 int i; 678 679 switch (idx) { 680 case IMX8MM_ARM_PLL: 681 pre_div = 3; 682 switch (freq) { 683 case 1800000000U: 684 main_div = 225; 685 post_div = 0; 686 break; 687 case 1600000000U: 688 main_div = 200; 689 post_div = 0; 690 break; 691 case 1200000000U: 692 main_div = 300; 693 post_div = 1; 694 break; 695 case 1000000000U: 696 main_div = 250; 697 post_div = 1; 698 break; 699 case 800000000U: 700 main_div = 200; 701 post_div = 1; 702 break; 703 case 750000000U: 704 main_div = 250; 705 post_div = 2; 706 break; 707 case 700000000U: 708 main_div = 350; 709 post_div = 2; 710 break; 711 case 600000000U: 712 main_div = 300; 713 post_div = 2; 714 break; 715 default: 716 printf("%s: 0x%08x\n", __func__, idx); 717 return -1; 718 } 719 pll0 = CCM_14XX_IMX8M_ARM_PLL_GNRL_CTL; 720 pll1 = CCM_14XX_IMX8M_ARM_PLL_DIV_CTL; 721 break; 722 default: 723 printf("%s: 0x%08x\n", __func__, idx); 724 return -1; 725 } 726 727 regmap_write_4(sc->sc_anatop, pll0, 728 regmap_read_4(sc->sc_anatop, pll0) | 729 CCM_INT_PLL_LOCK_SEL); 730 regmap_write_4(sc->sc_anatop, pll0, 731 regmap_read_4(sc->sc_anatop, pll0) & 732 ~CCM_INT_PLL_RST); 733 regmap_write_4(sc->sc_anatop, pll1, 734 main_div << CCM_INT_PLL_MAIN_DIV_SHIFT | 735 pre_div << CCM_INT_PLL_PRE_DIV_SHIFT | 736 post_div << CCM_INT_PLL_POST_DIV_SHIFT); 737 delay(3); 738 regmap_write_4(sc->sc_anatop, pll0, 739 regmap_read_4(sc->sc_anatop, pll0) | 740 CCM_INT_PLL_RST); 741 for (i = 0; i < 5000; i++) { 742 reg = regmap_read_4(sc->sc_anatop, pll0); 743 if (reg & CCM_INT_PLL_LOCK) 744 break; 745 delay(10); 746 } 747 if (i == 5000) 748 printf("%s: timeout\n", __func__); 749 regmap_write_4(sc->sc_anatop, pll0, 750 regmap_read_4(sc->sc_anatop, pll0) & 751 ~CCM_INT_PLL_BYPASS); 752 753 return 0; 754 } 755 756 uint32_t 757 imxccm_imx8mm_enet(struct imxccm_softc *sc, uint32_t idx) 758 { 759 uint32_t mux; 760 761 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 762 return 0; 763 764 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 765 mux >>= sc->sc_muxs[idx].shift; 766 mux &= sc->sc_muxs[idx].mask; 767 768 switch (mux) { 769 case 0: 770 return clock_get_frequency(sc->sc_node, "osc_24m"); 771 case 1: 772 return 266 * 1000 * 1000; /* sys1_pll_266m */ 773 default: 774 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 775 return 0; 776 } 777 } 778 779 uint32_t 780 imxccm_imx8mm_ahb(struct imxccm_softc *sc, uint32_t idx) 781 { 782 uint32_t mux; 783 784 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 785 return 0; 786 787 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 788 mux >>= sc->sc_muxs[idx].shift; 789 mux &= sc->sc_muxs[idx].mask; 790 791 switch (mux) { 792 case 0: 793 return clock_get_frequency(sc->sc_node, "osc_24m"); 794 case 1: 795 return 133 * 1000 * 1000; /* sys_pll1_133m */ 796 case 2: 797 return 800 * 1000 * 1000; /* sys_pll1_800m */ 798 case 3: 799 return 400 * 1000 * 1000; /* sys_pll1_400m */ 800 case 4: 801 return 125 * 1000 * 1000; /* sys_pll2_125m */ 802 default: 803 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 804 return 0; 805 } 806 } 807 808 uint32_t 809 imxccm_imx8mm_i2c(struct imxccm_softc *sc, uint32_t idx) 810 { 811 uint32_t mux; 812 813 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 814 return 0; 815 816 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 817 mux >>= sc->sc_muxs[idx].shift; 818 mux &= sc->sc_muxs[idx].mask; 819 820 switch (mux) { 821 case 0: 822 return clock_get_frequency(sc->sc_node, "osc_24m"); 823 default: 824 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 825 return 0; 826 } 827 } 828 829 uint32_t 830 imxccm_imx8mm_uart(struct imxccm_softc *sc, uint32_t idx) 831 { 832 uint32_t mux; 833 834 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 835 return 0; 836 837 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 838 mux >>= sc->sc_muxs[idx].shift; 839 mux &= sc->sc_muxs[idx].mask; 840 841 switch (mux) { 842 case 0: 843 return clock_get_frequency(sc->sc_node, "osc_24m"); 844 default: 845 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 846 return 0; 847 } 848 } 849 850 uint32_t 851 imxccm_imx8mm_usdhc(struct imxccm_softc *sc, uint32_t idx) 852 { 853 uint32_t mux; 854 855 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 856 return 0; 857 858 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 859 mux >>= sc->sc_muxs[idx].shift; 860 mux &= sc->sc_muxs[idx].mask; 861 862 switch (mux) { 863 case 0: 864 return clock_get_frequency(sc->sc_node, "osc_24m"); 865 case 1: 866 return 400 * 1000 * 1000; /* sys1_pll_400m */ 867 default: 868 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 869 return 0; 870 } 871 } 872 873 uint32_t 874 imxccm_imx8mq_ecspi(struct imxccm_softc *sc, uint32_t idx) 875 { 876 uint32_t mux; 877 878 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 879 return 0; 880 881 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 882 mux >>= sc->sc_muxs[idx].shift; 883 mux &= sc->sc_muxs[idx].mask; 884 885 switch (mux) { 886 case 0: 887 return clock_get_frequency(sc->sc_node, "osc_25m"); 888 case 1: 889 return 200 * 1000 * 1000; /* sys2_pll_200m */ 890 default: 891 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 892 return 0; 893 } 894 } 895 896 uint32_t 897 imxccm_imx8mq_enet(struct imxccm_softc *sc, uint32_t idx) 898 { 899 uint32_t mux; 900 901 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 902 return 0; 903 904 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 905 mux >>= sc->sc_muxs[idx].shift; 906 mux &= sc->sc_muxs[idx].mask; 907 908 switch (mux) { 909 case 0: 910 return clock_get_frequency(sc->sc_node, "osc_25m"); 911 case 1: 912 return 266 * 1000 * 1000; /* sys1_pll_266m */ 913 default: 914 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 915 return 0; 916 } 917 } 918 919 uint32_t 920 imxccm_imx8mq_ahb(struct imxccm_softc *sc, uint32_t idx) 921 { 922 uint32_t mux; 923 924 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 925 return 0; 926 927 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 928 mux >>= sc->sc_muxs[idx].shift; 929 mux &= sc->sc_muxs[idx].mask; 930 931 switch (mux) { 932 case 0: 933 return clock_get_frequency(sc->sc_node, "osc_25m"); 934 case 1: 935 return 133 * 1000 * 1000; /* sys1_pll_133m */ 936 case 2: 937 return 800 * 1000 * 1000; /* sys1_pll_800m */ 938 case 3: 939 return 400 * 1000 * 1000; /* sys1_pll_400m */ 940 case 4: 941 return 125 * 1000 * 1000; /* sys2_pll_125m */ 942 default: 943 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 944 return 0; 945 } 946 } 947 948 uint32_t 949 imxccm_imx8mq_i2c(struct imxccm_softc *sc, uint32_t idx) 950 { 951 uint32_t mux; 952 953 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 954 return 0; 955 956 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 957 mux >>= sc->sc_muxs[idx].shift; 958 mux &= sc->sc_muxs[idx].mask; 959 960 switch (mux) { 961 case 0: 962 return clock_get_frequency(sc->sc_node, "osc_25m"); 963 default: 964 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 965 return 0; 966 } 967 } 968 969 uint32_t 970 imxccm_imx8mq_pwm(struct imxccm_softc *sc, uint32_t idx) 971 { 972 uint32_t mux; 973 974 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 975 return 0; 976 977 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 978 mux >>= sc->sc_muxs[idx].shift; 979 mux &= sc->sc_muxs[idx].mask; 980 981 switch (mux) { 982 case 0: 983 return clock_get_frequency(sc->sc_node, "osc_25m"); 984 case 1: 985 return 100 * 1000 * 1000; /* sys1_pll_100m */ 986 case 2: 987 return 160 * 1000 * 1000; /* sys1_pll_160m */ 988 case 3: 989 return 40 * 1000 * 1000; /* sys1_pll_40m */ 990 default: 991 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 992 return 0; 993 } 994 } 995 996 uint32_t 997 imxccm_imx8mq_uart(struct imxccm_softc *sc, uint32_t idx) 998 { 999 uint32_t mux; 1000 1001 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 1002 return 0; 1003 1004 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 1005 mux >>= sc->sc_muxs[idx].shift; 1006 mux &= sc->sc_muxs[idx].mask; 1007 1008 switch (mux) { 1009 case 0: 1010 return clock_get_frequency(sc->sc_node, "osc_25m"); 1011 default: 1012 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 1013 return 0; 1014 } 1015 } 1016 1017 uint32_t 1018 imxccm_imx8mq_usdhc(struct imxccm_softc *sc, uint32_t idx) 1019 { 1020 uint32_t mux; 1021 1022 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 1023 return 0; 1024 1025 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 1026 mux >>= sc->sc_muxs[idx].shift; 1027 mux &= sc->sc_muxs[idx].mask; 1028 1029 switch (mux) { 1030 case 0: 1031 return clock_get_frequency(sc->sc_node, "osc_25m"); 1032 case 1: 1033 return 400 * 1000 * 1000; /* sys1_pll_400m */ 1034 default: 1035 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 1036 return 0; 1037 } 1038 } 1039 1040 uint32_t 1041 imxccm_imx8mq_usb(struct imxccm_softc *sc, uint32_t idx) 1042 { 1043 uint32_t mux; 1044 1045 if (idx >= sc->sc_nmuxs || sc->sc_muxs[idx].reg == 0) 1046 return 0; 1047 1048 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 1049 mux >>= sc->sc_muxs[idx].shift; 1050 mux &= sc->sc_muxs[idx].mask; 1051 1052 switch (mux) { 1053 case 0: 1054 return clock_get_frequency(sc->sc_node, "osc_25m"); 1055 case 1: 1056 if (idx == IMX8MQ_CLK_USB_CORE_REF || 1057 idx == IMX8MQ_CLK_USB_PHY_REF) 1058 return 100 * 1000 * 1000; /* sys1_pll_100m */ 1059 if (idx == IMX8MQ_CLK_USB_BUS) 1060 return 500 * 1000 * 1000; /* sys2_pll_500m */ 1061 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 1062 return 0; 1063 default: 1064 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 1065 return 0; 1066 } 1067 } 1068 1069 uint32_t 1070 imxccm_imx8mq_get_pll(struct imxccm_softc *sc, uint32_t idx) 1071 { 1072 uint32_t divr_val, divq_val, divf_val; 1073 uint32_t divff, divfi; 1074 uint32_t pllout_div; 1075 uint32_t pll0, pll1; 1076 uint32_t freq; 1077 uint32_t mux; 1078 1079 pllout_div = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_PLLOUT_DIV_CFG); 1080 1081 switch (idx) { 1082 case IMX8MQ_ARM_PLL: 1083 pll0 = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_ARM_PLL0); 1084 pll1 = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_ARM_PLL1); 1085 pllout_div >>= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_SHIFT; 1086 pllout_div &= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_MASK; 1087 break; 1088 default: 1089 printf("%s: 0x%08x\n", __func__, idx); 1090 return 0; 1091 } 1092 1093 if (pll0 & CCM_FRAC_PLL_POWERDOWN) 1094 return 0; 1095 1096 if ((pll0 & CCM_FRAC_PLL_ENABLE) == 0) 1097 return 0; 1098 1099 mux = (pll0 >> CCM_FRAC_PLL_REFCLK_SEL_SHIFT) & 1100 CCM_FRAC_PLL_REFCLK_SEL_MASK; 1101 switch (mux) { 1102 case 0: 1103 freq = clock_get_frequency(sc->sc_node, "osc_25m"); 1104 break; 1105 case 1: 1106 case 2: 1107 freq = clock_get_frequency(sc->sc_node, "osc_27m"); 1108 break; 1109 default: 1110 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 1111 return 0; 1112 } 1113 1114 if (pll0 & CCM_FRAC_PLL_BYPASS) 1115 return freq; 1116 1117 divr_val = (pll0 >> CCM_FRAC_PLL_REFCLK_DIV_VAL_SHIFT) & 1118 CCM_FRAC_PLL_REFCLK_DIV_VAL_MASK; 1119 divq_val = pll0 & CCM_FRAC_PLL_OUTPUT_DIV_VAL_MASK; 1120 divff = (pll1 >> CCM_FRAC_PLL_FRAC_DIV_CTL_SHIFT) & 1121 CCM_FRAC_PLL_FRAC_DIV_CTL_MASK; 1122 divfi = pll1 & CCM_FRAC_PLL_INT_DIV_CTL_MASK; 1123 divf_val = 1 + divfi + divff / CCM_FRAC_PLL_DENOM; 1124 1125 freq = freq / (divr_val + 1) * 8 * divf_val / ((divq_val + 1) * 2); 1126 return freq / (pllout_div + 1); 1127 } 1128 1129 int 1130 imxccm_imx8mq_set_pll(struct imxccm_softc *sc, uint32_t idx, uint64_t freq) 1131 { 1132 uint64_t divff, divfi, divr; 1133 uint32_t pllout_div; 1134 uint32_t pll0, pll1; 1135 uint32_t mux, reg; 1136 uint64_t pfreq; 1137 int i; 1138 1139 pllout_div = regmap_read_4(sc->sc_anatop, CCM_FRAC_IMX8M_PLLOUT_DIV_CFG); 1140 1141 switch (idx) { 1142 case IMX8MQ_ARM_PLL: 1143 pll0 = CCM_FRAC_IMX8M_ARM_PLL0; 1144 pll1 = CCM_FRAC_IMX8M_ARM_PLL1; 1145 pllout_div >>= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_SHIFT; 1146 pllout_div &= CCM_FRAC_IMX8M_PLLOUT_DIV_CFG_ARM_MASK; 1147 /* XXX: Assume fixed divider to ease math. */ 1148 KASSERT(pllout_div == 0); 1149 divr = 5; 1150 break; 1151 default: 1152 printf("%s: 0x%08x\n", __func__, idx); 1153 return -1; 1154 } 1155 1156 reg = regmap_read_4(sc->sc_anatop, pll0); 1157 mux = (reg >> CCM_FRAC_PLL_REFCLK_SEL_SHIFT) & 1158 CCM_FRAC_PLL_REFCLK_SEL_MASK; 1159 switch (mux) { 1160 case 0: 1161 pfreq = clock_get_frequency(sc->sc_node, "osc_25m"); 1162 break; 1163 case 1: 1164 case 2: 1165 pfreq = clock_get_frequency(sc->sc_node, "osc_27m"); 1166 break; 1167 default: 1168 printf("%s: 0x%08x 0x%08x\n", __func__, idx, mux); 1169 return -1; 1170 } 1171 1172 /* Frac divider follows the PLL */ 1173 freq *= divr; 1174 1175 /* PLL calculation */ 1176 freq *= 2; 1177 pfreq *= 8; 1178 divfi = freq / pfreq; 1179 divff = (uint64_t)(freq - divfi * pfreq); 1180 divff = (divff * CCM_FRAC_PLL_DENOM) / pfreq; 1181 1182 reg = regmap_read_4(sc->sc_anatop, pll1); 1183 reg &= ~(CCM_FRAC_PLL_FRAC_DIV_CTL_MASK << CCM_FRAC_PLL_FRAC_DIV_CTL_SHIFT); 1184 reg |= divff << CCM_FRAC_PLL_FRAC_DIV_CTL_SHIFT; 1185 reg &= ~(CCM_FRAC_PLL_INT_DIV_CTL_MASK << CCM_FRAC_PLL_INT_DIV_CTL_SHIFT); 1186 reg |= (divfi - 1) << CCM_FRAC_PLL_INT_DIV_CTL_SHIFT; 1187 regmap_write_4(sc->sc_anatop, pll1, reg); 1188 1189 reg = regmap_read_4(sc->sc_anatop, pll0); 1190 reg &= ~CCM_FRAC_PLL_OUTPUT_DIV_VAL_MASK; 1191 reg &= ~(CCM_FRAC_PLL_REFCLK_DIV_VAL_MASK << CCM_FRAC_PLL_REFCLK_DIV_VAL_SHIFT); 1192 reg |= (divr - 1) << CCM_FRAC_PLL_REFCLK_DIV_VAL_SHIFT; 1193 regmap_write_4(sc->sc_anatop, pll0, reg); 1194 1195 reg = regmap_read_4(sc->sc_anatop, pll0); 1196 reg |= CCM_FRAC_PLL_NEWDIV_VAL; 1197 regmap_write_4(sc->sc_anatop, pll0, reg); 1198 1199 for (i = 0; i < 5000; i++) { 1200 reg = regmap_read_4(sc->sc_anatop, pll0); 1201 if (reg & CCM_FRAC_PLL_BYPASS) 1202 break; 1203 if (reg & CCM_FRAC_PLL_POWERDOWN) 1204 break; 1205 if (reg & CCM_FRAC_PLL_NEWDIV_ACK) 1206 break; 1207 delay(10); 1208 } 1209 if (i == 5000) 1210 printf("%s: timeout\n", __func__); 1211 1212 reg = regmap_read_4(sc->sc_anatop, pll0); 1213 reg &= ~CCM_FRAC_PLL_NEWDIV_VAL; 1214 regmap_write_4(sc->sc_anatop, pll0, reg); 1215 1216 return 0; 1217 } 1218 1219 int 1220 imxccm_imx8m_set_div(struct imxccm_softc *sc, uint32_t idx, uint64_t freq, 1221 uint64_t parent_freq) 1222 { 1223 uint64_t div; 1224 uint32_t reg; 1225 1226 if (parent_freq < freq) { 1227 printf("%s: parent frequency too low (0x%08x)\n", 1228 __func__, idx); 1229 return -1; 1230 } 1231 1232 /* divisor can only be changed if enabled */ 1233 imxccm_enable(sc, &idx, 1); 1234 1235 div = 0; 1236 while (parent_freq / (div + 1) > freq) 1237 div++; 1238 reg = HREAD4(sc, sc->sc_divs[idx].reg); 1239 reg &= ~(sc->sc_divs[idx].mask << sc->sc_divs[idx].shift); 1240 reg |= (div << sc->sc_divs[idx].shift); 1241 HWRITE4(sc, sc->sc_divs[idx].reg, reg); 1242 HCLR4(sc, sc->sc_predivs[idx].reg, 1243 sc->sc_predivs[idx].mask << sc->sc_predivs[idx].shift); 1244 return 0; 1245 } 1246 1247 void 1248 imxccm_enable_parent(struct imxccm_softc *sc, uint32_t parent, int on) 1249 { 1250 if (on) 1251 imxccm_enable(sc, &parent, on); 1252 } 1253 1254 void 1255 imxccm_enable(void *cookie, uint32_t *cells, int on) 1256 { 1257 struct imxccm_softc *sc = cookie; 1258 uint32_t idx = cells[0], parent; 1259 uint32_t pcells[2]; 1260 uint16_t reg; 1261 uint8_t pos; 1262 1263 /* Dummy clock. */ 1264 if (idx == 0) 1265 return; 1266 1267 if (sc->sc_gates == imx8mm_gates) { 1268 switch (idx) { 1269 case IMX8MM_CLK_PCIE1_CTRL: 1270 case IMX8MM_CLK_PCIE2_CTRL: 1271 pcells[0] = sc->sc_phandle; 1272 pcells[1] = IMX8MM_SYS_PLL2_250M; 1273 imxccm_set_parent(cookie, &idx, pcells); 1274 break; 1275 case IMX8MM_CLK_PCIE1_PHY: 1276 case IMX8MM_CLK_PCIE2_PHY: 1277 pcells[0] = sc->sc_phandle; 1278 pcells[1] = IMX8MM_SYS_PLL2_100M; 1279 imxccm_set_parent(cookie, &idx, pcells); 1280 break; 1281 } 1282 } else if (sc->sc_gates == imx8mq_gates) { 1283 switch (idx) { 1284 case IMX8MQ_CLK_32K: 1285 /* always on */ 1286 return; 1287 case IMX8MQ_CLK_PCIE1_CTRL: 1288 case IMX8MQ_CLK_PCIE2_CTRL: 1289 pcells[0] = sc->sc_phandle; 1290 pcells[1] = IMX8MQ_SYS2_PLL_250M; 1291 imxccm_set_parent(cookie, &idx, pcells); 1292 break; 1293 case IMX8MQ_CLK_PCIE1_PHY: 1294 case IMX8MQ_CLK_PCIE2_PHY: 1295 pcells[0] = sc->sc_phandle; 1296 pcells[1] = IMX8MQ_SYS2_PLL_100M; 1297 imxccm_set_parent(cookie, &idx, pcells); 1298 break; 1299 } 1300 } else if (sc->sc_gates == imx7d_gates) { 1301 if (sc->sc_anatop == NULL) { 1302 sc->sc_anatop = regmap_bycompatible("fsl,imx7d-anatop"); 1303 KASSERT(sc->sc_anatop); 1304 } 1305 1306 switch (idx) { 1307 case IMX7D_PLL_ENET_MAIN_125M_CLK: 1308 regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_ENET_SET, 1309 CCM_ANALOG_PLL_ENET_ENABLE_CLK_125MHZ); 1310 return; 1311 default: 1312 break; 1313 } 1314 } else if (sc->sc_gates == imx6_gates) { 1315 if (sc->sc_anatop == NULL) { 1316 sc->sc_anatop = regmap_bycompatible("fsl,imx6q-anatop"); 1317 KASSERT(sc->sc_anatop); 1318 } 1319 1320 switch (idx) { 1321 case IMX6_CLK_PLL3: 1322 imxccm_imx6_enable_pll_usb1(sc, on); 1323 return; 1324 case IMX6_CLK_PLL6: 1325 imxccm_imx6_enable_pll_enet(sc, on); 1326 return; 1327 case IMX6_CLK_PLL7: 1328 imxccm_imx6_enable_pll_usb2(sc, on); 1329 return; 1330 case IMX6_CLK_PLL3_USB_OTG: 1331 imxccm_enable_parent(sc, IMX6_CLK_PLL3, on); 1332 regmap_write_4(sc->sc_anatop, 1333 on ? CCM_ANALOG_PLL_USB1_SET : CCM_ANALOG_PLL_USB1_CLR, 1334 CCM_ANALOG_PLL_USB1_ENABLE); 1335 return; 1336 case IMX6_CLK_PLL6_ENET: 1337 imxccm_enable_parent(sc, IMX6_CLK_PLL6, on); 1338 regmap_write_4(sc->sc_anatop, 1339 on ? CCM_ANALOG_PLL_ENET_SET : CCM_ANALOG_PLL_ENET_CLR, 1340 CCM_ANALOG_PLL_ENET_ENABLE); 1341 return; 1342 case IMX6_CLK_PLL7_USB_HOST: 1343 imxccm_enable_parent(sc, IMX6_CLK_PLL7, on); 1344 regmap_write_4(sc->sc_anatop, 1345 on ? CCM_ANALOG_PLL_USB2_SET : CCM_ANALOG_PLL_USB2_CLR, 1346 CCM_ANALOG_PLL_USB2_ENABLE); 1347 return; 1348 case IMX6_CLK_USBPHY1: 1349 /* PLL outputs should alwas be on. */ 1350 regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB1_SET, 1351 CCM_ANALOG_PLL_USB1_EN_USB_CLKS); 1352 imxccm_enable_parent(sc, IMX6_CLK_PLL3_USB_OTG, on); 1353 return; 1354 case IMX6_CLK_USBPHY2: 1355 /* PLL outputs should alwas be on. */ 1356 regmap_write_4(sc->sc_anatop, CCM_ANALOG_PLL_USB2_SET, 1357 CCM_ANALOG_PLL_USB2_EN_USB_CLKS); 1358 imxccm_enable_parent(sc, IMX6_CLK_PLL7_USB_HOST, on); 1359 return; 1360 case IMX6_CLK_SATA_REF_100: 1361 imxccm_enable_parent(sc, IMX6_CLK_PLL6_ENET, on); 1362 regmap_write_4(sc->sc_anatop, 1363 on ? CCM_ANALOG_PLL_ENET_SET : CCM_ANALOG_PLL_ENET_CLR, 1364 CCM_ANALOG_PLL_ENET_ENABLE_100M); 1365 return; 1366 case IMX6_CLK_ENET_REF: 1367 imxccm_enable_parent(sc, IMX6_CLK_PLL6_ENET, on); 1368 return; 1369 case IMX6_CLK_IPG: 1370 case IMX6_CLK_IPG_PER: 1371 case IMX6_CLK_ECSPI_ROOT: 1372 /* always on */ 1373 return; 1374 default: 1375 break; 1376 } 1377 } 1378 1379 if (on) { 1380 if (idx < sc->sc_ngates && sc->sc_gates[idx].parent) { 1381 parent = sc->sc_gates[idx].parent; 1382 imxccm_enable(sc, &parent, on); 1383 } 1384 1385 if (idx < sc->sc_ndivs && sc->sc_divs[idx].parent) { 1386 parent = sc->sc_divs[idx].parent; 1387 imxccm_enable(sc, &parent, on); 1388 } 1389 } 1390 1391 if (idx >= sc->sc_ngates || sc->sc_gates[idx].reg == 0) { 1392 if ((idx < sc->sc_ndivs && sc->sc_divs[idx].reg != 0) || 1393 (idx < sc->sc_nmuxs && sc->sc_muxs[idx].reg != 0)) 1394 return; 1395 printf("%s: 0x%08x\n", __func__, idx); 1396 return; 1397 } 1398 1399 reg = sc->sc_gates[idx].reg; 1400 pos = sc->sc_gates[idx].pos; 1401 1402 if (on) 1403 HSET4(sc, reg, 0x3 << (2 * pos)); 1404 else 1405 HCLR4(sc, reg, 0x3 << (2 * pos)); 1406 } 1407 1408 uint32_t 1409 imxccm_get_frequency(void *cookie, uint32_t *cells) 1410 { 1411 struct imxccm_softc *sc = cookie; 1412 uint32_t idx = cells[0]; 1413 uint32_t div, pre, reg, parent; 1414 uint32_t freq; 1415 1416 /* Dummy clock. */ 1417 if (idx == 0) 1418 return 0; 1419 1420 if (idx < sc->sc_ngates && sc->sc_gates[idx].parent) { 1421 parent = sc->sc_gates[idx].parent; 1422 return imxccm_get_frequency(sc, &parent); 1423 } 1424 1425 if (idx < sc->sc_ndivs && sc->sc_divs[idx].parent) { 1426 div = HREAD4(sc, sc->sc_divs[idx].reg); 1427 div = div >> sc->sc_divs[idx].shift; 1428 div = div & sc->sc_divs[idx].mask; 1429 parent = sc->sc_divs[idx].parent; 1430 return imxccm_get_frequency(sc, &parent) / (div + 1); 1431 } 1432 1433 if (sc->sc_gates == imx8mm_gates) { 1434 switch (idx) { 1435 case IMX8MM_CLK_ARM: 1436 parent = IMX8MM_ARM_PLL; 1437 return imxccm_get_frequency(sc, &parent); 1438 case IMX8MM_ARM_PLL: 1439 return imxccm_imx8mm_get_pll(sc, idx); 1440 } 1441 1442 /* These are composite clocks. */ 1443 if (idx < sc->sc_ngates && sc->sc_gates[idx].reg && 1444 idx < sc->sc_ndivs && sc->sc_divs[idx].reg && 1445 idx < sc->sc_npredivs && sc->sc_predivs[idx].reg) { 1446 switch (idx) { 1447 case IMX8MM_CLK_ENET_AXI: 1448 freq = imxccm_imx8mm_enet(sc, idx); 1449 break; 1450 case IMX8MM_CLK_AHB: 1451 freq = imxccm_imx8mm_ahb(sc, idx); 1452 break; 1453 case IMX8MM_CLK_I2C1: 1454 case IMX8MM_CLK_I2C2: 1455 case IMX8MM_CLK_I2C3: 1456 case IMX8MM_CLK_I2C4: 1457 freq = imxccm_imx8mm_i2c(sc, idx); 1458 break; 1459 case IMX8MM_CLK_UART1: 1460 case IMX8MM_CLK_UART2: 1461 case IMX8MM_CLK_UART3: 1462 case IMX8MM_CLK_UART4: 1463 freq = imxccm_imx8mm_uart(sc, idx); 1464 break; 1465 case IMX8MM_CLK_USDHC1: 1466 case IMX8MM_CLK_USDHC2: 1467 case IMX8MM_CLK_USDHC3: 1468 freq = imxccm_imx8mm_usdhc(sc, idx); 1469 break; 1470 default: 1471 printf("%s: 0x%08x\n", __func__, idx); 1472 return 0; 1473 } 1474 1475 reg = HREAD4(sc, sc->sc_divs[idx].reg); 1476 div = reg >> sc->sc_divs[idx].shift; 1477 div = div & sc->sc_divs[idx].mask; 1478 pre = reg >> sc->sc_predivs[idx].shift; 1479 pre = pre & sc->sc_predivs[idx].mask; 1480 return ((freq / (pre + 1)) / (div + 1)); 1481 } 1482 } else if (sc->sc_gates == imx8mq_gates) { 1483 switch (idx) { 1484 case IMX8MQ_CLK_ARM: 1485 parent = IMX8MQ_ARM_PLL; 1486 return imxccm_get_frequency(sc, &parent); 1487 case IMX8MQ_ARM_PLL: 1488 return imxccm_imx8mq_get_pll(sc, idx); 1489 } 1490 1491 /* These are composite clocks. */ 1492 if (idx < sc->sc_ngates && sc->sc_gates[idx].reg && 1493 idx < sc->sc_ndivs && sc->sc_divs[idx].reg && 1494 idx < sc->sc_npredivs && sc->sc_predivs[idx].reg) { 1495 switch (idx) { 1496 case IMX8MQ_CLK_ENET_AXI: 1497 freq = imxccm_imx8mq_enet(sc, idx); 1498 break; 1499 case IMX8MQ_CLK_AHB: 1500 freq = imxccm_imx8mq_ahb(sc, idx); 1501 break; 1502 case IMX8MQ_CLK_I2C1: 1503 case IMX8MQ_CLK_I2C2: 1504 case IMX8MQ_CLK_I2C3: 1505 case IMX8MQ_CLK_I2C4: 1506 freq = imxccm_imx8mq_i2c(sc, idx); 1507 break; 1508 case IMX8MQ_CLK_UART1: 1509 case IMX8MQ_CLK_UART2: 1510 case IMX8MQ_CLK_UART3: 1511 case IMX8MQ_CLK_UART4: 1512 freq = imxccm_imx8mq_uart(sc, idx); 1513 break; 1514 case IMX8MQ_CLK_USDHC1: 1515 case IMX8MQ_CLK_USDHC2: 1516 freq = imxccm_imx8mq_usdhc(sc, idx); 1517 break; 1518 case IMX8MQ_CLK_USB_BUS: 1519 case IMX8MQ_CLK_USB_CORE_REF: 1520 case IMX8MQ_CLK_USB_PHY_REF: 1521 freq = imxccm_imx8mq_usb(sc, idx); 1522 break; 1523 case IMX8MQ_CLK_ECSPI1: 1524 case IMX8MQ_CLK_ECSPI2: 1525 case IMX8MQ_CLK_ECSPI3: 1526 freq = imxccm_imx8mq_ecspi(sc, idx); 1527 break; 1528 case IMX8MQ_CLK_PWM1: 1529 case IMX8MQ_CLK_PWM2: 1530 case IMX8MQ_CLK_PWM3: 1531 case IMX8MQ_CLK_PWM4: 1532 freq = imxccm_imx8mq_pwm(sc, idx); 1533 break; 1534 default: 1535 printf("%s: 0x%08x\n", __func__, idx); 1536 return 0; 1537 } 1538 1539 reg = HREAD4(sc, sc->sc_divs[idx].reg); 1540 div = reg >> sc->sc_divs[idx].shift; 1541 div = div & sc->sc_divs[idx].mask; 1542 pre = reg >> sc->sc_predivs[idx].shift; 1543 pre = pre & sc->sc_predivs[idx].mask; 1544 return ((freq / (pre + 1)) / (div + 1)); 1545 } 1546 1547 } else if (sc->sc_gates == imx7d_gates) { 1548 switch (idx) { 1549 case IMX7D_ENET_AXI_ROOT_SRC: 1550 return imxccm_imx7d_enet(sc, idx); 1551 case IMX7D_I2C1_ROOT_SRC: 1552 case IMX7D_I2C2_ROOT_SRC: 1553 case IMX7D_I2C3_ROOT_SRC: 1554 case IMX7D_I2C4_ROOT_SRC: 1555 return imxccm_imx7d_i2c(sc, idx); 1556 case IMX7D_UART1_ROOT_SRC: 1557 case IMX7D_UART2_ROOT_SRC: 1558 case IMX7D_UART3_ROOT_SRC: 1559 case IMX7D_UART4_ROOT_SRC: 1560 case IMX7D_UART5_ROOT_SRC: 1561 case IMX7D_UART6_ROOT_SRC: 1562 case IMX7D_UART7_ROOT_SRC: 1563 return imxccm_imx7d_uart(sc, idx); 1564 case IMX7D_USDHC1_ROOT_SRC: 1565 case IMX7D_USDHC2_ROOT_SRC: 1566 case IMX7D_USDHC3_ROOT_SRC: 1567 return imxccm_imx7d_usdhc(sc, idx); 1568 } 1569 } else if (sc->sc_gates == imx6ul_gates) { 1570 switch (idx) { 1571 case IMX6UL_CLK_ARM: 1572 return imxccm_get_armclk(sc); 1573 case IMX6UL_CLK_IPG: 1574 return imxccm_get_ipgclk(sc); 1575 case IMX6UL_CLK_PERCLK: 1576 return imxccm_get_ipg_perclk(sc); 1577 case IMX6UL_CLK_UART1_SERIAL: 1578 return imxccm_get_uartclk(sc); 1579 case IMX6UL_CLK_USDHC1: 1580 case IMX6UL_CLK_USDHC2: 1581 return imxccm_get_usdhx(sc, idx - IMX6UL_CLK_USDHC1 + 1); 1582 } 1583 } else if (sc->sc_gates == imx6_gates) { 1584 switch (idx) { 1585 case IMX6_CLK_AHB: 1586 return imxccm_get_ahbclk(sc); 1587 case IMX6_CLK_ARM: 1588 return imxccm_get_armclk(sc); 1589 case IMX6_CLK_IPG: 1590 return imxccm_get_ipgclk(sc); 1591 case IMX6_CLK_IPG_PER: 1592 return imxccm_get_ipg_perclk(sc); 1593 case IMX6_CLK_ECSPI_ROOT: 1594 return imxccm_get_ecspiclk(sc); 1595 case IMX6_CLK_UART_SERIAL: 1596 return imxccm_get_uartclk(sc); 1597 case IMX6_CLK_USDHC1: 1598 case IMX6_CLK_USDHC2: 1599 case IMX6_CLK_USDHC3: 1600 case IMX6_CLK_USDHC4: 1601 return imxccm_get_usdhx(sc, idx - IMX6_CLK_USDHC1 + 1); 1602 } 1603 } 1604 1605 printf("%s: 0x%08x\n", __func__, idx); 1606 return 0; 1607 } 1608 1609 int 1610 imxccm_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) 1611 { 1612 struct imxccm_softc *sc = cookie; 1613 uint32_t idx = cells[0]; 1614 uint32_t reg, div, parent, parent_freq; 1615 uint32_t pcells[2]; 1616 int ret; 1617 1618 if (sc->sc_divs == imx8mm_divs) { 1619 switch (idx) { 1620 case IMX8MM_CLK_ARM: 1621 parent = IMX8MM_CLK_A53_SRC; 1622 return imxccm_set_frequency(cookie, &parent, freq); 1623 case IMX8MM_CLK_A53_SRC: 1624 pcells[0] = sc->sc_phandle; 1625 pcells[1] = IMX8MM_SYS_PLL1_800M; 1626 ret = imxccm_set_parent(cookie, &idx, pcells); 1627 if (ret) 1628 return ret; 1629 ret = imxccm_imx8mm_set_pll(sc, IMX8MM_ARM_PLL, freq); 1630 pcells[0] = sc->sc_phandle; 1631 pcells[1] = IMX8MM_ARM_PLL_OUT; 1632 imxccm_set_parent(cookie, &idx, pcells); 1633 return ret; 1634 case IMX8MM_CLK_USDHC1_ROOT: 1635 case IMX8MM_CLK_USDHC2_ROOT: 1636 case IMX8MM_CLK_USDHC3_ROOT: 1637 parent = sc->sc_gates[idx].parent; 1638 return imxccm_set_frequency(sc, &parent, freq); 1639 case IMX8MM_CLK_USDHC1: 1640 case IMX8MM_CLK_USDHC2: 1641 case IMX8MM_CLK_USDHC3: 1642 parent_freq = imxccm_imx8mm_usdhc(sc, idx); 1643 return imxccm_imx8m_set_div(sc, idx, freq, parent_freq); 1644 } 1645 } else if (sc->sc_divs == imx8mq_divs) { 1646 switch (idx) { 1647 case IMX8MQ_CLK_ARM: 1648 parent = IMX8MQ_CLK_A53_SRC; 1649 return imxccm_set_frequency(cookie, &parent, freq); 1650 case IMX8MQ_CLK_A53_SRC: 1651 pcells[0] = sc->sc_phandle; 1652 pcells[1] = IMX8MQ_SYS1_PLL_800M; 1653 ret = imxccm_set_parent(cookie, &idx, pcells); 1654 if (ret) 1655 return ret; 1656 ret = imxccm_imx8mq_set_pll(sc, IMX8MQ_ARM_PLL, freq); 1657 pcells[0] = sc->sc_phandle; 1658 pcells[1] = IMX8MQ_ARM_PLL_OUT; 1659 imxccm_set_parent(cookie, &idx, pcells); 1660 return ret; 1661 case IMX8MQ_CLK_USB_BUS: 1662 case IMX8MQ_CLK_USB_CORE_REF: 1663 case IMX8MQ_CLK_USB_PHY_REF: 1664 if (imxccm_get_frequency(sc, cells) != freq) 1665 break; 1666 return 0; 1667 case IMX8MQ_CLK_USDHC1: 1668 case IMX8MQ_CLK_USDHC2: 1669 parent_freq = imxccm_imx8mq_usdhc(sc, idx); 1670 return imxccm_imx8m_set_div(sc, idx, freq, parent_freq); 1671 } 1672 } else if (sc->sc_divs == imx7d_divs) { 1673 switch (idx) { 1674 case IMX7D_USDHC1_ROOT_CLK: 1675 case IMX7D_USDHC2_ROOT_CLK: 1676 case IMX7D_USDHC3_ROOT_CLK: 1677 parent = sc->sc_gates[idx].parent; 1678 return imxccm_set_frequency(sc, &parent, freq); 1679 case IMX7D_USDHC1_ROOT_DIV: 1680 case IMX7D_USDHC2_ROOT_DIV: 1681 case IMX7D_USDHC3_ROOT_DIV: 1682 parent = sc->sc_divs[idx].parent; 1683 parent_freq = imxccm_get_frequency(sc, &parent); 1684 div = 0; 1685 while (parent_freq / (div + 1) > freq) 1686 div++; 1687 reg = HREAD4(sc, sc->sc_divs[idx].reg); 1688 reg &= ~(sc->sc_divs[idx].mask << sc->sc_divs[idx].shift); 1689 reg |= (div << sc->sc_divs[idx].shift); 1690 HWRITE4(sc, sc->sc_divs[idx].reg, reg); 1691 return 0; 1692 } 1693 } 1694 1695 printf("%s: 0x%08x %x\n", __func__, idx, freq); 1696 return -1; 1697 } 1698 1699 int 1700 imxccm_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells) 1701 { 1702 struct imxccm_softc *sc = cookie; 1703 uint32_t idx = cells[0]; 1704 uint32_t pidx; 1705 uint32_t mux; 1706 1707 if (pcells[0] != sc->sc_phandle) { 1708 printf("%s: 0x%08x parent 0x%08x\n", __func__, idx, pcells[0]); 1709 return -1; 1710 } 1711 1712 pidx = pcells[1]; 1713 1714 if (sc->sc_muxs == imx8mm_muxs) { 1715 switch (idx) { 1716 case IMX8MM_CLK_A53_SRC: 1717 if (pidx != IMX8MM_ARM_PLL_OUT && 1718 pidx != IMX8MM_SYS_PLL1_800M) 1719 break; 1720 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 1721 mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift); 1722 if (pidx == IMX8MM_ARM_PLL_OUT) 1723 mux |= (0x1 << sc->sc_muxs[idx].shift); 1724 if (pidx == IMX8MM_SYS_PLL1_800M) 1725 mux |= (0x4 << sc->sc_muxs[idx].shift); 1726 HWRITE4(sc, sc->sc_muxs[idx].reg, mux); 1727 return 0; 1728 case IMX8MM_CLK_USB_BUS: 1729 if (pidx != IMX8MM_SYS_PLL2_500M) 1730 break; 1731 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 1732 mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift); 1733 mux |= (0x1 << sc->sc_muxs[idx].shift); 1734 HWRITE4(sc, sc->sc_muxs[idx].reg, mux); 1735 return 0; 1736 case IMX8MM_CLK_USB_CORE_REF: 1737 case IMX8MM_CLK_USB_PHY_REF: 1738 if (pidx != IMX8MM_SYS_PLL1_100M) 1739 break; 1740 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 1741 mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift); 1742 mux |= (0x1 << sc->sc_muxs[idx].shift); 1743 HWRITE4(sc, sc->sc_muxs[idx].reg, mux); 1744 return 0; 1745 case IMX8MM_CLK_PCIE1_CTRL: 1746 case IMX8MM_CLK_PCIE2_CTRL: 1747 if (pidx != IMX8MM_SYS_PLL2_250M) 1748 break; 1749 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 1750 mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift); 1751 mux |= (0x1 << sc->sc_muxs[idx].shift); 1752 HWRITE4(sc, sc->sc_muxs[idx].reg, mux); 1753 return 0; 1754 case IMX8MM_CLK_PCIE1_PHY: 1755 case IMX8MM_CLK_PCIE2_PHY: 1756 if (pidx != IMX8MM_SYS_PLL2_100M) 1757 break; 1758 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 1759 mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift); 1760 mux |= (0x1 << sc->sc_muxs[idx].shift); 1761 HWRITE4(sc, sc->sc_muxs[idx].reg, mux); 1762 return 0; 1763 } 1764 } else if (sc->sc_muxs == imx8mq_muxs) { 1765 switch (idx) { 1766 case IMX8MQ_CLK_A53_SRC: 1767 if (pidx != IMX8MQ_ARM_PLL_OUT && 1768 pidx != IMX8MQ_SYS1_PLL_800M) 1769 break; 1770 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 1771 mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift); 1772 if (pidx == IMX8MQ_ARM_PLL_OUT) 1773 mux |= (0x1 << sc->sc_muxs[idx].shift); 1774 if (pidx == IMX8MQ_SYS1_PLL_800M) 1775 mux |= (0x4 << sc->sc_muxs[idx].shift); 1776 HWRITE4(sc, sc->sc_muxs[idx].reg, mux); 1777 return 0; 1778 case IMX8MQ_CLK_USB_BUS: 1779 if (pidx != IMX8MQ_SYS2_PLL_500M) 1780 break; 1781 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 1782 mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift); 1783 mux |= (0x1 << sc->sc_muxs[idx].shift); 1784 HWRITE4(sc, sc->sc_muxs[idx].reg, mux); 1785 return 0; 1786 case IMX8MQ_CLK_USB_CORE_REF: 1787 case IMX8MQ_CLK_USB_PHY_REF: 1788 if (pidx != IMX8MQ_SYS1_PLL_100M) 1789 break; 1790 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 1791 mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift); 1792 mux |= (0x1 << sc->sc_muxs[idx].shift); 1793 HWRITE4(sc, sc->sc_muxs[idx].reg, mux); 1794 return 0; 1795 case IMX8MQ_CLK_PCIE1_CTRL: 1796 case IMX8MQ_CLK_PCIE2_CTRL: 1797 if (pidx != IMX8MQ_SYS2_PLL_250M) 1798 break; 1799 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 1800 mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift); 1801 mux |= (0x1 << sc->sc_muxs[idx].shift); 1802 HWRITE4(sc, sc->sc_muxs[idx].reg, mux); 1803 return 0; 1804 case IMX8MQ_CLK_PCIE1_PHY: 1805 case IMX8MQ_CLK_PCIE2_PHY: 1806 if (pidx != IMX8MQ_SYS2_PLL_100M) 1807 break; 1808 mux = HREAD4(sc, sc->sc_muxs[idx].reg); 1809 mux &= ~(sc->sc_muxs[idx].mask << sc->sc_muxs[idx].shift); 1810 mux |= (0x1 << sc->sc_muxs[idx].shift); 1811 HWRITE4(sc, sc->sc_muxs[idx].reg, mux); 1812 return 0; 1813 } 1814 } 1815 1816 printf("%s: 0x%08x 0x%08x\n", __func__, idx, pidx); 1817 return -1; 1818 } 1819