1/* 2 * Broadcom specific AMBA 3 * ChipCommon Power Management Unit driver 4 * 5 * Copyright 2009, Michael Buesch <m@bues.ch> 6 * Copyright 2007, 2011, Broadcom Corporation 7 * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de> 8 * 9 * Licensed under the GNU/GPL. See COPYING for details. 10 */ 11 12#include "bcma_private.h" 13#include <linux/export.h> 14#include <linux/bcma/bcma.h> 15 16u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset) 17{ 18 bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); 19 bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); 20 return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); 21} 22EXPORT_SYMBOL_GPL(bcma_chipco_pll_read); 23 24void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) 25{ 26 bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); 27 bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); 28 bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value); 29} 30EXPORT_SYMBOL_GPL(bcma_chipco_pll_write); 31 32void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, 33 u32 set) 34{ 35 bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); 36 bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); 37 bcma_cc_maskset32(cc, BCMA_CC_PLLCTL_DATA, mask, set); 38} 39EXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset); 40 41void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, 42 u32 offset, u32 mask, u32 set) 43{ 44 bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset); 45 bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR); 46 bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL_DATA, mask, set); 47} 48EXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset); 49 50void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, 51 u32 set) 52{ 53 bcma_cc_write32(cc, BCMA_CC_REGCTL_ADDR, offset); 54 bcma_cc_read32(cc, BCMA_CC_REGCTL_ADDR); 55 bcma_cc_maskset32(cc, BCMA_CC_REGCTL_DATA, mask, set); 56} 57EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); 58 59static u32 bcma_pmu_xtalfreq(struct bcma_drv_cc *cc) 60{ 61 u32 ilp_ctl, alp_hz; 62 63 if (!(bcma_cc_read32(cc, BCMA_CC_PMU_STAT) & 64 BCMA_CC_PMU_STAT_EXT_LPO_AVAIL)) 65 return 0; 66 67 bcma_cc_write32(cc, BCMA_CC_PMU_XTAL_FREQ, 68 BIT(BCMA_CC_PMU_XTAL_FREQ_MEASURE_SHIFT)); 69 usleep_range(1000, 2000); 70 71 ilp_ctl = bcma_cc_read32(cc, BCMA_CC_PMU_XTAL_FREQ); 72 ilp_ctl &= BCMA_CC_PMU_XTAL_FREQ_ILPCTL_MASK; 73 74 bcma_cc_write32(cc, BCMA_CC_PMU_XTAL_FREQ, 0); 75 76 alp_hz = ilp_ctl * 32768 / 4; 77 return (alp_hz + 50000) / 100000 * 100; 78} 79 80static void bcma_pmu2_pll_init0(struct bcma_drv_cc *cc, u32 xtalfreq) 81{ 82 struct bcma_bus *bus = cc->core->bus; 83 u32 freq_tgt_target = 0, freq_tgt_current; 84 u32 pll0, mask; 85 86 switch (bus->chipinfo.id) { 87 case BCMA_CHIP_ID_BCM43142: 88 /* pmu2_xtaltab0_adfll_485 */ 89 switch (xtalfreq) { 90 case 12000: 91 freq_tgt_target = 0x50D52; 92 break; 93 case 20000: 94 freq_tgt_target = 0x307FE; 95 break; 96 case 26000: 97 freq_tgt_target = 0x254EA; 98 break; 99 case 37400: 100 freq_tgt_target = 0x19EF8; 101 break; 102 case 52000: 103 freq_tgt_target = 0x12A75; 104 break; 105 } 106 break; 107 } 108 109 if (!freq_tgt_target) { 110 bcma_err(bus, "Unknown TGT frequency for xtalfreq %d\n", 111 xtalfreq); 112 return; 113 } 114 115 pll0 = bcma_chipco_pll_read(cc, BCMA_CC_PMU15_PLL_PLLCTL0); 116 freq_tgt_current = (pll0 & BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK) >> 117 BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT; 118 119 if (freq_tgt_current == freq_tgt_target) { 120 bcma_debug(bus, "Target TGT frequency already set\n"); 121 return; 122 } 123 124 /* Turn off PLL */ 125 switch (bus->chipinfo.id) { 126 case BCMA_CHIP_ID_BCM43142: 127 mask = (u32)~(BCMA_RES_4314_HT_AVAIL | 128 BCMA_RES_4314_MACPHY_CLK_AVAIL); 129 130 bcma_cc_mask32(cc, BCMA_CC_PMU_MINRES_MSK, mask); 131 bcma_cc_mask32(cc, BCMA_CC_PMU_MAXRES_MSK, mask); 132 bcma_wait_value(cc->core, BCMA_CLKCTLST, 133 BCMA_CLKCTLST_HAVEHT, 0, 20000); 134 break; 135 } 136 137 pll0 &= ~BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK; 138 pll0 |= freq_tgt_target << BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT; 139 bcma_chipco_pll_write(cc, BCMA_CC_PMU15_PLL_PLLCTL0, pll0); 140 141 /* Flush */ 142 if (cc->pmu.rev >= 2) 143 bcma_cc_set32(cc, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD); 144 145 /* TODO: Do we need to update OTP? */ 146} 147 148static void bcma_pmu_pll_init(struct bcma_drv_cc *cc) 149{ 150 struct bcma_bus *bus = cc->core->bus; 151 u32 xtalfreq = bcma_pmu_xtalfreq(cc); 152 153 switch (bus->chipinfo.id) { 154 case BCMA_CHIP_ID_BCM43142: 155 if (xtalfreq == 0) 156 xtalfreq = 20000; 157 bcma_pmu2_pll_init0(cc, xtalfreq); 158 break; 159 } 160} 161 162static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) 163{ 164 struct bcma_bus *bus = cc->core->bus; 165 u32 min_msk = 0, max_msk = 0; 166 167 switch (bus->chipinfo.id) { 168 case BCMA_CHIP_ID_BCM4313: 169 min_msk = 0x200D; 170 max_msk = 0xFFFF; 171 break; 172 case BCMA_CHIP_ID_BCM43142: 173 min_msk = BCMA_RES_4314_LPLDO_PU | 174 BCMA_RES_4314_PMU_SLEEP_DIS | 175 BCMA_RES_4314_PMU_BG_PU | 176 BCMA_RES_4314_CBUCK_LPOM_PU | 177 BCMA_RES_4314_CBUCK_PFM_PU | 178 BCMA_RES_4314_CLDO_PU | 179 BCMA_RES_4314_LPLDO2_LVM | 180 BCMA_RES_4314_WL_PMU_PU | 181 BCMA_RES_4314_LDO3P3_PU | 182 BCMA_RES_4314_OTP_PU | 183 BCMA_RES_4314_WL_PWRSW_PU | 184 BCMA_RES_4314_LQ_AVAIL | 185 BCMA_RES_4314_LOGIC_RET | 186 BCMA_RES_4314_MEM_SLEEP | 187 BCMA_RES_4314_MACPHY_RET | 188 BCMA_RES_4314_WL_CORE_READY; 189 max_msk = 0x3FFFFFFF; 190 break; 191 default: 192 bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n", 193 bus->chipinfo.id); 194 } 195 196 /* Set the resource masks. */ 197 if (min_msk) 198 bcma_cc_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk); 199 if (max_msk) 200 bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); 201 202 /* 203 * Add some delay; allow resources to come up and settle. 204 * Delay is required for SoC (early init). 205 */ 206 mdelay(2); 207} 208 209/* Disable to allow reading SPROM. Don't know the adventages of enabling it. */ 210void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable) 211{ 212 struct bcma_bus *bus = cc->core->bus; 213 u32 val; 214 215 val = bcma_cc_read32(cc, BCMA_CC_CHIPCTL); 216 if (enable) { 217 val |= BCMA_CHIPCTL_4331_EXTPA_EN; 218 if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11) 219 val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; 220 else if (bus->chipinfo.rev > 0) 221 val |= BCMA_CHIPCTL_4331_EXTPA_EN2; 222 } else { 223 val &= ~BCMA_CHIPCTL_4331_EXTPA_EN; 224 val &= ~BCMA_CHIPCTL_4331_EXTPA_EN2; 225 val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; 226 } 227 bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val); 228} 229 230static void bcma_pmu_workarounds(struct bcma_drv_cc *cc) 231{ 232 struct bcma_bus *bus = cc->core->bus; 233 234 switch (bus->chipinfo.id) { 235 case BCMA_CHIP_ID_BCM4313: 236 /* enable 12 mA drive strenth for 4313 and set chipControl 237 register bit 1 */ 238 bcma_chipco_chipctl_maskset(cc, 0, 239 ~BCMA_CCTRL_4313_12MA_LED_DRIVE, 240 BCMA_CCTRL_4313_12MA_LED_DRIVE); 241 break; 242 case BCMA_CHIP_ID_BCM4331: 243 case BCMA_CHIP_ID_BCM43431: 244 /* Ext PA lines must be enabled for tx on BCM4331 */ 245 bcma_chipco_bcm4331_ext_pa_lines_ctl(cc, true); 246 break; 247 case BCMA_CHIP_ID_BCM43224: 248 case BCMA_CHIP_ID_BCM43421: 249 /* enable 12 mA drive strenth for 43224 and set chipControl 250 register bit 15 */ 251 if (bus->chipinfo.rev == 0) { 252 bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL, 253 ~BCMA_CCTRL_43224_GPIO_TOGGLE, 254 BCMA_CCTRL_43224_GPIO_TOGGLE); 255 bcma_chipco_chipctl_maskset(cc, 0, 256 ~BCMA_CCTRL_43224A0_12MA_LED_DRIVE, 257 BCMA_CCTRL_43224A0_12MA_LED_DRIVE); 258 } else { 259 bcma_chipco_chipctl_maskset(cc, 0, 260 ~BCMA_CCTRL_43224B0_12MA_LED_DRIVE, 261 BCMA_CCTRL_43224B0_12MA_LED_DRIVE); 262 } 263 break; 264 default: 265 bcma_debug(bus, "Workarounds unknown or not needed for device 0x%04X\n", 266 bus->chipinfo.id); 267 } 268} 269 270void bcma_pmu_early_init(struct bcma_drv_cc *cc) 271{ 272 u32 pmucap; 273 274 pmucap = bcma_cc_read32(cc, BCMA_CC_PMU_CAP); 275 cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION); 276 277 bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n", 278 cc->pmu.rev, pmucap); 279} 280 281void bcma_pmu_init(struct bcma_drv_cc *cc) 282{ 283 if (cc->pmu.rev == 1) 284 bcma_cc_mask32(cc, BCMA_CC_PMU_CTL, 285 ~BCMA_CC_PMU_CTL_NOILPONW); 286 else 287 bcma_cc_set32(cc, BCMA_CC_PMU_CTL, 288 BCMA_CC_PMU_CTL_NOILPONW); 289 290 bcma_pmu_pll_init(cc); 291 bcma_pmu_resources_init(cc); 292 bcma_pmu_workarounds(cc); 293} 294 295u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc) 296{ 297 struct bcma_bus *bus = cc->core->bus; 298 299 switch (bus->chipinfo.id) { 300 case BCMA_CHIP_ID_BCM4313: 301 case BCMA_CHIP_ID_BCM43224: 302 case BCMA_CHIP_ID_BCM43225: 303 case BCMA_CHIP_ID_BCM43227: 304 case BCMA_CHIP_ID_BCM43228: 305 case BCMA_CHIP_ID_BCM4331: 306 case BCMA_CHIP_ID_BCM43421: 307 case BCMA_CHIP_ID_BCM43428: 308 case BCMA_CHIP_ID_BCM43431: 309 case BCMA_CHIP_ID_BCM4716: 310 case BCMA_CHIP_ID_BCM47162: 311 case BCMA_CHIP_ID_BCM4748: 312 case BCMA_CHIP_ID_BCM4749: 313 case BCMA_CHIP_ID_BCM5357: 314 case BCMA_CHIP_ID_BCM53572: 315 case BCMA_CHIP_ID_BCM6362: 316 /* always 20Mhz */ 317 return 20000 * 1000; 318 case BCMA_CHIP_ID_BCM4706: 319 case BCMA_CHIP_ID_BCM5356: 320 /* always 25Mhz */ 321 return 25000 * 1000; 322 case BCMA_CHIP_ID_BCM43460: 323 case BCMA_CHIP_ID_BCM4352: 324 case BCMA_CHIP_ID_BCM4360: 325 if (cc->status & BCMA_CC_CHIPST_4360_XTAL_40MZ) 326 return 40000 * 1000; 327 else 328 return 20000 * 1000; 329 default: 330 bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n", 331 bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK); 332 } 333 return BCMA_CC_PMU_ALP_CLOCK; 334} 335 336/* Find the output of the "m" pll divider given pll controls that start with 337 * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc. 338 */ 339static u32 bcma_pmu_pll_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m) 340{ 341 u32 tmp, div, ndiv, p1, p2, fc; 342 struct bcma_bus *bus = cc->core->bus; 343 344 BUG_ON((pll0 & 3) || (pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0)); 345 346 BUG_ON(!m || m > 4); 347 348 if (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 || 349 bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) { 350 /* Detect failure in clock setting */ 351 tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); 352 if (tmp & 0x40000) 353 return 133 * 1000000; 354 } 355 356 tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_P1P2_OFF); 357 p1 = (tmp & BCMA_CC_PPL_P1_MASK) >> BCMA_CC_PPL_P1_SHIFT; 358 p2 = (tmp & BCMA_CC_PPL_P2_MASK) >> BCMA_CC_PPL_P2_SHIFT; 359 360 tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_M14_OFF); 361 div = (tmp >> ((m - 1) * BCMA_CC_PPL_MDIV_WIDTH)) & 362 BCMA_CC_PPL_MDIV_MASK; 363 364 tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_NM5_OFF); 365 ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT; 366 367 /* Do calculation in Mhz */ 368 fc = bcma_pmu_get_alp_clock(cc) / 1000000; 369 fc = (p1 * ndiv * fc) / p2; 370 371 /* Return clock in Hertz */ 372 return (fc / div) * 1000000; 373} 374 375static u32 bcma_pmu_pll_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m) 376{ 377 u32 tmp, ndiv, p1div, p2div; 378 u32 clock; 379 380 BUG_ON(!m || m > 4); 381 382 /* Get N, P1 and P2 dividers to determine CPU clock */ 383 tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PMU6_4706_PROCPLL_OFF); 384 ndiv = (tmp & BCMA_CC_PMU6_4706_PROC_NDIV_INT_MASK) 385 >> BCMA_CC_PMU6_4706_PROC_NDIV_INT_SHIFT; 386 p1div = (tmp & BCMA_CC_PMU6_4706_PROC_P1DIV_MASK) 387 >> BCMA_CC_PMU6_4706_PROC_P1DIV_SHIFT; 388 p2div = (tmp & BCMA_CC_PMU6_4706_PROC_P2DIV_MASK) 389 >> BCMA_CC_PMU6_4706_PROC_P2DIV_SHIFT; 390 391 tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); 392 if (tmp & BCMA_CC_CHIPST_4706_PKG_OPTION) 393 /* Low cost bonding: Fixed reference clock 25MHz and m = 4 */ 394 clock = (25000000 / 4) * ndiv * p2div / p1div; 395 else 396 /* Fixed reference clock 25MHz and m = 2 */ 397 clock = (25000000 / 2) * ndiv * p2div / p1div; 398 399 if (m == BCMA_CC_PMU5_MAINPLL_SSB) 400 clock = clock / 4; 401 402 return clock; 403} 404 405/* query bus clock frequency for PMU-enabled chipcommon */ 406u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc) 407{ 408 struct bcma_bus *bus = cc->core->bus; 409 410 switch (bus->chipinfo.id) { 411 case BCMA_CHIP_ID_BCM4716: 412 case BCMA_CHIP_ID_BCM4748: 413 case BCMA_CHIP_ID_BCM47162: 414 return bcma_pmu_pll_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0, 415 BCMA_CC_PMU5_MAINPLL_SSB); 416 case BCMA_CHIP_ID_BCM5356: 417 return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0, 418 BCMA_CC_PMU5_MAINPLL_SSB); 419 case BCMA_CHIP_ID_BCM5357: 420 case BCMA_CHIP_ID_BCM4749: 421 return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0, 422 BCMA_CC_PMU5_MAINPLL_SSB); 423 case BCMA_CHIP_ID_BCM4706: 424 return bcma_pmu_pll_clock_bcm4706(cc, 425 BCMA_CC_PMU4706_MAINPLL_PLL0, 426 BCMA_CC_PMU5_MAINPLL_SSB); 427 case BCMA_CHIP_ID_BCM53572: 428 return 75000000; 429 default: 430 bcma_warn(bus, "No bus clock specified for %04X device, pmu rev. %d, using default %d Hz\n", 431 bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK); 432 } 433 return BCMA_CC_PMU_HT_CLOCK; 434} 435EXPORT_SYMBOL_GPL(bcma_pmu_get_bus_clock); 436 437/* query cpu clock frequency for PMU-enabled chipcommon */ 438u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc) 439{ 440 struct bcma_bus *bus = cc->core->bus; 441 442 if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) 443 return 300000000; 444 445 /* New PMUs can have different clock for bus and CPU */ 446 if (cc->pmu.rev >= 5) { 447 u32 pll; 448 switch (bus->chipinfo.id) { 449 case BCMA_CHIP_ID_BCM4706: 450 return bcma_pmu_pll_clock_bcm4706(cc, 451 BCMA_CC_PMU4706_MAINPLL_PLL0, 452 BCMA_CC_PMU5_MAINPLL_CPU); 453 case BCMA_CHIP_ID_BCM5356: 454 pll = BCMA_CC_PMU5356_MAINPLL_PLL0; 455 break; 456 case BCMA_CHIP_ID_BCM5357: 457 case BCMA_CHIP_ID_BCM4749: 458 pll = BCMA_CC_PMU5357_MAINPLL_PLL0; 459 break; 460 default: 461 pll = BCMA_CC_PMU4716_MAINPLL_PLL0; 462 break; 463 } 464 465 return bcma_pmu_pll_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU); 466 } 467 468 /* On old PMUs CPU has the same clock as the bus */ 469 return bcma_pmu_get_bus_clock(cc); 470} 471 472static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset, 473 u32 value) 474{ 475 bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); 476 bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value); 477} 478 479void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) 480{ 481 u32 tmp = 0; 482 u8 phypll_offset = 0; 483 u8 bcm5357_bcm43236_p1div[] = {0x1, 0x5, 0x5}; 484 u8 bcm5357_bcm43236_ndiv[] = {0x30, 0xf6, 0xfc}; 485 struct bcma_bus *bus = cc->core->bus; 486 487 switch (bus->chipinfo.id) { 488 case BCMA_CHIP_ID_BCM5357: 489 case BCMA_CHIP_ID_BCM4749: 490 case BCMA_CHIP_ID_BCM53572: 491 /* 5357[ab]0, 43236[ab]0, and 6362b0 */ 492 493 /* BCM5357 needs to touch PLL1_PLLCTL[02], 494 so offset PLL0_PLLCTL[02] by 6 */ 495 phypll_offset = (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 || 496 bus->chipinfo.id == BCMA_CHIP_ID_BCM4749 || 497 bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) ? 6 : 0; 498 499 /* RMW only the P1 divider */ 500 bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, 501 BCMA_CC_PMU_PLL_CTL0 + phypll_offset); 502 tmp = bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); 503 tmp &= (~(BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK)); 504 tmp |= (bcm5357_bcm43236_p1div[spuravoid] << BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT); 505 bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); 506 507 /* RMW only the int feedback divider */ 508 bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, 509 BCMA_CC_PMU_PLL_CTL2 + phypll_offset); 510 tmp = bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); 511 tmp &= ~(BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK); 512 tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT; 513 bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); 514 515 tmp = BCMA_CC_PMU_CTL_PLL_UPD; 516 break; 517 518 case BCMA_CHIP_ID_BCM4331: 519 case BCMA_CHIP_ID_BCM43431: 520 if (spuravoid == 2) { 521 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 522 0x11500014); 523 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 524 0x0FC00a08); 525 } else if (spuravoid == 1) { 526 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 527 0x11500014); 528 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 529 0x0F600a08); 530 } else { 531 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 532 0x11100014); 533 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 534 0x03000a08); 535 } 536 tmp = BCMA_CC_PMU_CTL_PLL_UPD; 537 break; 538 539 case BCMA_CHIP_ID_BCM43224: 540 case BCMA_CHIP_ID_BCM43225: 541 case BCMA_CHIP_ID_BCM43421: 542 if (spuravoid == 1) { 543 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 544 0x11500010); 545 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, 546 0x000C0C06); 547 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 548 0x0F600a08); 549 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, 550 0x00000000); 551 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, 552 0x2001E920); 553 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 554 0x88888815); 555 } else { 556 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 557 0x11100010); 558 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, 559 0x000c0c06); 560 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 561 0x03000a08); 562 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, 563 0x00000000); 564 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, 565 0x200005c0); 566 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 567 0x88888815); 568 } 569 tmp = BCMA_CC_PMU_CTL_PLL_UPD; 570 break; 571 572 case BCMA_CHIP_ID_BCM4716: 573 case BCMA_CHIP_ID_BCM4748: 574 case BCMA_CHIP_ID_BCM47162: 575 if (spuravoid == 1) { 576 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 577 0x11500060); 578 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, 579 0x080C0C06); 580 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 581 0x0F600000); 582 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, 583 0x00000000); 584 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, 585 0x2001E924); 586 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 587 0x88888815); 588 } else { 589 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 590 0x11100060); 591 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, 592 0x080c0c06); 593 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 594 0x03000000); 595 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, 596 0x00000000); 597 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, 598 0x200005c0); 599 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 600 0x88888815); 601 } 602 603 tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW; 604 break; 605 606 case BCMA_CHIP_ID_BCM43131: 607 case BCMA_CHIP_ID_BCM43217: 608 case BCMA_CHIP_ID_BCM43227: 609 case BCMA_CHIP_ID_BCM43228: 610 case BCMA_CHIP_ID_BCM43428: 611 /* LCNXN */ 612 /* PLL Settings for spur avoidance on/off mode, 613 no on2 support for 43228A0 */ 614 if (spuravoid == 1) { 615 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 616 0x01100014); 617 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, 618 0x040C0C06); 619 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 620 0x03140A08); 621 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, 622 0x00333333); 623 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, 624 0x202C2820); 625 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 626 0x88888815); 627 } else { 628 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0, 629 0x11100014); 630 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1, 631 0x040c0c06); 632 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2, 633 0x03000a08); 634 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3, 635 0x00000000); 636 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4, 637 0x200005c0); 638 bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5, 639 0x88888815); 640 } 641 tmp = BCMA_CC_PMU_CTL_PLL_UPD; 642 break; 643 default: 644 bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n", 645 bus->chipinfo.id); 646 break; 647 } 648 649 tmp |= bcma_cc_read32(cc, BCMA_CC_PMU_CTL); 650 bcma_cc_write32(cc, BCMA_CC_PMU_CTL, tmp); 651} 652EXPORT_SYMBOL_GPL(bcma_pmu_spuravoid_pllupdate); 653