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