1 /* $OpenBSD: rkclock.c,v 1.10 2017/08/21 21:02:12 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org> 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/sysctl.h> 21 #include <sys/device.h> 22 23 #include <machine/intr.h> 24 #include <machine/bus.h> 25 #include <machine/fdt.h> 26 27 #include <dev/ofw/openfirm.h> 28 #include <dev/ofw/ofw_clock.h> 29 #include <dev/ofw/fdt.h> 30 31 /* RK3288 registers */ 32 #define RK3288_CRU_CPLL_CON(i) (0x0020 + (i) * 4) 33 #define RK3288_CRU_GPLL_CON(i) (0x0030 + (i) * 4) 34 #define RK3288_CRU_CLKSEL_CON(i) (0x0060 + (i) * 4) 35 36 /* RK3399 registers */ 37 #define RK3399_CRU_LPLL_CON(i) (0x0000 + (i) * 4) 38 #define RK3399_CRU_BPLL_CON(i) (0x0020 + (i) * 4) 39 #define RK3399_CRU_DPLL_CON(i) (0x0020 + (i) * 4) 40 #define RK3399_CRU_CPLL_CON(i) (0x0060 + (i) * 4) 41 #define RK3399_CRU_GPLL_CON(i) (0x0080 + (i) * 4) 42 #define RK3399_CRU_NPLL_CON(i) (0x00a0 + (i) * 4) 43 #define RK3399_CRU_CLKSEL_CON(i) (0x0100 + (i) * 4) 44 #define RK3399_CRU_CLKGATE_CON(i) (0x0300 + (i) * 4) 45 #define RK3399_CRU_SOFTRST_CON(i) (0x0400 + (i) * 4) 46 #define RK3399_CRU_SDMMC_CON(i) (0x0580 + (i) * 4) 47 48 #include "rkclock_clocks.h" 49 50 #define HREAD4(sc, reg) \ 51 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) 52 #define HWRITE4(sc, reg, val) \ 53 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 54 #define HSET4(sc, reg, bits) \ 55 HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits)) 56 #define HCLR4(sc, reg, bits) \ 57 HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits)) 58 59 struct rkclock_softc { 60 struct device sc_dev; 61 bus_space_tag_t sc_iot; 62 bus_space_handle_t sc_ioh; 63 64 struct clock_device sc_cd; 65 struct reset_device sc_rd; 66 }; 67 68 int rkclock_match(struct device *, void *, void *); 69 void rkclock_attach(struct device *, struct device *, void *); 70 71 struct cfattach rkclock_ca = { 72 sizeof (struct rkclock_softc), rkclock_match, rkclock_attach 73 }; 74 75 struct cfdriver rkclock_cd = { 76 NULL, "rkclock", DV_DULL 77 }; 78 79 struct rkclock_softc *rkclock_cpuspeed_sc; 80 81 uint32_t rk3288_get_frequency(void *, uint32_t *); 82 int rk3288_set_frequency(void *, uint32_t *, uint32_t); 83 void rk3288_enable(void *, uint32_t *, int); 84 void rk3288_reset(void *, uint32_t *, int); 85 86 uint32_t rk3399_get_frequency(void *, uint32_t *); 87 int rk3399_set_frequency(void *, uint32_t *, uint32_t); 88 void rk3399_enable(void *, uint32_t *, int); 89 void rk3399_reset(void *, uint32_t *, int); 90 int rk3399_cpuspeed(int *); 91 92 uint32_t rk3399_pmu_get_frequency(void *, uint32_t *); 93 int rk3399_pmu_set_frequency(void *, uint32_t *, uint32_t); 94 void rk3399_pmu_enable(void *, uint32_t *, int); 95 void rk3399_pmu_reset(void *, uint32_t *, int); 96 97 struct rkclock_compat { 98 const char *compat; 99 void (*enable)(void *, uint32_t *, int); 100 uint32_t (*get_frequency)(void *, uint32_t *); 101 int (*set_frequency)(void *, uint32_t *, uint32_t); 102 void (*reset)(void *, uint32_t *, int); 103 int (*cpuspeed)(int *); 104 }; 105 106 struct rkclock_compat rkclock_compat[] = { 107 { 108 "rockchip,rk3288-cru", 109 rk3288_enable, rk3288_get_frequency, 110 rk3288_set_frequency, rk3288_reset 111 }, 112 { 113 "rockchip,rk3399-cru", 114 rk3399_enable, rk3399_get_frequency, 115 rk3399_set_frequency, rk3399_reset, 116 rk3399_cpuspeed 117 }, 118 { 119 "rockchip,rk3399-pmucru", 120 rk3399_pmu_enable, rk3399_pmu_get_frequency, 121 rk3399_pmu_set_frequency, rk3399_pmu_reset 122 } 123 }; 124 125 int 126 rkclock_match(struct device *parent, void *match, void *aux) 127 { 128 struct fdt_attach_args *faa = aux; 129 int i; 130 131 for (i = 0; i < nitems(rkclock_compat); i++) { 132 if (OF_is_compatible(faa->fa_node, rkclock_compat[i].compat)) 133 return 1; 134 } 135 136 return 0; 137 } 138 139 void 140 rkclock_attach(struct device *parent, struct device *self, void *aux) 141 { 142 struct rkclock_softc *sc = (struct rkclock_softc *)self; 143 struct fdt_attach_args *faa = aux; 144 int i; 145 146 if (faa->fa_nreg < 1) { 147 printf(": no registers\n"); 148 return; 149 } 150 151 sc->sc_iot = faa->fa_iot; 152 153 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 154 faa->fa_reg[0].size, 0, &sc->sc_ioh)) { 155 printf(": can't map registers\n"); 156 return; 157 } 158 159 printf("\n"); 160 161 for (i = 0; i < nitems(rkclock_compat); i++) { 162 if (OF_is_compatible(faa->fa_node, rkclock_compat[i].compat)) { 163 sc->sc_cd.cd_enable = rkclock_compat[i].enable; 164 sc->sc_cd.cd_get_frequency = 165 rkclock_compat[i].get_frequency; 166 sc->sc_cd.cd_set_frequency = 167 rkclock_compat[i].set_frequency; 168 sc->sc_rd.rd_reset = rkclock_compat[i].reset; 169 if (rkclock_compat[i].cpuspeed) { 170 rkclock_cpuspeed_sc = sc; 171 cpu_cpuspeed = rkclock_compat[i].cpuspeed; 172 } 173 break; 174 } 175 } 176 177 sc->sc_cd.cd_node = faa->fa_node; 178 sc->sc_cd.cd_cookie = sc; 179 clock_register(&sc->sc_cd); 180 181 sc->sc_rd.rd_node = faa->fa_node; 182 sc->sc_rd.rd_cookie = sc; 183 reset_register(&sc->sc_rd); 184 } 185 186 /* 187 * Rockchip RK3288 188 */ 189 190 uint32_t 191 rk3288_get_pll(struct rkclock_softc *sc, bus_size_t base) 192 { 193 uint32_t clkod, clkr, clkf; 194 uint32_t reg; 195 196 reg = HREAD4(sc, base); 197 clkod = (reg >> 0) & 0xf; 198 clkr = (reg >> 8) & 0x3f; 199 reg = HREAD4(sc, base + 4); 200 clkf = (reg >> 0) & 0x1fff; 201 return 24000000ULL * (clkf + 1) / (clkr + 1) / (clkod + 1); 202 } 203 204 uint32_t 205 rk3288_get_frequency(void *cookie, uint32_t *cells) 206 { 207 struct rkclock_softc *sc = cookie; 208 uint32_t idx = cells[0]; 209 uint32_t reg, mux, div_con; 210 211 switch (idx) { 212 case RK3288_PLL_CPLL: 213 return rk3288_get_pll(sc, RK3288_CRU_CPLL_CON(0)); 214 case RK3288_PLL_GPLL: 215 return rk3288_get_pll(sc, RK3288_CRU_GPLL_CON(0)); 216 case RK3288_CLK_SDMMC: 217 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(11)); 218 mux = (reg >> 6) & 0x3; 219 div_con = reg & 0x3f; 220 switch (mux) { 221 case 0: 222 idx = RK3288_PLL_CPLL; 223 break; 224 case 1: 225 idx = RK3288_PLL_GPLL; 226 break; 227 case 2: 228 return 24000000 / (div_con + 1); 229 default: 230 return 0; 231 } 232 return rk3288_get_frequency(sc, &idx) / (div_con + 1); 233 break; 234 case RK3288_CLK_UART0: 235 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(13)); 236 mux = (reg >> 8) & 0x3; 237 div_con = reg & 0x7f; 238 if (mux == 2) 239 return 24000000 / (div_con + 1); 240 break; 241 case RK3288_CLK_UART1: 242 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(14)); 243 mux = (reg >> 8) & 0x3; 244 div_con = reg & 0x7f; 245 if (mux == 2) 246 return 24000000 / (div_con + 1); 247 break; 248 case RK3288_CLK_UART2: 249 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(15)); 250 mux = (reg >> 8) & 0x3; 251 div_con = reg & 0x7f; 252 if (mux == 2) 253 return 24000000 / (div_con + 1); 254 break; 255 case RK3288_CLK_UART3: 256 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(16)); 257 mux = (reg >> 8) & 0x3; 258 div_con = reg & 0x7f; 259 if (mux == 2) 260 return 24000000 / (div_con + 1); 261 break; 262 case RK3288_CLK_UART4: 263 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(3)); 264 mux = (reg >> 8) & 0x3; 265 div_con = reg & 0x7f; 266 if (mux == 2) 267 return 24000000 / (div_con + 1); 268 break; 269 default: 270 break; 271 } 272 273 printf("%s: 0x%08x\n", __func__, idx); 274 return 0; 275 } 276 277 int 278 rk3288_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) 279 { 280 uint32_t idx = cells[0]; 281 282 printf("%s: 0x%08x\n", __func__, idx); 283 return -1; 284 } 285 286 void 287 rk3288_enable(void *cookie, uint32_t *cells, int on) 288 { 289 uint32_t idx = cells[0]; 290 291 switch (idx) { 292 case RK3288_CLK_SDMMC: 293 case RK3288_CLK_UART0: 294 case RK3288_CLK_UART1: 295 case RK3288_CLK_UART2: 296 case RK3288_CLK_UART3: 297 case RK3288_CLK_UART4: 298 case RK3288_CLK_MAC_RX: 299 case RK3288_CLK_MAC_TX: 300 case RK3288_CLK_SDMMC_DRV: 301 case RK3288_CLK_SDMMC_SAMPLE: 302 case RK3288_CLK_MAC: 303 case RK3288_ACLK_GMAC: 304 case RK3288_PCLK_GMAC: 305 case RK3288_HCLK_HOST0: 306 case RK3288_HCLK_SDMMC: 307 /* Enabled by default. */ 308 break; 309 default: 310 printf("%s: 0x%08x\n", __func__, idx); 311 break; 312 } 313 } 314 315 void 316 rk3288_reset(void *cookie, uint32_t *cells, int on) 317 { 318 uint32_t idx = cells[0]; 319 320 printf("%s: 0x%08x\n", __func__, idx); 321 } 322 323 /* 324 * Rockchip RK3399 325 */ 326 327 uint32_t 328 rk3399_get_pll(struct rkclock_softc *sc, bus_size_t base) 329 { 330 uint32_t fbdiv, postdiv1, postdiv2, refdiv; 331 uint32_t pll_work_mode; 332 uint32_t reg; 333 334 reg = HREAD4(sc, base + 0x000c); 335 pll_work_mode = (reg >> 8) & 0x3; 336 if (pll_work_mode == 0) 337 return 24000000; 338 if (pll_work_mode == 2) 339 return 32768; 340 341 reg = HREAD4(sc, base + 0x0000); 342 fbdiv = reg & 0xfff; 343 reg = HREAD4(sc, base + 0x0004); 344 postdiv2 = (reg >> 12) & 0x7; 345 postdiv1 = (reg >> 8) & 0x7; 346 refdiv = reg & 0x3f; 347 return 24000000ULL * fbdiv / refdiv / postdiv1 / postdiv2; 348 } 349 350 uint32_t 351 rk3399_get_armclk(struct rkclock_softc *sc, bus_size_t clksel) 352 { 353 uint32_t reg, mux, div_con; 354 uint32_t idx; 355 356 reg = HREAD4(sc, clksel); 357 mux = (reg >> 6) & 0x3; 358 div_con = reg & 0x1f; 359 switch (mux) { 360 case 0: 361 idx = RK3399_PLL_ALPLL; 362 break; 363 case 1: 364 idx = RK3399_PLL_ABPLL; 365 break; 366 case 2: 367 idx = RK3399_PLL_DPLL; 368 break; 369 case 3: 370 idx = RK3399_PLL_GPLL; 371 break; 372 } 373 374 return rk3399_get_frequency(sc, &idx) / (div_con + 1); 375 } 376 377 uint32_t 378 rk3399_get_frequency(void *cookie, uint32_t *cells) 379 { 380 struct rkclock_softc *sc = cookie; 381 uint32_t idx = cells[0]; 382 uint32_t reg, mux, div_con; 383 384 switch (idx) { 385 case RK3399_PLL_ALPLL: 386 return rk3399_get_pll(sc, RK3399_CRU_LPLL_CON(0)); 387 case RK3399_PLL_ABPLL: 388 return rk3399_get_pll(sc, RK3399_CRU_BPLL_CON(0)); 389 case RK3399_PLL_DPLL: 390 return rk3399_get_pll(sc, RK3399_CRU_DPLL_CON(0)); 391 case RK3399_PLL_CPLL: 392 return rk3399_get_pll(sc, RK3399_CRU_CPLL_CON(0)); 393 case RK3399_PLL_GPLL: 394 return rk3399_get_pll(sc, RK3399_CRU_GPLL_CON(0)); 395 case RK3399_PLL_NPLL: 396 return rk3399_get_pll(sc, RK3399_CRU_NPLL_CON(0)); 397 case RK3399_ARMCLKL: 398 return rk3399_get_armclk(sc, RK3399_CRU_CLKSEL_CON(0)); 399 break; 400 case RK3399_ARMCLKB: 401 return rk3399_get_armclk(sc, RK3399_CRU_CLKSEL_CON(2)); 402 break; 403 case RK3399_CLK_SDMMC: 404 reg = HREAD4(sc, RK3399_CRU_CLKSEL_CON(16)); 405 mux = (reg >> 8) & 0x7; 406 div_con = reg & 0x7f; 407 switch (mux) { 408 case 0: 409 idx = RK3399_PLL_CPLL; 410 break; 411 case 1: 412 idx = RK3399_PLL_GPLL; 413 break; 414 case 2: 415 idx = RK3399_PLL_NPLL; 416 break; 417 #ifdef notyet 418 case 3: 419 idx = RK3399_PLL_PPLL; 420 break; 421 case 4: 422 idx = RK3399_USB_480M; 423 break; 424 #endif 425 case 5: 426 return 24000000 / (div_con + 1); 427 default: 428 return 0; 429 } 430 return rk3399_get_frequency(sc, &idx) / (div_con + 1); 431 break; 432 case RK3399_CLK_UART0: 433 reg = HREAD4(sc, RK3399_CRU_CLKSEL_CON(33)); 434 mux = (reg >> 8) & 0x3; 435 div_con = reg & 0x7f; 436 if (mux == 2) 437 return 24000000 / (div_con + 1); 438 break; 439 case RK3399_CLK_UART1: 440 reg = HREAD4(sc, RK3399_CRU_CLKSEL_CON(34)); 441 mux = (reg >> 8) & 0x3; 442 div_con = reg & 0x7f; 443 if (mux == 2) 444 return 24000000 / (div_con + 1); 445 break; 446 case RK3399_CLK_UART2: 447 reg = HREAD4(sc, RK3399_CRU_CLKSEL_CON(35)); 448 mux = (reg >> 8) & 0x3; 449 div_con = reg & 0x7f; 450 if (mux == 2) 451 return 24000000 / (div_con + 1); 452 break; 453 case RK3399_CLK_UART3: 454 reg = HREAD4(sc, RK3399_CRU_CLKSEL_CON(36)); 455 mux = (reg >> 8) & 0x3; 456 div_con = reg & 0x7f; 457 if (mux == 2) 458 return 24000000 / (div_con + 1); 459 break; 460 case RK3399_HCLK_SDMMC: 461 reg = HREAD4(sc, RK3399_CRU_CLKSEL_CON(13)); 462 mux = (reg >> 15) & 0x1; 463 div_con = (reg >> 8) & 0x1f; 464 idx = mux ? RK3399_PLL_GPLL : RK3399_PLL_GPLL; 465 return rk3399_get_frequency(sc, &idx) / (div_con + 1); 466 default: 467 break; 468 } 469 470 printf("%s: 0x%08x\n", __func__, idx); 471 return 0; 472 } 473 474 int 475 rk3399_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) 476 { 477 uint32_t idx = cells[0]; 478 479 printf("%s: 0x%08x\n", __func__, idx); 480 return -1; 481 } 482 483 void 484 rk3399_enable(void *cookie, uint32_t *cells, int on) 485 { 486 uint32_t idx = cells[0]; 487 488 switch (idx) { 489 case RK3399_CLK_SDMMC: 490 case RK3399_CLK_EMMC: 491 case RK3399_CLK_UART0: 492 case RK3399_CLK_UART1: 493 case RK3399_CLK_UART2: 494 case RK3399_CLK_UART3: 495 case RK3399_CLK_MAC_RX: 496 case RK3399_CLK_MAC_TX: 497 case RK3399_CLK_MAC: 498 case RK3399_CLK_USB3OTG0_REF: 499 case RK3399_CLK_USB3OTG1_REF: 500 case RK3399_CLK_USB3OTG0_SUSPEND: 501 case RK3399_CLK_USB3OTG1_SUSPEND: 502 case RK3399_CLK_SDMMC_DRV: 503 case RK3399_CLK_SDMMC_SAMPLE: 504 case RK3399_ACLK_EMMC: 505 case RK3399_ACLK_GMAC: 506 case RK3399_ACLK_USB3OTG0: 507 case RK3399_ACLK_USB3OTG1: 508 case RK3399_ACLK_USB3_GRF: 509 case RK3399_PCLK_GMAC: 510 case RK3399_HCLK_HOST0: 511 case RK3399_HCLK_HOST0_ARB: 512 case RK3399_HCLK_HOST1: 513 case RK3399_HCLK_HOST1_ARB: 514 case RK3399_HCLK_SDMMC: 515 /* Enabled by default. */ 516 break; 517 default: 518 printf("%s: 0x%08x\n", __func__, idx); 519 break; 520 } 521 } 522 523 void 524 rk3399_reset(void *cookie, uint32_t *cells, int on) 525 { 526 struct rkclock_softc *sc = cookie; 527 uint32_t idx = cells[0]; 528 uint32_t mask = (1 << (idx % 16)); 529 530 HWRITE4(sc, RK3399_CRU_SOFTRST_CON(idx / 16), 531 mask << 16 | (on ? mask : 0)); 532 } 533 534 int 535 rk3399_cpuspeed(int *freq) 536 { 537 uint32_t idx = RK3399_ARMCLKL; 538 539 *freq = rk3399_get_frequency(rkclock_cpuspeed_sc, &idx) / 1000000; 540 return 0; 541 } 542 543 uint32_t 544 rk3399_pmu_get_frequency(void *cookie, uint32_t *cells) 545 { 546 uint32_t idx = cells[0]; 547 548 printf("%s: 0x%08x\n", __func__, idx); 549 return 0; 550 } 551 552 int 553 rk3399_pmu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) 554 { 555 uint32_t idx = cells[0]; 556 557 printf("%s: 0x%08x\n", __func__, idx); 558 return -1; 559 } 560 561 void 562 rk3399_pmu_enable(void *cookie, uint32_t *cells, int on) 563 { 564 uint32_t idx = cells[0]; 565 566 printf("%s: 0x%08x\n", __func__, idx); 567 } 568 569 void 570 rk3399_pmu_reset(void *cookie, uint32_t *cells, int on) 571 { 572 uint32_t idx = cells[0]; 573 574 printf("%s: 0x%08x\n", __func__, idx); 575 } 576