diff options
| -rw-r--r-- | drivers/bcma/sprom.c | 126 | ||||
| -rw-r--r-- | include/linux/bcma/bcma_driver_chipcommon.h | 10 |
2 files changed, 115 insertions, 21 deletions
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index fba8066857d2..cdcf75c0954f 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c | |||
| @@ -300,37 +300,128 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) | |||
| 300 | SSB_SROM8_FEM_ANTSWLUT_SHIFT); | 300 | SSB_SROM8_FEM_ANTSWLUT_SHIFT); |
| 301 | } | 301 | } |
| 302 | 302 | ||
| 303 | static bool bcma_is_sprom_available(struct bcma_bus *bus) | 303 | /* |
| 304 | * Indicates the presence of external SPROM. | ||
| 305 | */ | ||
| 306 | static bool bcma_sprom_ext_available(struct bcma_bus *bus) | ||
| 304 | { | 307 | { |
| 305 | u32 sromctrl; | 308 | u32 chip_status; |
| 309 | u32 srom_control; | ||
| 310 | u32 present_mask; | ||
| 306 | 311 | ||
| 307 | if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) | 312 | if (bus->drv_cc.core->id.rev >= 31) { |
| 308 | return false; | 313 | if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) |
| 314 | return false; | ||
| 309 | 315 | ||
| 310 | if (bus->drv_cc.core->id.rev >= 32) { | 316 | srom_control = bcma_read32(bus->drv_cc.core, |
| 311 | sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL); | 317 | BCMA_CC_SROM_CONTROL); |
| 312 | return sromctrl & BCMA_CC_SROM_CONTROL_PRESENT; | 318 | return srom_control & BCMA_CC_SROM_CONTROL_PRESENT; |
| 313 | } | 319 | } |
| 314 | return true; | 320 | |
| 321 | /* older chipcommon revisions use chip status register */ | ||
| 322 | chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT); | ||
| 323 | switch (bus->chipinfo.id) { | ||
| 324 | case 0x4313: | ||
| 325 | present_mask = BCMA_CC_CHIPST_4313_SPROM_PRESENT; | ||
| 326 | break; | ||
| 327 | |||
| 328 | case 0x4331: | ||
| 329 | present_mask = BCMA_CC_CHIPST_4331_SPROM_PRESENT; | ||
| 330 | break; | ||
| 331 | |||
| 332 | default: | ||
| 333 | return true; | ||
| 334 | } | ||
| 335 | |||
| 336 | return chip_status & present_mask; | ||
| 337 | } | ||
| 338 | |||
| 339 | /* | ||
| 340 | * Indicates that on-chip OTP memory is present and enabled. | ||
| 341 | */ | ||
| 342 | static bool bcma_sprom_onchip_available(struct bcma_bus *bus) | ||
| 343 | { | ||
| 344 | u32 chip_status; | ||
| 345 | u32 otpsize = 0; | ||
| 346 | bool present; | ||
| 347 | |||
| 348 | chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT); | ||
| 349 | switch (bus->chipinfo.id) { | ||
| 350 | case 0x4313: | ||
| 351 | present = chip_status & BCMA_CC_CHIPST_4313_OTP_PRESENT; | ||
| 352 | break; | ||
| 353 | |||
| 354 | case 0x4331: | ||
| 355 | present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT; | ||
| 356 | break; | ||
| 357 | |||
| 358 | case 43224: | ||
| 359 | case 43225: | ||
| 360 | /* for these chips OTP is always available */ | ||
| 361 | present = true; | ||
| 362 | break; | ||
| 363 | |||
| 364 | default: | ||
| 365 | present = false; | ||
| 366 | break; | ||
| 367 | } | ||
| 368 | |||
| 369 | if (present) { | ||
| 370 | otpsize = bus->drv_cc.capabilities & BCMA_CC_CAP_OTPS; | ||
| 371 | otpsize >>= BCMA_CC_CAP_OTPS_SHIFT; | ||
| 372 | } | ||
| 373 | |||
| 374 | return otpsize != 0; | ||
| 375 | } | ||
| 376 | |||
| 377 | /* | ||
| 378 | * Verify OTP is filled and determine the byte | ||
| 379 | * offset where SPROM data is located. | ||
| 380 | * | ||
| 381 | * On error, returns 0; byte offset otherwise. | ||
| 382 | */ | ||
| 383 | static int bcma_sprom_onchip_offset(struct bcma_bus *bus) | ||
| 384 | { | ||
| 385 | struct bcma_device *cc = bus->drv_cc.core; | ||
| 386 | u32 offset; | ||
| 387 | |||
| 388 | /* verify OTP status */ | ||
| 389 | if ((bcma_read32(cc, BCMA_CC_OTPS) & BCMA_CC_OTPS_GU_PROG_HW) == 0) | ||
| 390 | return 0; | ||
| 391 | |||
| 392 | /* obtain bit offset from otplayout register */ | ||
| 393 | offset = (bcma_read32(cc, BCMA_CC_OTPL) & BCMA_CC_OTPL_GURGN_OFFSET); | ||
| 394 | return BCMA_CC_SPROM + (offset >> 3); | ||
| 315 | } | 395 | } |
| 316 | 396 | ||
| 317 | int bcma_sprom_get(struct bcma_bus *bus) | 397 | int bcma_sprom_get(struct bcma_bus *bus) |
| 318 | { | 398 | { |
| 319 | u16 offset; | 399 | u16 offset = BCMA_CC_SPROM; |
| 320 | u16 *sprom; | 400 | u16 *sprom; |
| 321 | int err = 0; | 401 | int err = 0; |
| 322 | 402 | ||
| 323 | if (!bus->drv_cc.core) | 403 | if (!bus->drv_cc.core) |
| 324 | return -EOPNOTSUPP; | 404 | return -EOPNOTSUPP; |
| 325 | 405 | ||
| 326 | if (!bcma_is_sprom_available(bus)) { | 406 | if (!bcma_sprom_ext_available(bus)) { |
| 327 | /* | 407 | /* |
| 328 | * Maybe there is no SPROM on the device? | 408 | * External SPROM takes precedence so check |
| 329 | * Now we ask the arch code if there is some sprom | 409 | * on-chip OTP only when no external SPROM |
| 330 | * available for this device in some other storage. | 410 | * is present. |
| 331 | */ | 411 | */ |
| 332 | err = bcma_fill_sprom_with_fallback(bus, &bus->sprom); | 412 | if (bcma_sprom_onchip_available(bus)) { |
| 333 | return err; | 413 | /* determine offset */ |
| 414 | offset = bcma_sprom_onchip_offset(bus); | ||
| 415 | } | ||
| 416 | if (!offset) { | ||
| 417 | /* | ||
| 418 | * Maybe there is no SPROM on the device? | ||
| 419 | * Now we ask the arch code if there is some sprom | ||
| 420 | * available for this device in some other storage. | ||
| 421 | */ | ||
| 422 | err = bcma_fill_sprom_with_fallback(bus, &bus->sprom); | ||
| 423 | return err; | ||
| 424 | } | ||
| 334 | } | 425 | } |
| 335 | 426 | ||
| 336 | sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), | 427 | sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), |
| @@ -341,11 +432,6 @@ int bcma_sprom_get(struct bcma_bus *bus) | |||
| 341 | if (bus->chipinfo.id == 0x4331) | 432 | if (bus->chipinfo.id == 0x4331) |
| 342 | bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false); | 433 | bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false); |
| 343 | 434 | ||
| 344 | /* Most cards have SPROM moved by additional offset 0x30 (48 dwords). | ||
| 345 | * According to brcm80211 this applies to cards with PCIe rev >= 6 | ||
| 346 | * TODO: understand this condition and use it */ | ||
| 347 | offset = (bus->chipinfo.id == 0x4331) ? BCMA_CC_SPROM : | ||
| 348 | BCMA_CC_SPROM_PCIE6; | ||
| 349 | pr_debug("SPROM offset 0x%x\n", offset); | 435 | pr_debug("SPROM offset 0x%x\n", offset); |
| 350 | bcma_sprom_read(bus, offset, sprom); | 436 | bcma_sprom_read(bus, offset, sprom); |
| 351 | 437 | ||
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index e72938b10714..8bbfe31fbac8 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h | |||
| @@ -56,6 +56,9 @@ | |||
| 56 | #define BCMA_CC_OTPS_HW_PROTECT 0x00000001 | 56 | #define BCMA_CC_OTPS_HW_PROTECT 0x00000001 |
| 57 | #define BCMA_CC_OTPS_SW_PROTECT 0x00000002 | 57 | #define BCMA_CC_OTPS_SW_PROTECT 0x00000002 |
| 58 | #define BCMA_CC_OTPS_CID_PROTECT 0x00000004 | 58 | #define BCMA_CC_OTPS_CID_PROTECT 0x00000004 |
| 59 | #define BCMA_CC_OTPS_GU_PROG_IND 0x00000F00 /* General Use programmed indication */ | ||
| 60 | #define BCMA_CC_OTPS_GU_PROG_IND_SHIFT 8 | ||
| 61 | #define BCMA_CC_OTPS_GU_PROG_HW 0x00000100 /* HW region programmed */ | ||
| 59 | #define BCMA_CC_OTPC 0x0014 /* OTP control */ | 62 | #define BCMA_CC_OTPC 0x0014 /* OTP control */ |
| 60 | #define BCMA_CC_OTPC_RECWAIT 0xFF000000 | 63 | #define BCMA_CC_OTPC_RECWAIT 0xFF000000 |
| 61 | #define BCMA_CC_OTPC_PROGWAIT 0x00FFFF00 | 64 | #define BCMA_CC_OTPC_PROGWAIT 0x00FFFF00 |
| @@ -72,6 +75,8 @@ | |||
| 72 | #define BCMA_CC_OTPP_READ 0x40000000 | 75 | #define BCMA_CC_OTPP_READ 0x40000000 |
| 73 | #define BCMA_CC_OTPP_START 0x80000000 | 76 | #define BCMA_CC_OTPP_START 0x80000000 |
| 74 | #define BCMA_CC_OTPP_BUSY 0x80000000 | 77 | #define BCMA_CC_OTPP_BUSY 0x80000000 |
| 78 | #define BCMA_CC_OTPL 0x001C /* OTP layout */ | ||
| 79 | #define BCMA_CC_OTPL_GURGN_OFFSET 0x00000FFF /* offset of general use region */ | ||
| 75 | #define BCMA_CC_IRQSTAT 0x0020 | 80 | #define BCMA_CC_IRQSTAT 0x0020 |
| 76 | #define BCMA_CC_IRQMASK 0x0024 | 81 | #define BCMA_CC_IRQMASK 0x0024 |
| 77 | #define BCMA_CC_IRQ_GPIO 0x00000001 /* gpio intr */ | 82 | #define BCMA_CC_IRQ_GPIO 0x00000001 /* gpio intr */ |
| @@ -79,6 +84,10 @@ | |||
| 79 | #define BCMA_CC_IRQ_WDRESET 0x80000000 /* watchdog reset occurred */ | 84 | #define BCMA_CC_IRQ_WDRESET 0x80000000 /* watchdog reset occurred */ |
| 80 | #define BCMA_CC_CHIPCTL 0x0028 /* Rev >= 11 only */ | 85 | #define BCMA_CC_CHIPCTL 0x0028 /* Rev >= 11 only */ |
| 81 | #define BCMA_CC_CHIPSTAT 0x002C /* Rev >= 11 only */ | 86 | #define BCMA_CC_CHIPSTAT 0x002C /* Rev >= 11 only */ |
| 87 | #define BCMA_CC_CHIPST_4313_SPROM_PRESENT 1 | ||
| 88 | #define BCMA_CC_CHIPST_4313_OTP_PRESENT 2 | ||
| 89 | #define BCMA_CC_CHIPST_4331_SPROM_PRESENT 2 | ||
| 90 | #define BCMA_CC_CHIPST_4331_OTP_PRESENT 4 | ||
| 82 | #define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */ | 91 | #define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */ |
| 83 | #define BCMA_CC_JCMD_START 0x80000000 | 92 | #define BCMA_CC_JCMD_START 0x80000000 |
| 84 | #define BCMA_CC_JCMD_BUSY 0x80000000 | 93 | #define BCMA_CC_JCMD_BUSY 0x80000000 |
| @@ -256,7 +265,6 @@ | |||
| 256 | #define BCMA_CC_PLLCTL_ADDR 0x0660 | 265 | #define BCMA_CC_PLLCTL_ADDR 0x0660 |
| 257 | #define BCMA_CC_PLLCTL_DATA 0x0664 | 266 | #define BCMA_CC_PLLCTL_DATA 0x0664 |
| 258 | #define BCMA_CC_SPROM 0x0800 /* SPROM beginning */ | 267 | #define BCMA_CC_SPROM 0x0800 /* SPROM beginning */ |
| 259 | #define BCMA_CC_SPROM_PCIE6 0x0830 /* SPROM beginning on PCIe rev >= 6 */ | ||
| 260 | 268 | ||
| 261 | /* Divider allocation in 4716/47162/5356 */ | 269 | /* Divider allocation in 4716/47162/5356 */ |
| 262 | #define BCMA_CC_PMU5_MAINPLL_CPU 1 | 270 | #define BCMA_CC_PMU5_MAINPLL_CPU 1 |
