1 /*- 2 * Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org> 3 * Copyright (c) 2010, Broadcom Corporation. 4 * All rights reserved. 5 * 6 * This file is derived from the siutils.c source distributed with the 7 * Asus RT-N16 firmware source code release. 8 * 9 * Permission to use, copy, modify, and/or distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 16 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 18 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 19 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 * 21 * $Id: siutils.c,v 1.821.2.48 2011-02-11 20:59:28 Exp $ 22 */ 23 24 #include <sys/cdefs.h> 25 __FBSDID("$FreeBSD$"); 26 27 #include <sys/param.h> 28 #include <sys/kernel.h> 29 #include <sys/bus.h> 30 #include <sys/limits.h> 31 #include <sys/malloc.h> 32 #include <sys/module.h> 33 #include <sys/systm.h> 34 35 #include <dev/bhnd/bhnd.h> 36 #include <dev/bhnd/bhndb/bhndb_pcireg.h> 37 38 #include <dev/bhnd/cores/chipc/chipc.h> 39 #include <dev/bhnd/cores/chipc/chipcreg.h> 40 41 #include <dev/bhnd/cores/pmu/bhnd_pmuvar.h> 42 #include <dev/bhnd/cores/pmu/bhnd_pmureg.h> 43 44 #include "bhnd_chipc_if.h" 45 46 #include "bhnd_pwrctl_private.h" 47 48 static uint32_t bhnd_pwrctl_factor6(uint32_t x); 49 50 /** 51 * Return the factor value corresponding to a given N3M clock control magic 52 * field value (CHIPC_F6_*). 53 */ 54 static uint32_t 55 bhnd_pwrctl_factor6(uint32_t x) 56 { 57 switch (x) { 58 case CHIPC_F6_2: 59 return (2); 60 case CHIPC_F6_3: 61 return (3); 62 case CHIPC_F6_4: 63 return (4); 64 case CHIPC_F6_5: 65 return (5); 66 case CHIPC_F6_6: 67 return (6); 68 case CHIPC_F6_7: 69 return (7); 70 default: 71 return (0); 72 } 73 } 74 75 /** 76 * Return the backplane clock's chipc 'M' register offset for a given PLL type, 77 * or 0 if a fixed clock speed should be used. 78 * 79 * @param cid Chip identification. 80 * @param pll_type PLL type (CHIPC_PLL_TYPE*) 81 * @param[out] fixed_hz If 0 is returned, will be set to the fixed clock 82 * speed for this device. 83 */ 84 bus_size_t 85 bhnd_pwrctl_si_clkreg_m(const struct bhnd_chipid *cid, 86 uint8_t pll_type, uint32_t *fixed_hz) 87 { 88 switch (pll_type) { 89 case CHIPC_PLL_TYPE6: 90 return (CHIPC_CLKC_M3); 91 case CHIPC_PLL_TYPE3: 92 return (CHIPC_CLKC_M2); 93 default: 94 return (CHIPC_CLKC_SB); 95 } 96 } 97 98 /** 99 * Calculate the backplane clock speed (in Hz) for a given a set of clock 100 * control values. 101 * 102 * @param cid Chip identification. 103 * @param pll_type PLL type (CHIPC_PLL_TYPE*) 104 * @param n clock control N register value. 105 * @param m clock control M register value. 106 */ 107 uint32_t 108 bhnd_pwrctl_si_clock_rate(const struct bhnd_chipid *cid, 109 uint32_t pll_type, uint32_t n, uint32_t m) 110 { 111 uint32_t rate; 112 113 KASSERT(bhnd_pwrctl_si_clkreg_m(cid, pll_type, NULL) != 0, 114 ("can't compute clock rate on fixed clock")); 115 116 rate = bhnd_pwrctl_clock_rate(pll_type, n, m); 117 if (pll_type == CHIPC_PLL_TYPE3) 118 rate /= 2; 119 120 return (rate); 121 } 122 123 /** 124 * Return the CPU clock's chipc 'M' register offset for a given PLL type, 125 * or 0 if a fixed clock speed should be used. 126 * 127 * @param cid Chip identification. 128 * @param pll_type PLL type (CHIPC_PLL_TYPE*) 129 * @param[out] fixed_hz If 0 is returned, will be set to the fixed clock 130 * speed for this device. 131 */ 132 bus_size_t 133 bhnd_pwrctl_cpu_clkreg_m(const struct bhnd_chipid *cid, 134 uint8_t pll_type, uint32_t *fixed_hz) 135 { 136 switch (pll_type) { 137 case CHIPC_PLL_TYPE2: 138 case CHIPC_PLL_TYPE4: 139 case CHIPC_PLL_TYPE6: 140 case CHIPC_PLL_TYPE7: 141 return (CHIPC_CLKC_M3); 142 143 case CHIPC_PLL_TYPE5: 144 /* fixed 200MHz */ 145 if (fixed_hz != NULL) 146 *fixed_hz = 200 * 1000 * 1000; 147 return (0); 148 149 case CHIPC_PLL_TYPE3: 150 if (cid->chip_id == BHND_CHIPID_BCM5365) { 151 /* fixed 200MHz */ 152 if (fixed_hz != NULL) 153 *fixed_hz = 200 * 1000 * 1000; 154 return (0); 155 } 156 157 return (CHIPC_CLKC_M2); 158 159 default: 160 return (CHIPC_CLKC_SB); 161 } 162 } 163 164 /** 165 * Calculate the CPU clock speed (in Hz) for a given a set of clock control 166 * values. 167 * 168 * @param cid Chip identification. 169 * @param pll_type PLL type (CHIPC_PLL_TYPE*) 170 * @param n clock control N register value. 171 * @param m clock control M register value. 172 */ 173 uint32_t 174 bhnd_pwrctl_cpu_clock_rate(const struct bhnd_chipid *cid, 175 uint32_t pll_type, uint32_t n, uint32_t m) 176 { 177 KASSERT(bhnd_pwrctl_cpu_clkreg_m(cid, pll_type, NULL) != 0, 178 ("can't compute clock rate on fixed clock")); 179 180 return (bhnd_pwrctl_clock_rate(pll_type, n, m)); 181 } 182 183 /** 184 * Calculate the clock speed (in Hz) for a given a set of clockcontrol 185 * values. 186 * 187 * @param pll_type PLL type (CHIPC_PLL_TYPE*) 188 * @param n clock control N register value. 189 * @param m clock control M register value. 190 */ 191 uint32_t 192 bhnd_pwrctl_clock_rate(uint32_t pll_type, uint32_t n, uint32_t m) 193 { 194 uint32_t clk_base; 195 uint32_t n1, n2, clock, m1, m2, m3, mc; 196 197 n1 = CHIPC_GET_BITS(n, CHIPC_CN_N1); 198 n2 = CHIPC_GET_BITS(n, CHIPC_CN_N2); 199 200 switch (pll_type) { 201 case CHIPC_PLL_TYPE1: 202 case CHIPC_PLL_TYPE3: 203 case CHIPC_PLL_TYPE4: 204 case CHIPC_PLL_TYPE7: 205 n1 = bhnd_pwrctl_factor6(n1); 206 n2 += CHIPC_F5_BIAS; 207 break; 208 209 case CHIPC_PLL_TYPE2: 210 n1 += CHIPC_T2_BIAS; 211 n2 += CHIPC_T2_BIAS; 212 KASSERT(n1 >= 2 && n1 <= 7, ("invalid n1 value")); 213 KASSERT(n2 >= 5 && n2 <= 23, ("invalid n2 value")); 214 break; 215 216 case CHIPC_PLL_TYPE5: 217 return (100000000); 218 219 case CHIPC_PLL_TYPE6: 220 if (m & CHIPC_T6_MMASK) 221 return (CHIPC_T6_M1); 222 else 223 return (CHIPC_T6_M0); 224 225 default: 226 printf("unsupported PLL type %u\n", pll_type); 227 return (0); 228 } 229 230 /* PLL types 3 and 7 use BASE2 (25Mhz) */ 231 if (pll_type == CHIPC_PLL_TYPE3 || pll_type == CHIPC_PLL_TYPE7) { 232 clk_base = CHIPC_CLOCK_BASE2; 233 } else { 234 clk_base = CHIPC_CLOCK_BASE1; 235 } 236 237 clock = clk_base * n1 * n2; 238 239 if (clock == 0) 240 return (0); 241 242 m1 = CHIPC_GET_BITS(m, CHIPC_M1); 243 m2 = CHIPC_GET_BITS(m, CHIPC_M2); 244 m3 = CHIPC_GET_BITS(m, CHIPC_M3); 245 mc = CHIPC_GET_BITS(m, CHIPC_MC); 246 247 switch (pll_type) { 248 case CHIPC_PLL_TYPE1: 249 case CHIPC_PLL_TYPE3: 250 case CHIPC_PLL_TYPE4: 251 case CHIPC_PLL_TYPE7: 252 m1 = bhnd_pwrctl_factor6(m1); 253 if (pll_type == CHIPC_PLL_TYPE1 || pll_type == CHIPC_PLL_TYPE3) 254 m2 += CHIPC_F5_BIAS; 255 else 256 m2 = bhnd_pwrctl_factor6(m2); 257 258 m3 = bhnd_pwrctl_factor6(m3); 259 260 switch (mc) { 261 case CHIPC_MC_BYPASS: 262 return (clock); 263 case CHIPC_MC_M1: 264 return (clock / m1); 265 case CHIPC_MC_M1M2: 266 return (clock / (m1 * m2)); 267 case CHIPC_MC_M1M2M3: 268 return (clock / (m1 * m2 * m3)); 269 case CHIPC_MC_M1M3: 270 return (clock / (m1 * m3)); 271 default: 272 printf("unsupported pwrctl mc %#x\n", mc); 273 return (0); 274 } 275 case CHIPC_PLL_TYPE2: 276 m1 += CHIPC_T2_BIAS; 277 m2 += CHIPC_T2M2_BIAS; 278 m3 += CHIPC_T2_BIAS; 279 KASSERT(m1 >= 2 && m1 <= 7, ("invalid m1 value")); 280 KASSERT(m2 >= 3 && m2 <= 10, ("invalid m2 value")); 281 KASSERT(m3 >= 2 && m3 <= 7, ("invalid m3 value")); 282 283 if ((mc & CHIPC_T2MC_M1BYP) == 0) 284 clock /= m1; 285 if ((mc & CHIPC_T2MC_M2BYP) == 0) 286 clock /= m2; 287 if ((mc & CHIPC_T2MC_M3BYP) == 0) 288 clock /= m3; 289 290 return (clock); 291 default: 292 panic("unhandled PLL type %u\n", pll_type); 293 } 294 } 295 296 /** 297 * Return the backplane clock speed in Hz. 298 * 299 * @param sc driver instance state. 300 */ 301 uint32_t 302 bhnd_pwrctl_getclk_speed(struct bhnd_pwrctl_softc *sc) 303 { 304 const struct bhnd_chipid *cid; 305 struct chipc_caps *ccaps; 306 bus_size_t creg; 307 uint32_t n, m; 308 uint32_t rate; 309 310 PWRCTL_LOCK_ASSERT(sc, MA_OWNED); 311 312 cid = bhnd_get_chipid(sc->chipc_dev); 313 ccaps = BHND_CHIPC_GET_CAPS(sc->chipc_dev); 314 315 n = bhnd_bus_read_4(sc->res, CHIPC_CLKC_N); 316 317 /* Get M register offset */ 318 creg = bhnd_pwrctl_si_clkreg_m(cid, ccaps->pll_type, &rate); 319 if (creg == 0) /* fixed rate */ 320 return (rate); 321 322 /* calculate rate */ 323 m = bhnd_bus_read_4(sc->res, creg); 324 return (bhnd_pwrctl_si_clock_rate(cid, ccaps->pll_type, n, m)); 325 } 326 327 /* return the slow clock source */ 328 static bhnd_clksrc 329 bhnd_pwrctl_slowclk_src(struct bhnd_pwrctl_softc *sc) 330 { 331 uint32_t clkreg; 332 uint32_t clksrc; 333 334 /* Fetch clock source */ 335 if (PWRCTL_QUIRK(sc, PCICLK_CTL)) { 336 return (bhnd_pwrctl_hostb_get_clksrc(sc->chipc_dev, 337 BHND_CLOCK_ILP)); 338 } else if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) { 339 clkreg = bhnd_bus_read_4(sc->res, CHIPC_PLL_SLOWCLK_CTL); 340 clksrc = clkreg & CHIPC_SCC_SS_MASK; 341 } else { 342 /* Instaclock */ 343 clksrc = CHIPC_SCC_SS_XTAL; 344 } 345 346 /* Map to bhnd_clksrc */ 347 switch (clksrc) { 348 case CHIPC_SCC_SS_PCI: 349 return (BHND_CLKSRC_PCI); 350 case CHIPC_SCC_SS_LPO: 351 return (BHND_CLKSRC_LPO); 352 case CHIPC_SCC_SS_XTAL: 353 return (BHND_CLKSRC_XTAL); 354 default: 355 return (BHND_CLKSRC_UNKNOWN); 356 } 357 } 358 359 /* return the ILP (slowclock) min or max frequency */ 360 static uint32_t 361 bhnd_pwrctl_slowclk_freq(struct bhnd_pwrctl_softc *sc, bool max_freq) 362 { 363 bhnd_clksrc slowclk; 364 uint32_t div; 365 uint32_t hz; 366 367 slowclk = bhnd_pwrctl_slowclk_src(sc); 368 369 /* Determine clock divisor */ 370 if (PWRCTL_QUIRK(sc, PCICLK_CTL)) { 371 if (slowclk == BHND_CLKSRC_PCI) 372 div = 64; 373 else 374 div = 32; 375 } else if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) { 376 div = bhnd_bus_read_4(sc->res, CHIPC_PLL_SLOWCLK_CTL); 377 div = CHIPC_GET_BITS(div, CHIPC_SCC_CD); 378 div = 4 * (div + 1); 379 } else if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) { 380 if (max_freq) { 381 div = 1; 382 } else { 383 div = bhnd_bus_read_4(sc->res, CHIPC_SYS_CLK_CTL); 384 div = CHIPC_GET_BITS(div, CHIPC_SYCC_CD); 385 div = 4 * (div + 1); 386 } 387 } else { 388 device_printf(sc->dev, "unknown device type\n"); 389 return (0); 390 } 391 392 /* Determine clock frequency */ 393 switch (slowclk) { 394 case BHND_CLKSRC_LPO: 395 hz = max_freq ? CHIPC_LPOMAXFREQ : CHIPC_LPOMINFREQ; 396 break; 397 case BHND_CLKSRC_XTAL: 398 hz = max_freq ? CHIPC_XTALMAXFREQ : CHIPC_XTALMINFREQ; 399 break; 400 case BHND_CLKSRC_PCI: 401 hz = max_freq ? CHIPC_PCIMAXFREQ : CHIPC_PCIMINFREQ; 402 break; 403 default: 404 device_printf(sc->dev, "unknown slowclk source %#x\n", slowclk); 405 return (0); 406 } 407 408 return (hz / div); 409 } 410 411 /** 412 * Initialize power control registers. 413 */ 414 int 415 bhnd_pwrctl_init(struct bhnd_pwrctl_softc *sc) 416 { 417 uint32_t clkctl; 418 uint32_t pll_delay, slowclk, slowmaxfreq; 419 uint32_t pll_on_delay, fref_sel_delay; 420 int error; 421 422 pll_delay = CHIPC_PLL_DELAY; 423 424 /* set all Instaclk chip ILP to 1 MHz */ 425 if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) { 426 clkctl = (CHIPC_ILP_DIV_1MHZ << CHIPC_SYCC_CD_SHIFT); 427 clkctl &= CHIPC_SYCC_CD_MASK; 428 bhnd_bus_write_4(sc->res, CHIPC_SYS_CLK_CTL, clkctl); 429 } 430 431 /* 432 * Initialize PLL/FREF delays. 433 * 434 * If the slow clock is not sourced by the xtal, include the 435 * delay required to bring it up. 436 */ 437 slowclk = bhnd_pwrctl_slowclk_src(sc); 438 if (slowclk != CHIPC_SCC_SS_XTAL) 439 pll_delay += CHIPC_XTAL_ON_DELAY; 440 441 /* Starting with 4318 it is ILP that is used for the delays */ 442 if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) 443 slowmaxfreq = bhnd_pwrctl_slowclk_freq(sc, false); 444 else 445 slowmaxfreq = bhnd_pwrctl_slowclk_freq(sc, true); 446 447 pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; 448 fref_sel_delay = ((slowmaxfreq * CHIPC_FREF_DELAY) + 999999) / 1000000; 449 450 bhnd_bus_write_4(sc->res, CHIPC_PLL_ON_DELAY, pll_on_delay); 451 bhnd_bus_write_4(sc->res, CHIPC_PLL_FREFSEL_DELAY, fref_sel_delay); 452 453 /* If required, force HT */ 454 if (PWRCTL_QUIRK(sc, FORCE_HT)) { 455 if ((error = bhnd_pwrctl_setclk(sc, BHND_CLOCK_HT))) 456 return (error); 457 } 458 459 return (0); 460 } 461 462 /* return the value suitable for writing to the dot11 core 463 * FAST_PWRUP_DELAY register */ 464 u_int 465 bhnd_pwrctl_fast_pwrup_delay(struct bhnd_pwrctl_softc *sc) 466 { 467 u_int pll_on_delay, slowminfreq; 468 u_int fpdelay; 469 470 fpdelay = 0; 471 472 slowminfreq = bhnd_pwrctl_slowclk_freq(sc, false); 473 474 pll_on_delay = bhnd_bus_read_4(sc->res, CHIPC_PLL_ON_DELAY) + 2; 475 pll_on_delay *= 1000000; 476 pll_on_delay += (slowminfreq - 1); 477 fpdelay = pll_on_delay / slowminfreq; 478 479 return (fpdelay); 480 } 481 482 /** 483 * Distribute @p clock on backplane. 484 * 485 * @param sc Driver instance state. 486 * @param clock Clock to enable. 487 * 488 * @retval 0 success 489 * @retval ENODEV If @p clock is unsupported, or if the device does not 490 * support dynamic clock control. 491 */ 492 int 493 bhnd_pwrctl_setclk(struct bhnd_pwrctl_softc *sc, bhnd_clock clock) 494 { 495 uint32_t scc; 496 497 PWRCTL_LOCK_ASSERT(sc, MA_OWNED); 498 499 /* Is dynamic clock control supported? */ 500 if (PWRCTL_QUIRK(sc, FIXED_CLK)) 501 return (ENODEV); 502 503 /* Chips with ccrev 10 are EOL and they don't have SYCC_HR used below */ 504 if (bhnd_get_hwrev(sc->chipc_dev) == 10) 505 return (ENODEV); 506 507 if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) 508 scc = bhnd_bus_read_4(sc->res, CHIPC_PLL_SLOWCLK_CTL); 509 else 510 scc = bhnd_bus_read_4(sc->res, CHIPC_SYS_CLK_CTL); 511 512 switch (clock) { 513 case BHND_CLOCK_HT: 514 /* fast (pll) clock */ 515 if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) { 516 scc &= ~(CHIPC_SCC_XC | CHIPC_SCC_FS | CHIPC_SCC_IP); 517 scc |= CHIPC_SCC_IP; 518 519 /* force xtal back on before clearing SCC_DYN_XTAL.. */ 520 bhnd_pwrctl_hostb_ungate_clock(sc->chipc_dev, 521 BHND_CLOCK_HT); 522 } else if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) { 523 scc |= CHIPC_SYCC_HR; 524 } else { 525 return (ENODEV); 526 } 527 528 if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) 529 bhnd_bus_write_4(sc->res, CHIPC_PLL_SLOWCLK_CTL, scc); 530 else 531 bhnd_bus_write_4(sc->res, CHIPC_SYS_CLK_CTL, scc); 532 DELAY(CHIPC_PLL_DELAY); 533 534 break; 535 536 case BHND_CLOCK_DYN: 537 /* enable dynamic clock control */ 538 if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) { 539 scc &= ~(CHIPC_SCC_FS | CHIPC_SCC_IP | CHIPC_SCC_XC); 540 if ((scc & CHIPC_SCC_SS_MASK) != CHIPC_SCC_SS_XTAL) 541 scc |= CHIPC_SCC_XC; 542 543 bhnd_bus_write_4(sc->res, CHIPC_PLL_SLOWCLK_CTL, scc); 544 545 /* for dynamic control, we have to release our xtal_pu 546 * "force on" */ 547 if (scc & CHIPC_SCC_XC) { 548 bhnd_pwrctl_hostb_gate_clock(sc->chipc_dev, 549 BHND_CLOCK_HT); 550 } 551 } else if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) { 552 /* Instaclock */ 553 scc &= ~CHIPC_SYCC_HR; 554 bhnd_bus_write_4(sc->res, CHIPC_SYS_CLK_CTL, scc); 555 } else { 556 return (ENODEV); 557 } 558 559 break; 560 561 default: 562 return (ENODEV); 563 } 564 565 return (0); 566 } 567