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