aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorSujith <Sujith.Manoharan@atheros.com>2010-06-01 05:44:09 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-06-03 14:10:46 -0400
commit15ae733b25b7d74e9ef14eab8414447204bdcc1b (patch)
tree6757e3b53d2fdc17f9c326f955222d7b8c0e4738 /drivers/net/wireless
parenta55f858852e4345d0a31af593c46738ca8614bff (diff)
ath9k_hw: Update the PCI WAR register
This patch updates the PCI power save handling code, fixing ASPM hangs and handling device state D3 properly. The WAR register is programmed with the correct values now. Signed-off-by: Sujith <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_hw.c85
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h3
2 files changed, 60 insertions, 28 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index a8a8cdc04afa..748449cd5872 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -436,55 +436,84 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
436 } 436 }
437 437
438 udelay(1000); 438 udelay(1000);
439 }
439 440
440 /* set bit 19 to allow forcing of pcie core into L1 state */ 441 if (power_off) {
441 REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); 442 /* clear bit 19 to disable L1 */
443 REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
444
445 val = REG_READ(ah, AR_WA);
442 446
443 /* Several PCIe massages to ensure proper behaviour */ 447 /*
448 * Set PCIe workaround bits
449 * In AR9280 and AR9285, bit 14 in WA register (disable L1)
450 * should only be set when device enters D3 and be
451 * cleared when device comes back to D0.
452 */
453 if (ah->config.pcie_waen) {
454 if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
455 val |= AR_WA_D3_L1_DISABLE;
456 } else {
457 if (((AR_SREV_9285(ah) ||
458 AR_SREV_9271(ah) ||
459 AR_SREV_9287(ah)) &&
460 (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) ||
461 (AR_SREV_9280(ah) &&
462 (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) {
463 val |= AR_WA_D3_L1_DISABLE;
464 }
465 }
466
467 if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) {
468 /*
469 * Disable bit 6 and 7 before entering D3 to
470 * prevent system hang.
471 */
472 val &= ~(AR_WA_BIT6 | AR_WA_BIT7);
473 }
474
475 if (AR_SREV_9285E_20(ah))
476 val |= AR_WA_BIT23;
477
478 REG_WRITE(ah, AR_WA, val);
479 } else {
444 if (ah->config.pcie_waen) { 480 if (ah->config.pcie_waen) {
445 val = ah->config.pcie_waen; 481 val = ah->config.pcie_waen;
446 if (!power_off) 482 if (!power_off)
447 val &= (~AR_WA_D3_L1_DISABLE); 483 val &= (~AR_WA_D3_L1_DISABLE);
448 } else { 484 } else {
449 if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || 485 if (AR_SREV_9285(ah) ||
486 AR_SREV_9271(ah) ||
450 AR_SREV_9287(ah)) { 487 AR_SREV_9287(ah)) {
451 val = AR9285_WA_DEFAULT; 488 val = AR9285_WA_DEFAULT;
452 if (!power_off) 489 if (!power_off)
453 val &= (~AR_WA_D3_L1_DISABLE); 490 val &= (~AR_WA_D3_L1_DISABLE);
454 } else if (AR_SREV_9280(ah)) { 491 }
492 else if (AR_SREV_9280(ah)) {
455 /* 493 /*
456 * On AR9280 chips bit 22 of 0x4004 needs to be 494 * For AR9280 chips, bit 22 of 0x4004
457 * set otherwise card may disappear. 495 * needs to be set.
458 */ 496 */
459 val = AR9280_WA_DEFAULT; 497 val = AR9280_WA_DEFAULT;
460 if (!power_off) 498 if (!power_off)
461 val &= (~AR_WA_D3_L1_DISABLE); 499 val &= (~AR_WA_D3_L1_DISABLE);
462 } else 500 } else {
463 val = AR_WA_DEFAULT; 501 val = AR_WA_DEFAULT;
502 }
503 }
504
505 /* WAR for ASPM system hang */
506 if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) {
507 val |= (AR_WA_BIT6 | AR_WA_BIT7);
464 } 508 }
465 509
510 if (AR_SREV_9285E_20(ah))
511 val |= AR_WA_BIT23;
512
466 REG_WRITE(ah, AR_WA, val); 513 REG_WRITE(ah, AR_WA, val);
467 }
468 514
469 if (power_off) { 515 /* set bit 19 to allow forcing of pcie core into L1 state */
470 /* 516 REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
471 * Set PCIe workaround bits
472 * bit 14 in WA register (disable L1) should only
473 * be set when device enters D3 and be cleared
474 * when device comes back to D0.
475 */
476 if (ah->config.pcie_waen) {
477 if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
478 REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
479 } else {
480 if (((AR_SREV_9285(ah) || AR_SREV_9271(ah) ||
481 AR_SREV_9287(ah)) &&
482 (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) ||
483 (AR_SREV_9280(ah) &&
484 (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) {
485 REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
486 }
487 }
488 } 517 }
489} 518}
490 519
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index c9a009fab221..a7371a080491 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -700,6 +700,9 @@
700#define AR_RC_HOSTIF 0x00000100 700#define AR_RC_HOSTIF 0x00000100
701 701
702#define AR_WA 0x4004 702#define AR_WA 0x4004
703#define AR_WA_BIT6 (1 << 6)
704#define AR_WA_BIT7 (1 << 7)
705#define AR_WA_BIT23 (1 << 23)
703#define AR_WA_D3_L1_DISABLE (1 << 14) 706#define AR_WA_D3_L1_DISABLE (1 << 14)
704#define AR9285_WA_DEFAULT 0x004a050b 707#define AR9285_WA_DEFAULT 0x004a050b
705#define AR9280_WA_DEFAULT 0x0040073b 708#define AR9280_WA_DEFAULT 0x0040073b