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