diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/Kconfig | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/Makefile | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ani.c | 195 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ani.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/eeprom.c | 3870 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/eeprom.h | 245 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/eeprom_4k.c | 1186 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/eeprom_9287.c | 1183 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/eeprom_def.c | 1385 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 19 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/mac.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/mac.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/pci.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/phy.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/phy.h | 21 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 48 |
19 files changed, 4092 insertions, 4135 deletions
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 2cb72f8c32d7..ef5f59c4dd80 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
@@ -6,7 +6,13 @@ config ATH9K | |||
6 | select NEW_LEDS | 6 | select NEW_LEDS |
7 | ---help--- | 7 | ---help--- |
8 | This module adds support for wireless adapters based on | 8 | This module adds support for wireless adapters based on |
9 | Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets. | 9 | Atheros IEEE 802.11n AR5008, AR9001 and AR9002 family |
10 | of chipsets. For a specific list of supported external | ||
11 | cards, laptops that already ship with these cards and | ||
12 | APs that come with these cards refer to to ath9k wiki | ||
13 | products page: | ||
14 | |||
15 | http://wireless.kernel.org/en/users/Drivers/ath9k/products | ||
10 | 16 | ||
11 | If you choose to build a module, it'll be called ath9k. | 17 | If you choose to build a module, it'll be called ath9k. |
12 | 18 | ||
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 783bc39eb2ff..28443e05ec10 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -1,5 +1,8 @@ | |||
1 | ath9k-y += hw.o \ | 1 | ath9k-y += hw.o \ |
2 | eeprom.o \ | 2 | eeprom.o \ |
3 | eeprom_def.o \ | ||
4 | eeprom_4k.o \ | ||
5 | eeprom_9287.o \ | ||
3 | mac.o \ | 6 | mac.o \ |
4 | calib.o \ | 7 | calib.o \ |
5 | ani.o \ | 8 | ani.o \ |
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index b7093126dbb8..f264097a2f4e 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -236,36 +236,35 @@ static void ath9k_ani_restart(struct ath_hw *ah) | |||
236 | return; | 236 | return; |
237 | 237 | ||
238 | aniState = ah->curani; | 238 | aniState = ah->curani; |
239 | |||
240 | aniState->listenTime = 0; | 239 | aniState->listenTime = 0; |
241 | if (ah->has_hw_phycounters) { | 240 | |
242 | if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) { | 241 | if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) { |
243 | aniState->ofdmPhyErrBase = 0; | 242 | aniState->ofdmPhyErrBase = 0; |
244 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
245 | "OFDM Trigger is too high for hw counters\n"); | ||
246 | } else { | ||
247 | aniState->ofdmPhyErrBase = | ||
248 | AR_PHY_COUNTMAX - aniState->ofdmTrigHigh; | ||
249 | } | ||
250 | if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) { | ||
251 | aniState->cckPhyErrBase = 0; | ||
252 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
253 | "CCK Trigger is too high for hw counters\n"); | ||
254 | } else { | ||
255 | aniState->cckPhyErrBase = | ||
256 | AR_PHY_COUNTMAX - aniState->cckTrigHigh; | ||
257 | } | ||
258 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 243 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, |
259 | "Writing ofdmbase=%u cckbase=%u\n", | 244 | "OFDM Trigger is too high for hw counters\n"); |
260 | aniState->ofdmPhyErrBase, | 245 | } else { |
261 | aniState->cckPhyErrBase); | 246 | aniState->ofdmPhyErrBase = |
262 | REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); | 247 | AR_PHY_COUNTMAX - aniState->ofdmTrigHigh; |
263 | REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); | 248 | } |
264 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); | 249 | if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) { |
265 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | 250 | aniState->cckPhyErrBase = 0; |
266 | 251 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | |
267 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | 252 | "CCK Trigger is too high for hw counters\n"); |
253 | } else { | ||
254 | aniState->cckPhyErrBase = | ||
255 | AR_PHY_COUNTMAX - aniState->cckTrigHigh; | ||
268 | } | 256 | } |
257 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
258 | "Writing ofdmbase=%u cckbase=%u\n", | ||
259 | aniState->ofdmPhyErrBase, | ||
260 | aniState->cckPhyErrBase); | ||
261 | REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); | ||
262 | REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); | ||
263 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); | ||
264 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | ||
265 | |||
266 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | ||
267 | |||
269 | aniState->ofdmPhyErrCount = 0; | 268 | aniState->ofdmPhyErrCount = 0; |
270 | aniState->cckPhyErrCount = 0; | 269 | aniState->cckPhyErrCount = 0; |
271 | } | 270 | } |
@@ -530,18 +529,12 @@ void ath9k_ani_reset(struct ath_hw *ah) | |||
530 | if (aniState->firstepLevel != 0) | 529 | if (aniState->firstepLevel != 0) |
531 | ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, | 530 | ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, |
532 | aniState->firstepLevel); | 531 | aniState->firstepLevel); |
533 | if (ah->has_hw_phycounters) { | ||
534 | ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & | ||
535 | ~ATH9K_RX_FILTER_PHYERR); | ||
536 | ath9k_ani_restart(ah); | ||
537 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); | ||
538 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | ||
539 | 532 | ||
540 | } else { | 533 | ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & |
541 | ath9k_ani_restart(ah); | 534 | ~ATH9K_RX_FILTER_PHYERR); |
542 | ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) | | 535 | ath9k_ani_restart(ah); |
543 | ATH9K_RX_FILTER_PHYERR); | 536 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); |
544 | } | 537 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); |
545 | } | 538 | } |
546 | 539 | ||
547 | void ath9k_hw_ani_monitor(struct ath_hw *ah, | 540 | void ath9k_hw_ani_monitor(struct ath_hw *ah, |
@@ -550,6 +543,8 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, | |||
550 | { | 543 | { |
551 | struct ar5416AniState *aniState; | 544 | struct ar5416AniState *aniState; |
552 | int32_t listenTime; | 545 | int32_t listenTime; |
546 | u32 phyCnt1, phyCnt2; | ||
547 | u32 ofdmPhyErrCnt, cckPhyErrCnt; | ||
553 | 548 | ||
554 | if (!DO_ANI(ah)) | 549 | if (!DO_ANI(ah)) |
555 | return; | 550 | return; |
@@ -566,50 +561,45 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, | |||
566 | 561 | ||
567 | aniState->listenTime += listenTime; | 562 | aniState->listenTime += listenTime; |
568 | 563 | ||
569 | if (ah->has_hw_phycounters) { | 564 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); |
570 | u32 phyCnt1, phyCnt2; | ||
571 | u32 ofdmPhyErrCnt, cckPhyErrCnt; | ||
572 | 565 | ||
573 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | 566 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); |
574 | 567 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | |
575 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | 568 | |
576 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | 569 | if (phyCnt1 < aniState->ofdmPhyErrBase || |
577 | 570 | phyCnt2 < aniState->cckPhyErrBase) { | |
578 | if (phyCnt1 < aniState->ofdmPhyErrBase || | 571 | if (phyCnt1 < aniState->ofdmPhyErrBase) { |
579 | phyCnt2 < aniState->cckPhyErrBase) { | 572 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, |
580 | if (phyCnt1 < aniState->ofdmPhyErrBase) { | 573 | "phyCnt1 0x%x, resetting " |
581 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 574 | "counter value to 0x%x\n", |
582 | "phyCnt1 0x%x, resetting " | 575 | phyCnt1, aniState->ofdmPhyErrBase); |
583 | "counter value to 0x%x\n", | 576 | REG_WRITE(ah, AR_PHY_ERR_1, |
584 | phyCnt1, aniState->ofdmPhyErrBase); | 577 | aniState->ofdmPhyErrBase); |
585 | REG_WRITE(ah, AR_PHY_ERR_1, | 578 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, |
586 | aniState->ofdmPhyErrBase); | 579 | AR_PHY_ERR_OFDM_TIMING); |
587 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, | 580 | } |
588 | AR_PHY_ERR_OFDM_TIMING); | 581 | if (phyCnt2 < aniState->cckPhyErrBase) { |
589 | } | 582 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, |
590 | if (phyCnt2 < aniState->cckPhyErrBase) { | 583 | "phyCnt2 0x%x, resetting " |
591 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 584 | "counter value to 0x%x\n", |
592 | "phyCnt2 0x%x, resetting " | 585 | phyCnt2, aniState->cckPhyErrBase); |
593 | "counter value to 0x%x\n", | 586 | REG_WRITE(ah, AR_PHY_ERR_2, |
594 | phyCnt2, aniState->cckPhyErrBase); | 587 | aniState->cckPhyErrBase); |
595 | REG_WRITE(ah, AR_PHY_ERR_2, | 588 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, |
596 | aniState->cckPhyErrBase); | 589 | AR_PHY_ERR_CCK_TIMING); |
597 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, | ||
598 | AR_PHY_ERR_CCK_TIMING); | ||
599 | } | ||
600 | return; | ||
601 | } | 590 | } |
591 | return; | ||
592 | } | ||
602 | 593 | ||
603 | ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; | 594 | ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; |
604 | ah->stats.ast_ani_ofdmerrs += | 595 | ah->stats.ast_ani_ofdmerrs += |
605 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; | 596 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; |
606 | aniState->ofdmPhyErrCount = ofdmPhyErrCnt; | 597 | aniState->ofdmPhyErrCount = ofdmPhyErrCnt; |
607 | 598 | ||
608 | cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; | 599 | cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; |
609 | ah->stats.ast_ani_cckerrs += | 600 | ah->stats.ast_ani_cckerrs += |
610 | cckPhyErrCnt - aniState->cckPhyErrCount; | 601 | cckPhyErrCnt - aniState->cckPhyErrCount; |
611 | aniState->cckPhyErrCount = cckPhyErrCnt; | 602 | aniState->cckPhyErrCount = cckPhyErrCnt; |
612 | } | ||
613 | 603 | ||
614 | if (aniState->listenTime > 5 * ah->aniperiod) { | 604 | if (aniState->listenTime > 5 * ah->aniperiod) { |
615 | if (aniState->ofdmPhyErrCount <= aniState->listenTime * | 605 | if (aniState->ofdmPhyErrCount <= aniState->listenTime * |
@@ -632,11 +622,6 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, | |||
632 | } | 622 | } |
633 | } | 623 | } |
634 | 624 | ||
635 | bool ath9k_hw_phycounters(struct ath_hw *ah) | ||
636 | { | ||
637 | return ah->has_hw_phycounters ? true : false; | ||
638 | } | ||
639 | |||
640 | void ath9k_enable_mib_counters(struct ath_hw *ah) | 625 | void ath9k_enable_mib_counters(struct ath_hw *ah) |
641 | { | 626 | { |
642 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable MIB counters\n"); | 627 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable MIB counters\n"); |
@@ -781,9 +766,7 @@ void ath9k_hw_ani_init(struct ath_hw *ah) | |||
781 | { | 766 | { |
782 | int i; | 767 | int i; |
783 | 768 | ||
784 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Attach ANI\n"); | 769 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Initialize ANI\n"); |
785 | |||
786 | ah->has_hw_phycounters = 1; | ||
787 | 770 | ||
788 | memset(ah->ani, 0, sizeof(ah->ani)); | 771 | memset(ah->ani, 0, sizeof(ah->ani)); |
789 | for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { | 772 | for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { |
@@ -799,24 +782,22 @@ void ath9k_hw_ani_init(struct ath_hw *ah) | |||
799 | ATH9K_ANI_CCK_WEAK_SIG_THR; | 782 | ATH9K_ANI_CCK_WEAK_SIG_THR; |
800 | ah->ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; | 783 | ah->ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; |
801 | ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL; | 784 | ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL; |
802 | if (ah->has_hw_phycounters) { | 785 | ah->ani[i].ofdmPhyErrBase = |
803 | ah->ani[i].ofdmPhyErrBase = | 786 | AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH; |
804 | AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH; | 787 | ah->ani[i].cckPhyErrBase = |
805 | ah->ani[i].cckPhyErrBase = | 788 | AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH; |
806 | AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH; | ||
807 | } | ||
808 | } | ||
809 | if (ah->has_hw_phycounters) { | ||
810 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
811 | "Setting OfdmErrBase = 0x%08x\n", | ||
812 | ah->ani[0].ofdmPhyErrBase); | ||
813 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n", | ||
814 | ah->ani[0].cckPhyErrBase); | ||
815 | |||
816 | REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase); | ||
817 | REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase); | ||
818 | ath9k_enable_mib_counters(ah); | ||
819 | } | 789 | } |
790 | |||
791 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
792 | "Setting OfdmErrBase = 0x%08x\n", | ||
793 | ah->ani[0].ofdmPhyErrBase); | ||
794 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n", | ||
795 | ah->ani[0].cckPhyErrBase); | ||
796 | |||
797 | REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase); | ||
798 | REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase); | ||
799 | ath9k_enable_mib_counters(ah); | ||
800 | |||
820 | ah->aniperiod = ATH9K_ANI_PERIOD; | 801 | ah->aniperiod = ATH9K_ANI_PERIOD; |
821 | if (ah->config.enable_ani) | 802 | if (ah->config.enable_ani) |
822 | ah->proc_phyerr |= HAL_PROCESS_ANI; | 803 | ah->proc_phyerr |= HAL_PROCESS_ANI; |
@@ -826,9 +807,7 @@ void ath9k_hw_ani_disable(struct ath_hw *ah) | |||
826 | { | 807 | { |
827 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disabling ANI\n"); | 808 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disabling ANI\n"); |
828 | 809 | ||
829 | if (ah->has_hw_phycounters) { | 810 | ath9k_hw_disable_mib_counters(ah); |
830 | ath9k_hw_disable_mib_counters(ah); | 811 | REG_WRITE(ah, AR_PHY_ERR_1, 0); |
831 | REG_WRITE(ah, AR_PHY_ERR_1, 0); | 812 | REG_WRITE(ah, AR_PHY_ERR_2, 0); |
832 | REG_WRITE(ah, AR_PHY_ERR_2, 0); | ||
833 | } | ||
834 | } | 813 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index a36b7bb7c42a..119924511f85 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h | |||
@@ -124,7 +124,6 @@ void ath9k_ani_reset(struct ath_hw *ah); | |||
124 | void ath9k_hw_ani_monitor(struct ath_hw *ah, | 124 | void ath9k_hw_ani_monitor(struct ath_hw *ah, |
125 | const struct ath9k_node_stats *stats, | 125 | const struct ath9k_node_stats *stats, |
126 | struct ath9k_channel *chan); | 126 | struct ath9k_channel *chan); |
127 | bool ath9k_hw_phycounters(struct ath_hw *ah); | ||
128 | void ath9k_enable_mib_counters(struct ath_hw *ah); | 127 | void ath9k_enable_mib_counters(struct ath_hw *ah); |
129 | void ath9k_hw_disable_mib_counters(struct ath_hw *ah); | 128 | void ath9k_hw_disable_mib_counters(struct ath_hw *ah); |
130 | u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt, | 129 | u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt, |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 7a5a157e15c4..2fd663c01b8e 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "hw.h" | 25 | #include "hw.h" |
26 | #include "rc.h" | 26 | #include "rc.h" |
27 | #include "debug.h" | 27 | #include "debug.h" |
28 | #include "../ath.h" | ||
28 | 29 | ||
29 | struct ath_node; | 30 | struct ath_node; |
30 | 31 | ||
@@ -532,6 +533,8 @@ struct ath_softc { | |||
532 | struct ieee80211_hw *hw; | 533 | struct ieee80211_hw *hw; |
533 | struct device *dev; | 534 | struct device *dev; |
534 | 535 | ||
536 | struct ath_common common; | ||
537 | |||
535 | spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */ | 538 | spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */ |
536 | struct ath_wiphy *pri_wiphy; | 539 | struct ath_wiphy *pri_wiphy; |
537 | struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may | 540 | struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may |
@@ -564,7 +567,6 @@ struct ath_softc { | |||
564 | u32 sc_flags; /* SC_OP_* */ | 567 | u32 sc_flags; /* SC_OP_* */ |
565 | u16 curtxpow; | 568 | u16 curtxpow; |
566 | u16 curaid; | 569 | u16 curaid; |
567 | u16 cachelsz; | ||
568 | u8 nbcnvifs; | 570 | u8 nbcnvifs; |
569 | u16 nvifs; | 571 | u16 nvifs; |
570 | u8 tx_chainmask; | 572 | u8 tx_chainmask; |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index 4cb64a0900bb..958948bc73fd 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c | |||
@@ -16,9 +16,16 @@ | |||
16 | 16 | ||
17 | #include "ath9k.h" | 17 | #include "ath9k.h" |
18 | 18 | ||
19 | static void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, | 19 | static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz) |
20 | u32 reg, u32 mask, | 20 | { |
21 | u32 shift, u32 val) | 21 | if (fbin == AR5416_BCHAN_UNUSED) |
22 | return fbin; | ||
23 | |||
24 | return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); | ||
25 | } | ||
26 | |||
27 | void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask, | ||
28 | u32 shift, u32 val) | ||
22 | { | 29 | { |
23 | u32 regVal; | 30 | u32 regVal; |
24 | 31 | ||
@@ -33,19 +40,8 @@ static void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, | |||
33 | return; | 40 | return; |
34 | } | 41 | } |
35 | 42 | ||
36 | static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz) | 43 | int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight, |
37 | { | 44 | int16_t targetLeft, int16_t targetRight) |
38 | |||
39 | if (fbin == AR5416_BCHAN_UNUSED) | ||
40 | return fbin; | ||
41 | |||
42 | return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); | ||
43 | } | ||
44 | |||
45 | static inline int16_t ath9k_hw_interpolate(u16 target, | ||
46 | u16 srcLeft, u16 srcRight, | ||
47 | int16_t targetLeft, | ||
48 | int16_t targetRight) | ||
49 | { | 45 | { |
50 | int16_t rv; | 46 | int16_t rv; |
51 | 47 | ||
@@ -59,9 +55,8 @@ static inline int16_t ath9k_hw_interpolate(u16 target, | |||
59 | return rv; | 55 | return rv; |
60 | } | 56 | } |
61 | 57 | ||
62 | static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, | 58 | bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize, |
63 | u16 listSize, u16 *indexL, | 59 | u16 *indexL, u16 *indexR) |
64 | u16 *indexR) | ||
65 | { | 60 | { |
66 | u16 i; | 61 | u16 i; |
67 | 62 | ||
@@ -88,16 +83,16 @@ static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, | |||
88 | return false; | 83 | return false; |
89 | } | 84 | } |
90 | 85 | ||
91 | static inline bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data) | 86 | bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data) |
92 | { | 87 | { |
93 | struct ath_softc *sc = ah->ah_sc; | 88 | struct ath_softc *sc = ah->ah_sc; |
94 | 89 | ||
95 | return sc->bus_ops->eeprom_read(ah, off, data); | 90 | return sc->bus_ops->eeprom_read(ah, off, data); |
96 | } | 91 | } |
97 | 92 | ||
98 | static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, | 93 | void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, |
99 | u8 *pVpdList, u16 numIntercepts, | 94 | u8 *pVpdList, u16 numIntercepts, |
100 | u8 *pRetVpdList) | 95 | u8 *pRetVpdList) |
101 | { | 96 | { |
102 | u16 i, k; | 97 | u16 i, k; |
103 | u8 currPwr = pwrMin; | 98 | u8 currPwr = pwrMin; |
@@ -120,16 +115,14 @@ static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, | |||
120 | pRetVpdList[i] = (u8) k; | 115 | pRetVpdList[i] = (u8) k; |
121 | currPwr += 2; | 116 | currPwr += 2; |
122 | } | 117 | } |
123 | |||
124 | return true; | ||
125 | } | 118 | } |
126 | 119 | ||
127 | static void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah, | 120 | void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah, |
128 | struct ath9k_channel *chan, | 121 | struct ath9k_channel *chan, |
129 | struct cal_target_power_leg *powInfo, | 122 | struct cal_target_power_leg *powInfo, |
130 | u16 numChannels, | 123 | u16 numChannels, |
131 | struct cal_target_power_leg *pNewPower, | 124 | struct cal_target_power_leg *pNewPower, |
132 | u16 numRates, bool isExtTarget) | 125 | u16 numRates, bool isExtTarget) |
133 | { | 126 | { |
134 | struct chan_centers centers; | 127 | struct chan_centers centers; |
135 | u16 clo, chi; | 128 | u16 clo, chi; |
@@ -179,75 +172,12 @@ static void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah, | |||
179 | } | 172 | } |
180 | } | 173 | } |
181 | 174 | ||
182 | static void ath9k_get_txgain_index(struct ath_hw *ah, | 175 | void ath9k_hw_get_target_powers(struct ath_hw *ah, |
183 | struct ath9k_channel *chan, | 176 | struct ath9k_channel *chan, |
184 | struct calDataPerFreqOpLoop *rawDatasetOpLoop, | 177 | struct cal_target_power_ht *powInfo, |
185 | u8 *calChans, u16 availPiers, u8 *pwr, u8 *pcdacIdx) | 178 | u16 numChannels, |
186 | { | 179 | struct cal_target_power_ht *pNewPower, |
187 | u8 pcdac, i = 0; | 180 | u16 numRates, bool isHt40Target) |
188 | u16 idxL = 0, idxR = 0, numPiers; | ||
189 | bool match; | ||
190 | struct chan_centers centers; | ||
191 | |||
192 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
193 | |||
194 | for (numPiers = 0; numPiers < availPiers; numPiers++) | ||
195 | if (calChans[numPiers] == AR5416_BCHAN_UNUSED) | ||
196 | break; | ||
197 | |||
198 | match = ath9k_hw_get_lower_upper_index( | ||
199 | (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), | ||
200 | calChans, numPiers, &idxL, &idxR); | ||
201 | if (match) { | ||
202 | pcdac = rawDatasetOpLoop[idxL].pcdac[0][0]; | ||
203 | *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0]; | ||
204 | } else { | ||
205 | pcdac = rawDatasetOpLoop[idxR].pcdac[0][0]; | ||
206 | *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] + | ||
207 | rawDatasetOpLoop[idxR].pwrPdg[0][0])/2; | ||
208 | } | ||
209 | |||
210 | while (pcdac > ah->originalGain[i] && | ||
211 | i < (AR9280_TX_GAIN_TABLE_SIZE - 1)) | ||
212 | i++; | ||
213 | |||
214 | *pcdacIdx = i; | ||
215 | return; | ||
216 | } | ||
217 | |||
218 | static void ath9k_olc_get_pdadcs(struct ath_hw *ah, | ||
219 | u32 initTxGain, | ||
220 | int txPower, | ||
221 | u8 *pPDADCValues) | ||
222 | { | ||
223 | u32 i; | ||
224 | u32 offset; | ||
225 | |||
226 | REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0, | ||
227 | AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); | ||
228 | REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1, | ||
229 | AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); | ||
230 | |||
231 | REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7, | ||
232 | AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain); | ||
233 | |||
234 | offset = txPower; | ||
235 | for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++) | ||
236 | if (i < offset) | ||
237 | pPDADCValues[i] = 0x0; | ||
238 | else | ||
239 | pPDADCValues[i] = 0xFF; | ||
240 | } | ||
241 | |||
242 | |||
243 | |||
244 | |||
245 | static void ath9k_hw_get_target_powers(struct ath_hw *ah, | ||
246 | struct ath9k_channel *chan, | ||
247 | struct cal_target_power_ht *powInfo, | ||
248 | u16 numChannels, | ||
249 | struct cal_target_power_ht *pNewPower, | ||
250 | u16 numRates, bool isHt40Target) | ||
251 | { | 181 | { |
252 | struct chan_centers centers; | 182 | struct chan_centers centers; |
253 | u16 clo, chi; | 183 | u16 clo, chi; |
@@ -297,9 +227,8 @@ static void ath9k_hw_get_target_powers(struct ath_hw *ah, | |||
297 | } | 227 | } |
298 | } | 228 | } |
299 | 229 | ||
300 | static u16 ath9k_hw_get_max_edge_power(u16 freq, | 230 | u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, |
301 | struct cal_ctl_edges *pRdEdgesPower, | 231 | bool is2GHz, int num_band_edges) |
302 | bool is2GHz, int num_band_edges) | ||
303 | { | 232 | { |
304 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | 233 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; |
305 | int i; | 234 | int i; |
@@ -325,3743 +254,10 @@ static u16 ath9k_hw_get_max_edge_power(u16 freq, | |||
325 | return twiceMaxEdgePower; | 254 | return twiceMaxEdgePower; |
326 | } | 255 | } |
327 | 256 | ||
328 | /****************************************/ | ||
329 | /* EEPROM Operations for 4K sized cards */ | ||
330 | /****************************************/ | ||
331 | |||
332 | static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah) | ||
333 | { | ||
334 | return ((ah->eeprom.map4k.baseEepHeader.version >> 12) & 0xF); | ||
335 | } | ||
336 | |||
337 | static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah) | ||
338 | { | ||
339 | return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF); | ||
340 | } | ||
341 | |||
342 | static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) | ||
343 | { | ||
344 | #define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) | ||
345 | u16 *eep_data = (u16 *)&ah->eeprom.map4k; | ||
346 | int addr, eep_start_loc = 0; | ||
347 | |||
348 | eep_start_loc = 64; | ||
349 | |||
350 | if (!ath9k_hw_use_flash(ah)) { | ||
351 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
352 | "Reading from EEPROM, not flash\n"); | ||
353 | } | ||
354 | |||
355 | for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { | ||
356 | if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) { | ||
357 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
358 | "Unable to read eeprom region \n"); | ||
359 | return false; | ||
360 | } | ||
361 | eep_data++; | ||
362 | } | ||
363 | |||
364 | return true; | ||
365 | #undef SIZE_EEPROM_4K | ||
366 | } | ||
367 | |||
368 | static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | ||
369 | { | ||
370 | #define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) | ||
371 | struct ar5416_eeprom_4k *eep = | ||
372 | (struct ar5416_eeprom_4k *) &ah->eeprom.map4k; | ||
373 | u16 *eepdata, temp, magic, magic2; | ||
374 | u32 sum = 0, el; | ||
375 | bool need_swap = false; | ||
376 | int i, addr; | ||
377 | |||
378 | |||
379 | if (!ath9k_hw_use_flash(ah)) { | ||
380 | if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, | ||
381 | &magic)) { | ||
382 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
383 | "Reading Magic # failed\n"); | ||
384 | return false; | ||
385 | } | ||
386 | |||
387 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
388 | "Read Magic = 0x%04X\n", magic); | ||
389 | |||
390 | if (magic != AR5416_EEPROM_MAGIC) { | ||
391 | magic2 = swab16(magic); | ||
392 | |||
393 | if (magic2 == AR5416_EEPROM_MAGIC) { | ||
394 | need_swap = true; | ||
395 | eepdata = (u16 *) (&ah->eeprom); | ||
396 | |||
397 | for (addr = 0; addr < EEPROM_4K_SIZE; addr++) { | ||
398 | temp = swab16(*eepdata); | ||
399 | *eepdata = temp; | ||
400 | eepdata++; | ||
401 | } | ||
402 | } else { | ||
403 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
404 | "Invalid EEPROM Magic. " | ||
405 | "endianness mismatch.\n"); | ||
406 | return -EINVAL; | ||
407 | } | ||
408 | } | ||
409 | } | ||
410 | |||
411 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", | ||
412 | need_swap ? "True" : "False"); | ||
413 | |||
414 | if (need_swap) | ||
415 | el = swab16(ah->eeprom.map4k.baseEepHeader.length); | ||
416 | else | ||
417 | el = ah->eeprom.map4k.baseEepHeader.length; | ||
418 | |||
419 | if (el > sizeof(struct ar5416_eeprom_4k)) | ||
420 | el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16); | ||
421 | else | ||
422 | el = el / sizeof(u16); | ||
423 | |||
424 | eepdata = (u16 *)(&ah->eeprom); | ||
425 | |||
426 | for (i = 0; i < el; i++) | ||
427 | sum ^= *eepdata++; | ||
428 | |||
429 | if (need_swap) { | ||
430 | u32 integer; | ||
431 | u16 word; | ||
432 | |||
433 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
434 | "EEPROM Endianness is not native.. Changing\n"); | ||
435 | |||
436 | word = swab16(eep->baseEepHeader.length); | ||
437 | eep->baseEepHeader.length = word; | ||
438 | |||
439 | word = swab16(eep->baseEepHeader.checksum); | ||
440 | eep->baseEepHeader.checksum = word; | ||
441 | |||
442 | word = swab16(eep->baseEepHeader.version); | ||
443 | eep->baseEepHeader.version = word; | ||
444 | |||
445 | word = swab16(eep->baseEepHeader.regDmn[0]); | ||
446 | eep->baseEepHeader.regDmn[0] = word; | ||
447 | |||
448 | word = swab16(eep->baseEepHeader.regDmn[1]); | ||
449 | eep->baseEepHeader.regDmn[1] = word; | ||
450 | |||
451 | word = swab16(eep->baseEepHeader.rfSilent); | ||
452 | eep->baseEepHeader.rfSilent = word; | ||
453 | |||
454 | word = swab16(eep->baseEepHeader.blueToothOptions); | ||
455 | eep->baseEepHeader.blueToothOptions = word; | ||
456 | |||
457 | word = swab16(eep->baseEepHeader.deviceCap); | ||
458 | eep->baseEepHeader.deviceCap = word; | ||
459 | |||
460 | integer = swab32(eep->modalHeader.antCtrlCommon); | ||
461 | eep->modalHeader.antCtrlCommon = integer; | ||
462 | |||
463 | for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { | ||
464 | integer = swab32(eep->modalHeader.antCtrlChain[i]); | ||
465 | eep->modalHeader.antCtrlChain[i] = integer; | ||
466 | } | ||
467 | |||
468 | for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { | ||
469 | word = swab16(eep->modalHeader.spurChans[i].spurChan); | ||
470 | eep->modalHeader.spurChans[i].spurChan = word; | ||
471 | } | ||
472 | } | ||
473 | |||
474 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || | ||
475 | ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { | ||
476 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
477 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | ||
478 | sum, ah->eep_ops->get_eeprom_ver(ah)); | ||
479 | return -EINVAL; | ||
480 | } | ||
481 | |||
482 | return 0; | ||
483 | #undef EEPROM_4K_SIZE | ||
484 | } | ||
485 | |||
486 | static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, | ||
487 | enum eeprom_param param) | ||
488 | { | ||
489 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | ||
490 | struct modal_eep_4k_header *pModal = &eep->modalHeader; | ||
491 | struct base_eep_header_4k *pBase = &eep->baseEepHeader; | ||
492 | |||
493 | switch (param) { | ||
494 | case EEP_NFTHRESH_2: | ||
495 | return pModal->noiseFloorThreshCh[0]; | ||
496 | case AR_EEPROM_MAC(0): | ||
497 | return pBase->macAddr[0] << 8 | pBase->macAddr[1]; | ||
498 | case AR_EEPROM_MAC(1): | ||
499 | return pBase->macAddr[2] << 8 | pBase->macAddr[3]; | ||
500 | case AR_EEPROM_MAC(2): | ||
501 | return pBase->macAddr[4] << 8 | pBase->macAddr[5]; | ||
502 | case EEP_REG_0: | ||
503 | return pBase->regDmn[0]; | ||
504 | case EEP_REG_1: | ||
505 | return pBase->regDmn[1]; | ||
506 | case EEP_OP_CAP: | ||
507 | return pBase->deviceCap; | ||
508 | case EEP_OP_MODE: | ||
509 | return pBase->opCapFlags; | ||
510 | case EEP_RF_SILENT: | ||
511 | return pBase->rfSilent; | ||
512 | case EEP_OB_2: | ||
513 | return pModal->ob_01; | ||
514 | case EEP_DB_2: | ||
515 | return pModal->db1_01; | ||
516 | case EEP_MINOR_REV: | ||
517 | return pBase->version & AR5416_EEP_VER_MINOR_MASK; | ||
518 | case EEP_TX_MASK: | ||
519 | return pBase->txMask; | ||
520 | case EEP_RX_MASK: | ||
521 | return pBase->rxMask; | ||
522 | case EEP_FRAC_N_5G: | ||
523 | return 0; | ||
524 | default: | ||
525 | return 0; | ||
526 | } | ||
527 | } | ||
528 | |||
529 | static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah, | ||
530 | struct ath9k_channel *chan, | ||
531 | struct cal_data_per_freq_4k *pRawDataSet, | ||
532 | u8 *bChans, u16 availPiers, | ||
533 | u16 tPdGainOverlap, int16_t *pMinCalPower, | ||
534 | u16 *pPdGainBoundaries, u8 *pPDADCValues, | ||
535 | u16 numXpdGains) | ||
536 | { | ||
537 | #define TMP_VAL_VPD_TABLE \ | ||
538 | ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep)); | ||
539 | int i, j, k; | ||
540 | int16_t ss; | ||
541 | u16 idxL = 0, idxR = 0, numPiers; | ||
542 | static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS] | ||
543 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
544 | static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS] | ||
545 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
546 | static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS] | ||
547 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
548 | |||
549 | u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; | ||
550 | u8 minPwrT4[AR5416_EEP4K_NUM_PD_GAINS]; | ||
551 | u8 maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS]; | ||
552 | int16_t vpdStep; | ||
553 | int16_t tmpVal; | ||
554 | u16 sizeCurrVpdTable, maxIndex, tgtIndex; | ||
555 | bool match; | ||
556 | int16_t minDelta = 0; | ||
557 | struct chan_centers centers; | ||
558 | #define PD_GAIN_BOUNDARY_DEFAULT 58; | ||
559 | |||
560 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
561 | |||
562 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | ||
563 | if (bChans[numPiers] == AR5416_BCHAN_UNUSED) | ||
564 | break; | ||
565 | } | ||
566 | |||
567 | match = ath9k_hw_get_lower_upper_index( | ||
568 | (u8)FREQ2FBIN(centers.synth_center, | ||
569 | IS_CHAN_2GHZ(chan)), bChans, numPiers, | ||
570 | &idxL, &idxR); | ||
571 | |||
572 | if (match) { | ||
573 | for (i = 0; i < numXpdGains; i++) { | ||
574 | minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; | ||
575 | maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; | ||
576 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
577 | pRawDataSet[idxL].pwrPdg[i], | ||
578 | pRawDataSet[idxL].vpdPdg[i], | ||
579 | AR5416_EEP4K_PD_GAIN_ICEPTS, | ||
580 | vpdTableI[i]); | ||
581 | } | ||
582 | } else { | ||
583 | for (i = 0; i < numXpdGains; i++) { | ||
584 | pVpdL = pRawDataSet[idxL].vpdPdg[i]; | ||
585 | pPwrL = pRawDataSet[idxL].pwrPdg[i]; | ||
586 | pVpdR = pRawDataSet[idxR].vpdPdg[i]; | ||
587 | pPwrR = pRawDataSet[idxR].pwrPdg[i]; | ||
588 | |||
589 | minPwrT4[i] = max(pPwrL[0], pPwrR[0]); | ||
590 | |||
591 | maxPwrT4[i] = | ||
592 | min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1], | ||
593 | pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]); | ||
594 | |||
595 | |||
596 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
597 | pPwrL, pVpdL, | ||
598 | AR5416_EEP4K_PD_GAIN_ICEPTS, | ||
599 | vpdTableL[i]); | ||
600 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
601 | pPwrR, pVpdR, | ||
602 | AR5416_EEP4K_PD_GAIN_ICEPTS, | ||
603 | vpdTableR[i]); | ||
604 | |||
605 | for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { | ||
606 | vpdTableI[i][j] = | ||
607 | (u8)(ath9k_hw_interpolate((u16) | ||
608 | FREQ2FBIN(centers. | ||
609 | synth_center, | ||
610 | IS_CHAN_2GHZ | ||
611 | (chan)), | ||
612 | bChans[idxL], bChans[idxR], | ||
613 | vpdTableL[i][j], vpdTableR[i][j])); | ||
614 | } | ||
615 | } | ||
616 | } | ||
617 | |||
618 | *pMinCalPower = (int16_t)(minPwrT4[0] / 2); | ||
619 | |||
620 | k = 0; | ||
621 | |||
622 | for (i = 0; i < numXpdGains; i++) { | ||
623 | if (i == (numXpdGains - 1)) | ||
624 | pPdGainBoundaries[i] = | ||
625 | (u16)(maxPwrT4[i] / 2); | ||
626 | else | ||
627 | pPdGainBoundaries[i] = | ||
628 | (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4); | ||
629 | |||
630 | pPdGainBoundaries[i] = | ||
631 | min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); | ||
632 | |||
633 | if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { | ||
634 | minDelta = pPdGainBoundaries[0] - 23; | ||
635 | pPdGainBoundaries[0] = 23; | ||
636 | } else { | ||
637 | minDelta = 0; | ||
638 | } | ||
639 | |||
640 | if (i == 0) { | ||
641 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
642 | ss = (int16_t)(0 - (minPwrT4[i] / 2)); | ||
643 | else | ||
644 | ss = 0; | ||
645 | } else { | ||
646 | ss = (int16_t)((pPdGainBoundaries[i - 1] - | ||
647 | (minPwrT4[i] / 2)) - | ||
648 | tPdGainOverlap + 1 + minDelta); | ||
649 | } | ||
650 | vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); | ||
651 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
652 | |||
653 | while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
654 | tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); | ||
655 | pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); | ||
656 | ss++; | ||
657 | } | ||
658 | |||
659 | sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); | ||
660 | tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap - | ||
661 | (minPwrT4[i] / 2)); | ||
662 | maxIndex = (tgtIndex < sizeCurrVpdTable) ? | ||
663 | tgtIndex : sizeCurrVpdTable; | ||
664 | |||
665 | while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) | ||
666 | pPDADCValues[k++] = vpdTableI[i][ss++]; | ||
667 | |||
668 | vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - | ||
669 | vpdTableI[i][sizeCurrVpdTable - 2]); | ||
670 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
671 | |||
672 | if (tgtIndex >= maxIndex) { | ||
673 | while ((ss <= tgtIndex) && | ||
674 | (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
675 | tmpVal = (int16_t) TMP_VAL_VPD_TABLE; | ||
676 | pPDADCValues[k++] = (u8)((tmpVal > 255) ? | ||
677 | 255 : tmpVal); | ||
678 | ss++; | ||
679 | } | ||
680 | } | ||
681 | } | ||
682 | |||
683 | while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) { | ||
684 | pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT; | ||
685 | i++; | ||
686 | } | ||
687 | |||
688 | while (k < AR5416_NUM_PDADC_VALUES) { | ||
689 | pPDADCValues[k] = pPDADCValues[k - 1]; | ||
690 | k++; | ||
691 | } | ||
692 | |||
693 | return; | ||
694 | #undef TMP_VAL_VPD_TABLE | ||
695 | } | ||
696 | |||
697 | static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | ||
698 | struct ath9k_channel *chan, | ||
699 | int16_t *pTxPowerIndexOffset) | ||
700 | { | ||
701 | struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; | ||
702 | struct cal_data_per_freq_4k *pRawDataset; | ||
703 | u8 *pCalBChans = NULL; | ||
704 | u16 pdGainOverlap_t2; | ||
705 | static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; | ||
706 | u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK]; | ||
707 | u16 numPiers, i, j; | ||
708 | int16_t tMinCalPower; | ||
709 | u16 numXpdGain, xpdMask; | ||
710 | u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 }; | ||
711 | u32 reg32, regOffset, regChainOffset; | ||
712 | |||
713 | xpdMask = pEepData->modalHeader.xpdGain; | ||
714 | |||
715 | if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
716 | AR5416_EEP_MINOR_VER_2) { | ||
717 | pdGainOverlap_t2 = | ||
718 | pEepData->modalHeader.pdGainOverlap; | ||
719 | } else { | ||
720 | pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), | ||
721 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); | ||
722 | } | ||
723 | |||
724 | pCalBChans = pEepData->calFreqPier2G; | ||
725 | numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS; | ||
726 | |||
727 | numXpdGain = 0; | ||
728 | |||
729 | for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) { | ||
730 | if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) { | ||
731 | if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS) | ||
732 | break; | ||
733 | xpdGainValues[numXpdGain] = | ||
734 | (u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i); | ||
735 | numXpdGain++; | ||
736 | } | ||
737 | } | ||
738 | |||
739 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, | ||
740 | (numXpdGain - 1) & 0x3); | ||
741 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, | ||
742 | xpdGainValues[0]); | ||
743 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, | ||
744 | xpdGainValues[1]); | ||
745 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0); | ||
746 | |||
747 | for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { | ||
748 | if (AR_SREV_5416_20_OR_LATER(ah) && | ||
749 | (ah->rxchainmask == 5 || ah->txchainmask == 5) && | ||
750 | (i != 0)) { | ||
751 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; | ||
752 | } else | ||
753 | regChainOffset = i * 0x1000; | ||
754 | |||
755 | if (pEepData->baseEepHeader.txMask & (1 << i)) { | ||
756 | pRawDataset = pEepData->calPierData2G[i]; | ||
757 | |||
758 | ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan, | ||
759 | pRawDataset, pCalBChans, | ||
760 | numPiers, pdGainOverlap_t2, | ||
761 | &tMinCalPower, gainBoundaries, | ||
762 | pdadcValues, numXpdGain); | ||
763 | |||
764 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { | ||
765 | REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, | ||
766 | SM(pdGainOverlap_t2, | ||
767 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | ||
768 | | SM(gainBoundaries[0], | ||
769 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | ||
770 | | SM(gainBoundaries[1], | ||
771 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | ||
772 | | SM(gainBoundaries[2], | ||
773 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | ||
774 | | SM(gainBoundaries[3], | ||
775 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); | ||
776 | } | ||
777 | |||
778 | regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; | ||
779 | for (j = 0; j < 32; j++) { | ||
780 | reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) | | ||
781 | ((pdadcValues[4 * j + 1] & 0xFF) << 8) | | ||
782 | ((pdadcValues[4 * j + 2] & 0xFF) << 16)| | ||
783 | ((pdadcValues[4 * j + 3] & 0xFF) << 24); | ||
784 | REG_WRITE(ah, regOffset, reg32); | ||
785 | |||
786 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
787 | "PDADC (%d,%4x): %4.4x %8.8x\n", | ||
788 | i, regChainOffset, regOffset, | ||
789 | reg32); | ||
790 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
791 | "PDADC: Chain %d | " | ||
792 | "PDADC %3d Value %3d | " | ||
793 | "PDADC %3d Value %3d | " | ||
794 | "PDADC %3d Value %3d | " | ||
795 | "PDADC %3d Value %3d |\n", | ||
796 | i, 4 * j, pdadcValues[4 * j], | ||
797 | 4 * j + 1, pdadcValues[4 * j + 1], | ||
798 | 4 * j + 2, pdadcValues[4 * j + 2], | ||
799 | 4 * j + 3, | ||
800 | pdadcValues[4 * j + 3]); | ||
801 | |||
802 | regOffset += 4; | ||
803 | } | ||
804 | } | ||
805 | } | ||
806 | |||
807 | *pTxPowerIndexOffset = 0; | ||
808 | } | ||
809 | |||
810 | static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, | ||
811 | struct ath9k_channel *chan, | ||
812 | int16_t *ratesArray, | ||
813 | u16 cfgCtl, | ||
814 | u16 AntennaReduction, | ||
815 | u16 twiceMaxRegulatoryPower, | ||
816 | u16 powerLimit) | ||
817 | { | ||
818 | struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; | ||
819 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
820 | static const u16 tpScaleReductionTable[5] = | ||
821 | { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; | ||
822 | |||
823 | int i; | ||
824 | int16_t twiceLargestAntenna; | ||
825 | struct cal_ctl_data_4k *rep; | ||
826 | struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { | ||
827 | 0, { 0, 0, 0, 0} | ||
828 | }; | ||
829 | struct cal_target_power_leg targetPowerOfdmExt = { | ||
830 | 0, { 0, 0, 0, 0} }, targetPowerCckExt = { | ||
831 | 0, { 0, 0, 0, 0 } | ||
832 | }; | ||
833 | struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { | ||
834 | 0, {0, 0, 0, 0} | ||
835 | }; | ||
836 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; | ||
837 | u16 ctlModesFor11g[] = | ||
838 | { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, | ||
839 | CTL_2GHT40 | ||
840 | }; | ||
841 | u16 numCtlModes, *pCtlMode, ctlMode, freq; | ||
842 | struct chan_centers centers; | ||
843 | int tx_chainmask; | ||
844 | u16 twiceMinEdgePower; | ||
845 | |||
846 | tx_chainmask = ah->txchainmask; | ||
847 | |||
848 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
849 | |||
850 | twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0]; | ||
851 | |||
852 | twiceLargestAntenna = (int16_t)min(AntennaReduction - | ||
853 | twiceLargestAntenna, 0); | ||
854 | |||
855 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; | ||
856 | |||
857 | if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) { | ||
858 | maxRegAllowedPower -= | ||
859 | (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); | ||
860 | } | ||
861 | |||
862 | scaledPower = min(powerLimit, maxRegAllowedPower); | ||
863 | scaledPower = max((u16)0, scaledPower); | ||
864 | |||
865 | numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; | ||
866 | pCtlMode = ctlModesFor11g; | ||
867 | |||
868 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
869 | pEepData->calTargetPowerCck, | ||
870 | AR5416_NUM_2G_CCK_TARGET_POWERS, | ||
871 | &targetPowerCck, 4, false); | ||
872 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
873 | pEepData->calTargetPower2G, | ||
874 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
875 | &targetPowerOfdm, 4, false); | ||
876 | ath9k_hw_get_target_powers(ah, chan, | ||
877 | pEepData->calTargetPower2GHT20, | ||
878 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
879 | &targetPowerHt20, 8, false); | ||
880 | |||
881 | if (IS_CHAN_HT40(chan)) { | ||
882 | numCtlModes = ARRAY_SIZE(ctlModesFor11g); | ||
883 | ath9k_hw_get_target_powers(ah, chan, | ||
884 | pEepData->calTargetPower2GHT40, | ||
885 | AR5416_NUM_2G_40_TARGET_POWERS, | ||
886 | &targetPowerHt40, 8, true); | ||
887 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
888 | pEepData->calTargetPowerCck, | ||
889 | AR5416_NUM_2G_CCK_TARGET_POWERS, | ||
890 | &targetPowerCckExt, 4, true); | ||
891 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
892 | pEepData->calTargetPower2G, | ||
893 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
894 | &targetPowerOfdmExt, 4, true); | ||
895 | } | ||
896 | |||
897 | for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { | ||
898 | bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || | ||
899 | (pCtlMode[ctlMode] == CTL_2GHT40); | ||
900 | if (isHt40CtlMode) | ||
901 | freq = centers.synth_center; | ||
902 | else if (pCtlMode[ctlMode] & EXT_ADDITIVE) | ||
903 | freq = centers.ext_center; | ||
904 | else | ||
905 | freq = centers.ctl_center; | ||
906 | |||
907 | if (ah->eep_ops->get_eeprom_ver(ah) == 14 && | ||
908 | ah->eep_ops->get_eeprom_rev(ah) <= 2) | ||
909 | twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
910 | |||
911 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
912 | "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, " | ||
913 | "EXT_ADDITIVE %d\n", | ||
914 | ctlMode, numCtlModes, isHt40CtlMode, | ||
915 | (pCtlMode[ctlMode] & EXT_ADDITIVE)); | ||
916 | |||
917 | for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) && | ||
918 | pEepData->ctlIndex[i]; i++) { | ||
919 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
920 | " LOOP-Ctlidx %d: cfgCtl 0x%2.2x " | ||
921 | "pCtlMode 0x%2.2x ctlIndex 0x%2.2x " | ||
922 | "chan %d\n", | ||
923 | i, cfgCtl, pCtlMode[ctlMode], | ||
924 | pEepData->ctlIndex[i], chan->channel); | ||
925 | |||
926 | if ((((cfgCtl & ~CTL_MODE_M) | | ||
927 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
928 | pEepData->ctlIndex[i]) || | ||
929 | (((cfgCtl & ~CTL_MODE_M) | | ||
930 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
931 | ((pEepData->ctlIndex[i] & CTL_MODE_M) | | ||
932 | SD_NO_CTL))) { | ||
933 | rep = &(pEepData->ctlData[i]); | ||
934 | |||
935 | twiceMinEdgePower = | ||
936 | ath9k_hw_get_max_edge_power(freq, | ||
937 | rep->ctlEdges[ar5416_get_ntxchains | ||
938 | (tx_chainmask) - 1], | ||
939 | IS_CHAN_2GHZ(chan), | ||
940 | AR5416_EEP4K_NUM_BAND_EDGES); | ||
941 | |||
942 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
943 | " MATCH-EE_IDX %d: ch %d is2 %d " | ||
944 | "2xMinEdge %d chainmask %d chains %d\n", | ||
945 | i, freq, IS_CHAN_2GHZ(chan), | ||
946 | twiceMinEdgePower, tx_chainmask, | ||
947 | ar5416_get_ntxchains | ||
948 | (tx_chainmask)); | ||
949 | if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { | ||
950 | twiceMaxEdgePower = | ||
951 | min(twiceMaxEdgePower, | ||
952 | twiceMinEdgePower); | ||
953 | } else { | ||
954 | twiceMaxEdgePower = twiceMinEdgePower; | ||
955 | break; | ||
956 | } | ||
957 | } | ||
958 | } | ||
959 | |||
960 | minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); | ||
961 | |||
962 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
963 | " SEL-Min ctlMode %d pCtlMode %d " | ||
964 | "2xMaxEdge %d sP %d minCtlPwr %d\n", | ||
965 | ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, | ||
966 | scaledPower, minCtlPower); | ||
967 | |||
968 | switch (pCtlMode[ctlMode]) { | ||
969 | case CTL_11B: | ||
970 | for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); | ||
971 | i++) { | ||
972 | targetPowerCck.tPow2x[i] = | ||
973 | min((u16)targetPowerCck.tPow2x[i], | ||
974 | minCtlPower); | ||
975 | } | ||
976 | break; | ||
977 | case CTL_11G: | ||
978 | for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); | ||
979 | i++) { | ||
980 | targetPowerOfdm.tPow2x[i] = | ||
981 | min((u16)targetPowerOfdm.tPow2x[i], | ||
982 | minCtlPower); | ||
983 | } | ||
984 | break; | ||
985 | case CTL_2GHT20: | ||
986 | for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); | ||
987 | i++) { | ||
988 | targetPowerHt20.tPow2x[i] = | ||
989 | min((u16)targetPowerHt20.tPow2x[i], | ||
990 | minCtlPower); | ||
991 | } | ||
992 | break; | ||
993 | case CTL_11B_EXT: | ||
994 | targetPowerCckExt.tPow2x[0] = min((u16) | ||
995 | targetPowerCckExt.tPow2x[0], | ||
996 | minCtlPower); | ||
997 | break; | ||
998 | case CTL_11G_EXT: | ||
999 | targetPowerOfdmExt.tPow2x[0] = min((u16) | ||
1000 | targetPowerOfdmExt.tPow2x[0], | ||
1001 | minCtlPower); | ||
1002 | break; | ||
1003 | case CTL_2GHT40: | ||
1004 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); | ||
1005 | i++) { | ||
1006 | targetPowerHt40.tPow2x[i] = | ||
1007 | min((u16)targetPowerHt40.tPow2x[i], | ||
1008 | minCtlPower); | ||
1009 | } | ||
1010 | break; | ||
1011 | default: | ||
1012 | break; | ||
1013 | } | ||
1014 | } | ||
1015 | |||
1016 | ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = | ||
1017 | ratesArray[rate18mb] = ratesArray[rate24mb] = | ||
1018 | targetPowerOfdm.tPow2x[0]; | ||
1019 | ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; | ||
1020 | ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; | ||
1021 | ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; | ||
1022 | ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; | ||
1023 | |||
1024 | for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) | ||
1025 | ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; | ||
1026 | |||
1027 | ratesArray[rate1l] = targetPowerCck.tPow2x[0]; | ||
1028 | ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1]; | ||
1029 | ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2]; | ||
1030 | ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3]; | ||
1031 | |||
1032 | if (IS_CHAN_HT40(chan)) { | ||
1033 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { | ||
1034 | ratesArray[rateHt40_0 + i] = | ||
1035 | targetPowerHt40.tPow2x[i]; | ||
1036 | } | ||
1037 | ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; | ||
1038 | ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; | ||
1039 | ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; | ||
1040 | ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; | ||
1041 | } | ||
1042 | } | ||
1043 | |||
1044 | static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, | ||
1045 | struct ath9k_channel *chan, | ||
1046 | u16 cfgCtl, | ||
1047 | u8 twiceAntennaReduction, | ||
1048 | u8 twiceMaxRegulatoryPower, | ||
1049 | u8 powerLimit) | ||
1050 | { | ||
1051 | struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; | ||
1052 | struct modal_eep_4k_header *pModal = &pEepData->modalHeader; | ||
1053 | int16_t ratesArray[Ar5416RateSize]; | ||
1054 | int16_t txPowerIndexOffset = 0; | ||
1055 | u8 ht40PowerIncForPdadc = 2; | ||
1056 | int i; | ||
1057 | |||
1058 | memset(ratesArray, 0, sizeof(ratesArray)); | ||
1059 | |||
1060 | if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
1061 | AR5416_EEP_MINOR_VER_2) { | ||
1062 | ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; | ||
1063 | } | ||
1064 | |||
1065 | ath9k_hw_set_4k_power_per_rate_table(ah, chan, | ||
1066 | &ratesArray[0], cfgCtl, | ||
1067 | twiceAntennaReduction, | ||
1068 | twiceMaxRegulatoryPower, | ||
1069 | powerLimit); | ||
1070 | |||
1071 | ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset); | ||
1072 | |||
1073 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { | ||
1074 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); | ||
1075 | if (ratesArray[i] > AR5416_MAX_RATE_POWER) | ||
1076 | ratesArray[i] = AR5416_MAX_RATE_POWER; | ||
1077 | } | ||
1078 | |||
1079 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
1080 | for (i = 0; i < Ar5416RateSize; i++) | ||
1081 | ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2; | ||
1082 | } | ||
1083 | |||
1084 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, | ||
1085 | ATH9K_POW_SM(ratesArray[rate18mb], 24) | ||
1086 | | ATH9K_POW_SM(ratesArray[rate12mb], 16) | ||
1087 | | ATH9K_POW_SM(ratesArray[rate9mb], 8) | ||
1088 | | ATH9K_POW_SM(ratesArray[rate6mb], 0)); | ||
1089 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, | ||
1090 | ATH9K_POW_SM(ratesArray[rate54mb], 24) | ||
1091 | | ATH9K_POW_SM(ratesArray[rate48mb], 16) | ||
1092 | | ATH9K_POW_SM(ratesArray[rate36mb], 8) | ||
1093 | | ATH9K_POW_SM(ratesArray[rate24mb], 0)); | ||
1094 | |||
1095 | if (IS_CHAN_2GHZ(chan)) { | ||
1096 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, | ||
1097 | ATH9K_POW_SM(ratesArray[rate2s], 24) | ||
1098 | | ATH9K_POW_SM(ratesArray[rate2l], 16) | ||
1099 | | ATH9K_POW_SM(ratesArray[rateXr], 8) | ||
1100 | | ATH9K_POW_SM(ratesArray[rate1l], 0)); | ||
1101 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, | ||
1102 | ATH9K_POW_SM(ratesArray[rate11s], 24) | ||
1103 | | ATH9K_POW_SM(ratesArray[rate11l], 16) | ||
1104 | | ATH9K_POW_SM(ratesArray[rate5_5s], 8) | ||
1105 | | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); | ||
1106 | } | ||
1107 | |||
1108 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, | ||
1109 | ATH9K_POW_SM(ratesArray[rateHt20_3], 24) | ||
1110 | | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) | ||
1111 | | ATH9K_POW_SM(ratesArray[rateHt20_1], 8) | ||
1112 | | ATH9K_POW_SM(ratesArray[rateHt20_0], 0)); | ||
1113 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, | ||
1114 | ATH9K_POW_SM(ratesArray[rateHt20_7], 24) | ||
1115 | | ATH9K_POW_SM(ratesArray[rateHt20_6], 16) | ||
1116 | | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) | ||
1117 | | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); | ||
1118 | |||
1119 | if (IS_CHAN_HT40(chan)) { | ||
1120 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, | ||
1121 | ATH9K_POW_SM(ratesArray[rateHt40_3] + | ||
1122 | ht40PowerIncForPdadc, 24) | ||
1123 | | ATH9K_POW_SM(ratesArray[rateHt40_2] + | ||
1124 | ht40PowerIncForPdadc, 16) | ||
1125 | | ATH9K_POW_SM(ratesArray[rateHt40_1] + | ||
1126 | ht40PowerIncForPdadc, 8) | ||
1127 | | ATH9K_POW_SM(ratesArray[rateHt40_0] + | ||
1128 | ht40PowerIncForPdadc, 0)); | ||
1129 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, | ||
1130 | ATH9K_POW_SM(ratesArray[rateHt40_7] + | ||
1131 | ht40PowerIncForPdadc, 24) | ||
1132 | | ATH9K_POW_SM(ratesArray[rateHt40_6] + | ||
1133 | ht40PowerIncForPdadc, 16) | ||
1134 | | ATH9K_POW_SM(ratesArray[rateHt40_5] + | ||
1135 | ht40PowerIncForPdadc, 8) | ||
1136 | | ATH9K_POW_SM(ratesArray[rateHt40_4] + | ||
1137 | ht40PowerIncForPdadc, 0)); | ||
1138 | |||
1139 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, | ||
1140 | ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) | ||
1141 | | ATH9K_POW_SM(ratesArray[rateExtCck], 16) | ||
1142 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | ||
1143 | | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); | ||
1144 | } | ||
1145 | |||
1146 | i = rate6mb; | ||
1147 | |||
1148 | if (IS_CHAN_HT40(chan)) | ||
1149 | i = rateHt40_0; | ||
1150 | else if (IS_CHAN_HT20(chan)) | ||
1151 | i = rateHt20_0; | ||
1152 | |||
1153 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
1154 | ah->regulatory.max_power_level = | ||
1155 | ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2; | ||
1156 | else | ||
1157 | ah->regulatory.max_power_level = ratesArray[i]; | ||
1158 | |||
1159 | } | ||
1160 | |||
1161 | static void ath9k_hw_4k_set_addac(struct ath_hw *ah, | ||
1162 | struct ath9k_channel *chan) | ||
1163 | { | ||
1164 | struct modal_eep_4k_header *pModal; | ||
1165 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | ||
1166 | u8 biaslevel; | ||
1167 | |||
1168 | if (ah->hw_version.macVersion != AR_SREV_VERSION_9160) | ||
1169 | return; | ||
1170 | |||
1171 | if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7) | ||
1172 | return; | ||
1173 | |||
1174 | pModal = &eep->modalHeader; | ||
1175 | |||
1176 | if (pModal->xpaBiasLvl != 0xff) { | ||
1177 | biaslevel = pModal->xpaBiasLvl; | ||
1178 | INI_RA(&ah->iniAddac, 7, 1) = | ||
1179 | (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3; | ||
1180 | } | ||
1181 | } | ||
1182 | |||
1183 | static void ath9k_hw_4k_set_gain(struct ath_hw *ah, | ||
1184 | struct modal_eep_4k_header *pModal, | ||
1185 | struct ar5416_eeprom_4k *eep, | ||
1186 | u8 txRxAttenLocal, int regChainOffset) | ||
1187 | { | ||
1188 | REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, | ||
1189 | pModal->antCtrlChain[0]); | ||
1190 | |||
1191 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, | ||
1192 | (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) & | ||
1193 | ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | | ||
1194 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | | ||
1195 | SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | | ||
1196 | SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); | ||
1197 | |||
1198 | if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
1199 | AR5416_EEP_MINOR_VER_3) { | ||
1200 | txRxAttenLocal = pModal->txRxAttenCh[0]; | ||
1201 | |||
1202 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1203 | AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]); | ||
1204 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1205 | AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); | ||
1206 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1207 | AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, | ||
1208 | pModal->xatten2Margin[0]); | ||
1209 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1210 | AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]); | ||
1211 | |||
1212 | /* Set the block 1 value to block 0 value */ | ||
1213 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, | ||
1214 | AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, | ||
1215 | pModal->bswMargin[0]); | ||
1216 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, | ||
1217 | AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); | ||
1218 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, | ||
1219 | AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, | ||
1220 | pModal->xatten2Margin[0]); | ||
1221 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, | ||
1222 | AR_PHY_GAIN_2GHZ_XATTEN2_DB, | ||
1223 | pModal->xatten2Db[0]); | ||
1224 | } | ||
1225 | |||
1226 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, | ||
1227 | AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); | ||
1228 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, | ||
1229 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); | ||
1230 | |||
1231 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, | ||
1232 | AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); | ||
1233 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, | ||
1234 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); | ||
1235 | |||
1236 | if (AR_SREV_9285_11(ah)) | ||
1237 | REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); | ||
1238 | } | ||
1239 | |||
1240 | /* | ||
1241 | * Read EEPROM header info and program the device for correct operation | ||
1242 | * given the channel value. | ||
1243 | */ | ||
1244 | static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | ||
1245 | struct ath9k_channel *chan) | ||
1246 | { | ||
1247 | struct modal_eep_4k_header *pModal; | ||
1248 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | ||
1249 | u8 txRxAttenLocal; | ||
1250 | u8 ob[5], db1[5], db2[5]; | ||
1251 | u8 ant_div_control1, ant_div_control2; | ||
1252 | u32 regVal; | ||
1253 | |||
1254 | pModal = &eep->modalHeader; | ||
1255 | txRxAttenLocal = 23; | ||
1256 | |||
1257 | REG_WRITE(ah, AR_PHY_SWITCH_COM, | ||
1258 | ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); | ||
1259 | |||
1260 | /* Single chain for 4K EEPROM*/ | ||
1261 | ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal, 0); | ||
1262 | |||
1263 | /* Initialize Ant Diversity settings from EEPROM */ | ||
1264 | if (pModal->version >= 3) { | ||
1265 | ant_div_control1 = ((pModal->ob_234 >> 12) & 0xf); | ||
1266 | ant_div_control2 = ((pModal->db1_234 >> 12) & 0xf); | ||
1267 | regVal = REG_READ(ah, 0x99ac); | ||
1268 | regVal &= (~(0x7f000000)); | ||
1269 | regVal |= ((ant_div_control1 & 0x1) << 24); | ||
1270 | regVal |= (((ant_div_control1 >> 1) & 0x1) << 29); | ||
1271 | regVal |= (((ant_div_control1 >> 2) & 0x1) << 30); | ||
1272 | regVal |= ((ant_div_control2 & 0x3) << 25); | ||
1273 | regVal |= (((ant_div_control2 >> 2) & 0x3) << 27); | ||
1274 | REG_WRITE(ah, 0x99ac, regVal); | ||
1275 | regVal = REG_READ(ah, 0x99ac); | ||
1276 | regVal = REG_READ(ah, 0xa208); | ||
1277 | regVal &= (~(0x1 << 13)); | ||
1278 | regVal |= (((ant_div_control1 >> 3) & 0x1) << 13); | ||
1279 | REG_WRITE(ah, 0xa208, regVal); | ||
1280 | regVal = REG_READ(ah, 0xa208); | ||
1281 | } | ||
1282 | |||
1283 | if (pModal->version >= 2) { | ||
1284 | ob[0] = (pModal->ob_01 & 0xf); | ||
1285 | ob[1] = (pModal->ob_01 >> 4) & 0xf; | ||
1286 | ob[2] = (pModal->ob_234 & 0xf); | ||
1287 | ob[3] = ((pModal->ob_234 >> 4) & 0xf); | ||
1288 | ob[4] = ((pModal->ob_234 >> 8) & 0xf); | ||
1289 | |||
1290 | db1[0] = (pModal->db1_01 & 0xf); | ||
1291 | db1[1] = ((pModal->db1_01 >> 4) & 0xf); | ||
1292 | db1[2] = (pModal->db1_234 & 0xf); | ||
1293 | db1[3] = ((pModal->db1_234 >> 4) & 0xf); | ||
1294 | db1[4] = ((pModal->db1_234 >> 8) & 0xf); | ||
1295 | |||
1296 | db2[0] = (pModal->db2_01 & 0xf); | ||
1297 | db2[1] = ((pModal->db2_01 >> 4) & 0xf); | ||
1298 | db2[2] = (pModal->db2_234 & 0xf); | ||
1299 | db2[3] = ((pModal->db2_234 >> 4) & 0xf); | ||
1300 | db2[4] = ((pModal->db2_234 >> 8) & 0xf); | ||
1301 | |||
1302 | } else if (pModal->version == 1) { | ||
1303 | ob[0] = (pModal->ob_01 & 0xf); | ||
1304 | ob[1] = ob[2] = ob[3] = ob[4] = (pModal->ob_01 >> 4) & 0xf; | ||
1305 | db1[0] = (pModal->db1_01 & 0xf); | ||
1306 | db1[1] = db1[2] = db1[3] = | ||
1307 | db1[4] = ((pModal->db1_01 >> 4) & 0xf); | ||
1308 | db2[0] = (pModal->db2_01 & 0xf); | ||
1309 | db2[1] = db2[2] = db2[3] = | ||
1310 | db2[4] = ((pModal->db2_01 >> 4) & 0xf); | ||
1311 | } else { | ||
1312 | int i; | ||
1313 | for (i = 0; i < 5; i++) { | ||
1314 | ob[i] = pModal->ob_01; | ||
1315 | db1[i] = pModal->db1_01; | ||
1316 | db2[i] = pModal->db1_01; | ||
1317 | } | ||
1318 | } | ||
1319 | |||
1320 | if (AR_SREV_9271(ah)) { | ||
1321 | ath9k_hw_analog_shift_rmw(ah, | ||
1322 | AR9285_AN_RF2G3, | ||
1323 | AR9271_AN_RF2G3_OB_cck, | ||
1324 | AR9271_AN_RF2G3_OB_cck_S, | ||
1325 | ob[0]); | ||
1326 | ath9k_hw_analog_shift_rmw(ah, | ||
1327 | AR9285_AN_RF2G3, | ||
1328 | AR9271_AN_RF2G3_OB_psk, | ||
1329 | AR9271_AN_RF2G3_OB_psk_S, | ||
1330 | ob[1]); | ||
1331 | ath9k_hw_analog_shift_rmw(ah, | ||
1332 | AR9285_AN_RF2G3, | ||
1333 | AR9271_AN_RF2G3_OB_qam, | ||
1334 | AR9271_AN_RF2G3_OB_qam_S, | ||
1335 | ob[2]); | ||
1336 | ath9k_hw_analog_shift_rmw(ah, | ||
1337 | AR9285_AN_RF2G3, | ||
1338 | AR9271_AN_RF2G3_DB_1, | ||
1339 | AR9271_AN_RF2G3_DB_1_S, | ||
1340 | db1[0]); | ||
1341 | ath9k_hw_analog_shift_rmw(ah, | ||
1342 | AR9285_AN_RF2G4, | ||
1343 | AR9271_AN_RF2G4_DB_2, | ||
1344 | AR9271_AN_RF2G4_DB_2_S, | ||
1345 | db2[0]); | ||
1346 | } else { | ||
1347 | ath9k_hw_analog_shift_rmw(ah, | ||
1348 | AR9285_AN_RF2G3, | ||
1349 | AR9285_AN_RF2G3_OB_0, | ||
1350 | AR9285_AN_RF2G3_OB_0_S, | ||
1351 | ob[0]); | ||
1352 | ath9k_hw_analog_shift_rmw(ah, | ||
1353 | AR9285_AN_RF2G3, | ||
1354 | AR9285_AN_RF2G3_OB_1, | ||
1355 | AR9285_AN_RF2G3_OB_1_S, | ||
1356 | ob[1]); | ||
1357 | ath9k_hw_analog_shift_rmw(ah, | ||
1358 | AR9285_AN_RF2G3, | ||
1359 | AR9285_AN_RF2G3_OB_2, | ||
1360 | AR9285_AN_RF2G3_OB_2_S, | ||
1361 | ob[2]); | ||
1362 | ath9k_hw_analog_shift_rmw(ah, | ||
1363 | AR9285_AN_RF2G3, | ||
1364 | AR9285_AN_RF2G3_OB_3, | ||
1365 | AR9285_AN_RF2G3_OB_3_S, | ||
1366 | ob[3]); | ||
1367 | ath9k_hw_analog_shift_rmw(ah, | ||
1368 | AR9285_AN_RF2G3, | ||
1369 | AR9285_AN_RF2G3_OB_4, | ||
1370 | AR9285_AN_RF2G3_OB_4_S, | ||
1371 | ob[4]); | ||
1372 | |||
1373 | ath9k_hw_analog_shift_rmw(ah, | ||
1374 | AR9285_AN_RF2G3, | ||
1375 | AR9285_AN_RF2G3_DB1_0, | ||
1376 | AR9285_AN_RF2G3_DB1_0_S, | ||
1377 | db1[0]); | ||
1378 | ath9k_hw_analog_shift_rmw(ah, | ||
1379 | AR9285_AN_RF2G3, | ||
1380 | AR9285_AN_RF2G3_DB1_1, | ||
1381 | AR9285_AN_RF2G3_DB1_1_S, | ||
1382 | db1[1]); | ||
1383 | ath9k_hw_analog_shift_rmw(ah, | ||
1384 | AR9285_AN_RF2G3, | ||
1385 | AR9285_AN_RF2G3_DB1_2, | ||
1386 | AR9285_AN_RF2G3_DB1_2_S, | ||
1387 | db1[2]); | ||
1388 | ath9k_hw_analog_shift_rmw(ah, | ||
1389 | AR9285_AN_RF2G4, | ||
1390 | AR9285_AN_RF2G4_DB1_3, | ||
1391 | AR9285_AN_RF2G4_DB1_3_S, | ||
1392 | db1[3]); | ||
1393 | ath9k_hw_analog_shift_rmw(ah, | ||
1394 | AR9285_AN_RF2G4, | ||
1395 | AR9285_AN_RF2G4_DB1_4, | ||
1396 | AR9285_AN_RF2G4_DB1_4_S, db1[4]); | ||
1397 | |||
1398 | ath9k_hw_analog_shift_rmw(ah, | ||
1399 | AR9285_AN_RF2G4, | ||
1400 | AR9285_AN_RF2G4_DB2_0, | ||
1401 | AR9285_AN_RF2G4_DB2_0_S, | ||
1402 | db2[0]); | ||
1403 | ath9k_hw_analog_shift_rmw(ah, | ||
1404 | AR9285_AN_RF2G4, | ||
1405 | AR9285_AN_RF2G4_DB2_1, | ||
1406 | AR9285_AN_RF2G4_DB2_1_S, | ||
1407 | db2[1]); | ||
1408 | ath9k_hw_analog_shift_rmw(ah, | ||
1409 | AR9285_AN_RF2G4, | ||
1410 | AR9285_AN_RF2G4_DB2_2, | ||
1411 | AR9285_AN_RF2G4_DB2_2_S, | ||
1412 | db2[2]); | ||
1413 | ath9k_hw_analog_shift_rmw(ah, | ||
1414 | AR9285_AN_RF2G4, | ||
1415 | AR9285_AN_RF2G4_DB2_3, | ||
1416 | AR9285_AN_RF2G4_DB2_3_S, | ||
1417 | db2[3]); | ||
1418 | ath9k_hw_analog_shift_rmw(ah, | ||
1419 | AR9285_AN_RF2G4, | ||
1420 | AR9285_AN_RF2G4_DB2_4, | ||
1421 | AR9285_AN_RF2G4_DB2_4_S, | ||
1422 | db2[4]); | ||
1423 | } | ||
1424 | |||
1425 | |||
1426 | if (AR_SREV_9285_11(ah)) | ||
1427 | REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); | ||
1428 | |||
1429 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, | ||
1430 | pModal->switchSettling); | ||
1431 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, | ||
1432 | pModal->adcDesiredSize); | ||
1433 | |||
1434 | REG_WRITE(ah, AR_PHY_RF_CTL4, | ||
1435 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) | | ||
1436 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) | | ||
1437 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) | | ||
1438 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); | ||
1439 | |||
1440 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, | ||
1441 | pModal->txEndToRxOn); | ||
1442 | REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, | ||
1443 | pModal->thresh62); | ||
1444 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62, | ||
1445 | pModal->thresh62); | ||
1446 | |||
1447 | if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
1448 | AR5416_EEP_MINOR_VER_2) { | ||
1449 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START, | ||
1450 | pModal->txFrameToDataStart); | ||
1451 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON, | ||
1452 | pModal->txFrameToPaOn); | ||
1453 | } | ||
1454 | |||
1455 | if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
1456 | AR5416_EEP_MINOR_VER_3) { | ||
1457 | if (IS_CHAN_HT40(chan)) | ||
1458 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, | ||
1459 | AR_PHY_SETTLING_SWITCH, | ||
1460 | pModal->swSettleHt40); | ||
1461 | } | ||
1462 | } | ||
1463 | |||
1464 | static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah, | ||
1465 | struct ath9k_channel *chan) | ||
1466 | { | ||
1467 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | ||
1468 | struct modal_eep_4k_header *pModal = &eep->modalHeader; | ||
1469 | |||
1470 | return pModal->antCtrlCommon & 0xFFFF; | ||
1471 | } | ||
1472 | |||
1473 | static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah, | ||
1474 | enum ieee80211_band freq_band) | ||
1475 | { | ||
1476 | return 1; | ||
1477 | } | ||
1478 | |||
1479 | static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) | ||
1480 | { | ||
1481 | #define EEP_MAP4K_SPURCHAN \ | ||
1482 | (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan) | ||
1483 | |||
1484 | u16 spur_val = AR_NO_SPUR; | ||
1485 | |||
1486 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
1487 | "Getting spur idx %d is2Ghz. %d val %x\n", | ||
1488 | i, is2GHz, ah->config.spurchans[i][is2GHz]); | ||
1489 | |||
1490 | switch (ah->config.spurmode) { | ||
1491 | case SPUR_DISABLE: | ||
1492 | break; | ||
1493 | case SPUR_ENABLE_IOCTL: | ||
1494 | spur_val = ah->config.spurchans[i][is2GHz]; | ||
1495 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
1496 | "Getting spur val from new loc. %d\n", spur_val); | ||
1497 | break; | ||
1498 | case SPUR_ENABLE_EEPROM: | ||
1499 | spur_val = EEP_MAP4K_SPURCHAN; | ||
1500 | break; | ||
1501 | } | ||
1502 | |||
1503 | return spur_val; | ||
1504 | |||
1505 | #undef EEP_MAP4K_SPURCHAN | ||
1506 | } | ||
1507 | |||
1508 | static struct eeprom_ops eep_4k_ops = { | ||
1509 | .check_eeprom = ath9k_hw_4k_check_eeprom, | ||
1510 | .get_eeprom = ath9k_hw_4k_get_eeprom, | ||
1511 | .fill_eeprom = ath9k_hw_4k_fill_eeprom, | ||
1512 | .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver, | ||
1513 | .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev, | ||
1514 | .get_num_ant_config = ath9k_hw_4k_get_num_ant_config, | ||
1515 | .get_eeprom_antenna_cfg = ath9k_hw_4k_get_eeprom_antenna_cfg, | ||
1516 | .set_board_values = ath9k_hw_4k_set_board_values, | ||
1517 | .set_addac = ath9k_hw_4k_set_addac, | ||
1518 | .set_txpower = ath9k_hw_4k_set_txpower, | ||
1519 | .get_spur_channel = ath9k_hw_4k_get_spur_channel | ||
1520 | }; | ||
1521 | |||
1522 | /************************************************/ | ||
1523 | /* EEPROM Operations for non-4K (Default) cards */ | ||
1524 | /************************************************/ | ||
1525 | |||
1526 | static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah) | ||
1527 | { | ||
1528 | return ((ah->eeprom.def.baseEepHeader.version >> 12) & 0xF); | ||
1529 | } | ||
1530 | |||
1531 | static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah) | ||
1532 | { | ||
1533 | return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF); | ||
1534 | } | ||
1535 | |||
1536 | static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) | ||
1537 | { | ||
1538 | #define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16)) | ||
1539 | u16 *eep_data = (u16 *)&ah->eeprom.def; | ||
1540 | int addr, ar5416_eep_start_loc = 0x100; | ||
1541 | |||
1542 | for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) { | ||
1543 | if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc, | ||
1544 | eep_data)) { | ||
1545 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
1546 | "Unable to read eeprom region\n"); | ||
1547 | return false; | ||
1548 | } | ||
1549 | eep_data++; | ||
1550 | } | ||
1551 | return true; | ||
1552 | #undef SIZE_EEPROM_DEF | ||
1553 | } | ||
1554 | |||
1555 | static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | ||
1556 | { | ||
1557 | struct ar5416_eeprom_def *eep = | ||
1558 | (struct ar5416_eeprom_def *) &ah->eeprom.def; | ||
1559 | u16 *eepdata, temp, magic, magic2; | ||
1560 | u32 sum = 0, el; | ||
1561 | bool need_swap = false; | ||
1562 | int i, addr, size; | ||
1563 | |||
1564 | if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { | ||
1565 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Reading Magic # failed\n"); | ||
1566 | return false; | ||
1567 | } | ||
1568 | |||
1569 | if (!ath9k_hw_use_flash(ah)) { | ||
1570 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
1571 | "Read Magic = 0x%04X\n", magic); | ||
1572 | |||
1573 | if (magic != AR5416_EEPROM_MAGIC) { | ||
1574 | magic2 = swab16(magic); | ||
1575 | |||
1576 | if (magic2 == AR5416_EEPROM_MAGIC) { | ||
1577 | size = sizeof(struct ar5416_eeprom_def); | ||
1578 | need_swap = true; | ||
1579 | eepdata = (u16 *) (&ah->eeprom); | ||
1580 | |||
1581 | for (addr = 0; addr < size / sizeof(u16); addr++) { | ||
1582 | temp = swab16(*eepdata); | ||
1583 | *eepdata = temp; | ||
1584 | eepdata++; | ||
1585 | } | ||
1586 | } else { | ||
1587 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
1588 | "Invalid EEPROM Magic. " | ||
1589 | "Endianness mismatch.\n"); | ||
1590 | return -EINVAL; | ||
1591 | } | ||
1592 | } | ||
1593 | } | ||
1594 | |||
1595 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", | ||
1596 | need_swap ? "True" : "False"); | ||
1597 | |||
1598 | if (need_swap) | ||
1599 | el = swab16(ah->eeprom.def.baseEepHeader.length); | ||
1600 | else | ||
1601 | el = ah->eeprom.def.baseEepHeader.length; | ||
1602 | |||
1603 | if (el > sizeof(struct ar5416_eeprom_def)) | ||
1604 | el = sizeof(struct ar5416_eeprom_def) / sizeof(u16); | ||
1605 | else | ||
1606 | el = el / sizeof(u16); | ||
1607 | |||
1608 | eepdata = (u16 *)(&ah->eeprom); | ||
1609 | |||
1610 | for (i = 0; i < el; i++) | ||
1611 | sum ^= *eepdata++; | ||
1612 | |||
1613 | if (need_swap) { | ||
1614 | u32 integer, j; | ||
1615 | u16 word; | ||
1616 | |||
1617 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
1618 | "EEPROM Endianness is not native.. Changing.\n"); | ||
1619 | |||
1620 | word = swab16(eep->baseEepHeader.length); | ||
1621 | eep->baseEepHeader.length = word; | ||
1622 | |||
1623 | word = swab16(eep->baseEepHeader.checksum); | ||
1624 | eep->baseEepHeader.checksum = word; | ||
1625 | |||
1626 | word = swab16(eep->baseEepHeader.version); | ||
1627 | eep->baseEepHeader.version = word; | ||
1628 | |||
1629 | word = swab16(eep->baseEepHeader.regDmn[0]); | ||
1630 | eep->baseEepHeader.regDmn[0] = word; | ||
1631 | |||
1632 | word = swab16(eep->baseEepHeader.regDmn[1]); | ||
1633 | eep->baseEepHeader.regDmn[1] = word; | ||
1634 | |||
1635 | word = swab16(eep->baseEepHeader.rfSilent); | ||
1636 | eep->baseEepHeader.rfSilent = word; | ||
1637 | |||
1638 | word = swab16(eep->baseEepHeader.blueToothOptions); | ||
1639 | eep->baseEepHeader.blueToothOptions = word; | ||
1640 | |||
1641 | word = swab16(eep->baseEepHeader.deviceCap); | ||
1642 | eep->baseEepHeader.deviceCap = word; | ||
1643 | |||
1644 | for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) { | ||
1645 | struct modal_eep_header *pModal = | ||
1646 | &eep->modalHeader[j]; | ||
1647 | integer = swab32(pModal->antCtrlCommon); | ||
1648 | pModal->antCtrlCommon = integer; | ||
1649 | |||
1650 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
1651 | integer = swab32(pModal->antCtrlChain[i]); | ||
1652 | pModal->antCtrlChain[i] = integer; | ||
1653 | } | ||
1654 | |||
1655 | for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { | ||
1656 | word = swab16(pModal->spurChans[i].spurChan); | ||
1657 | pModal->spurChans[i].spurChan = word; | ||
1658 | } | ||
1659 | } | ||
1660 | } | ||
1661 | |||
1662 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || | ||
1663 | ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { | ||
1664 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
1665 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | ||
1666 | sum, ah->eep_ops->get_eeprom_ver(ah)); | ||
1667 | return -EINVAL; | ||
1668 | } | ||
1669 | |||
1670 | return 0; | ||
1671 | } | ||
1672 | |||
1673 | static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, | ||
1674 | enum eeprom_param param) | ||
1675 | { | ||
1676 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; | ||
1677 | struct modal_eep_header *pModal = eep->modalHeader; | ||
1678 | struct base_eep_header *pBase = &eep->baseEepHeader; | ||
1679 | |||
1680 | switch (param) { | ||
1681 | case EEP_NFTHRESH_5: | ||
1682 | return pModal[0].noiseFloorThreshCh[0]; | ||
1683 | case EEP_NFTHRESH_2: | ||
1684 | return pModal[1].noiseFloorThreshCh[0]; | ||
1685 | case AR_EEPROM_MAC(0): | ||
1686 | return pBase->macAddr[0] << 8 | pBase->macAddr[1]; | ||
1687 | case AR_EEPROM_MAC(1): | ||
1688 | return pBase->macAddr[2] << 8 | pBase->macAddr[3]; | ||
1689 | case AR_EEPROM_MAC(2): | ||
1690 | return pBase->macAddr[4] << 8 | pBase->macAddr[5]; | ||
1691 | case EEP_REG_0: | ||
1692 | return pBase->regDmn[0]; | ||
1693 | case EEP_REG_1: | ||
1694 | return pBase->regDmn[1]; | ||
1695 | case EEP_OP_CAP: | ||
1696 | return pBase->deviceCap; | ||
1697 | case EEP_OP_MODE: | ||
1698 | return pBase->opCapFlags; | ||
1699 | case EEP_RF_SILENT: | ||
1700 | return pBase->rfSilent; | ||
1701 | case EEP_OB_5: | ||
1702 | return pModal[0].ob; | ||
1703 | case EEP_DB_5: | ||
1704 | return pModal[0].db; | ||
1705 | case EEP_OB_2: | ||
1706 | return pModal[1].ob; | ||
1707 | case EEP_DB_2: | ||
1708 | return pModal[1].db; | ||
1709 | case EEP_MINOR_REV: | ||
1710 | return AR5416_VER_MASK; | ||
1711 | case EEP_TX_MASK: | ||
1712 | return pBase->txMask; | ||
1713 | case EEP_RX_MASK: | ||
1714 | return pBase->rxMask; | ||
1715 | case EEP_RXGAIN_TYPE: | ||
1716 | return pBase->rxGainType; | ||
1717 | case EEP_TXGAIN_TYPE: | ||
1718 | return pBase->txGainType; | ||
1719 | case EEP_OL_PWRCTRL: | ||
1720 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) | ||
1721 | return pBase->openLoopPwrCntl ? true : false; | ||
1722 | else | ||
1723 | return false; | ||
1724 | case EEP_RC_CHAIN_MASK: | ||
1725 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) | ||
1726 | return pBase->rcChainMask; | ||
1727 | else | ||
1728 | return 0; | ||
1729 | case EEP_DAC_HPWR_5G: | ||
1730 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) | ||
1731 | return pBase->dacHiPwrMode_5G; | ||
1732 | else | ||
1733 | return 0; | ||
1734 | case EEP_FRAC_N_5G: | ||
1735 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22) | ||
1736 | return pBase->frac_n_5g; | ||
1737 | else | ||
1738 | return 0; | ||
1739 | default: | ||
1740 | return 0; | ||
1741 | } | ||
1742 | } | ||
1743 | |||
1744 | static void ath9k_hw_def_set_gain(struct ath_hw *ah, | ||
1745 | struct modal_eep_header *pModal, | ||
1746 | struct ar5416_eeprom_def *eep, | ||
1747 | u8 txRxAttenLocal, int regChainOffset, int i) | ||
1748 | { | ||
1749 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { | ||
1750 | txRxAttenLocal = pModal->txRxAttenCh[i]; | ||
1751 | |||
1752 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
1753 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1754 | AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, | ||
1755 | pModal->bswMargin[i]); | ||
1756 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1757 | AR_PHY_GAIN_2GHZ_XATTEN1_DB, | ||
1758 | pModal->bswAtten[i]); | ||
1759 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1760 | AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, | ||
1761 | pModal->xatten2Margin[i]); | ||
1762 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1763 | AR_PHY_GAIN_2GHZ_XATTEN2_DB, | ||
1764 | pModal->xatten2Db[i]); | ||
1765 | } else { | ||
1766 | REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1767 | (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & | ||
1768 | ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) | ||
1769 | | SM(pModal-> bswMargin[i], | ||
1770 | AR_PHY_GAIN_2GHZ_BSW_MARGIN)); | ||
1771 | REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1772 | (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & | ||
1773 | ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) | ||
1774 | | SM(pModal->bswAtten[i], | ||
1775 | AR_PHY_GAIN_2GHZ_BSW_ATTEN)); | ||
1776 | } | ||
1777 | } | ||
1778 | |||
1779 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
1780 | REG_RMW_FIELD(ah, | ||
1781 | AR_PHY_RXGAIN + regChainOffset, | ||
1782 | AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); | ||
1783 | REG_RMW_FIELD(ah, | ||
1784 | AR_PHY_RXGAIN + regChainOffset, | ||
1785 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]); | ||
1786 | } else { | ||
1787 | REG_WRITE(ah, | ||
1788 | AR_PHY_RXGAIN + regChainOffset, | ||
1789 | (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) & | ||
1790 | ~AR_PHY_RXGAIN_TXRX_ATTEN) | ||
1791 | | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN)); | ||
1792 | REG_WRITE(ah, | ||
1793 | AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1794 | (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & | ||
1795 | ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) | | ||
1796 | SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN)); | ||
1797 | } | ||
1798 | } | ||
1799 | |||
1800 | static void ath9k_hw_def_set_board_values(struct ath_hw *ah, | ||
1801 | struct ath9k_channel *chan) | ||
1802 | { | ||
1803 | struct modal_eep_header *pModal; | ||
1804 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; | ||
1805 | int i, regChainOffset; | ||
1806 | u8 txRxAttenLocal; | ||
1807 | |||
1808 | pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); | ||
1809 | txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; | ||
1810 | |||
1811 | REG_WRITE(ah, AR_PHY_SWITCH_COM, | ||
1812 | ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); | ||
1813 | |||
1814 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
1815 | if (AR_SREV_9280(ah)) { | ||
1816 | if (i >= 2) | ||
1817 | break; | ||
1818 | } | ||
1819 | |||
1820 | if (AR_SREV_5416_20_OR_LATER(ah) && | ||
1821 | (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0)) | ||
1822 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; | ||
1823 | else | ||
1824 | regChainOffset = i * 0x1000; | ||
1825 | |||
1826 | REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, | ||
1827 | pModal->antCtrlChain[i]); | ||
1828 | |||
1829 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, | ||
1830 | (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) & | ||
1831 | ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | | ||
1832 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | | ||
1833 | SM(pModal->iqCalICh[i], | ||
1834 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | | ||
1835 | SM(pModal->iqCalQCh[i], | ||
1836 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); | ||
1837 | |||
1838 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) | ||
1839 | ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal, | ||
1840 | regChainOffset, i); | ||
1841 | } | ||
1842 | |||
1843 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
1844 | if (IS_CHAN_2GHZ(chan)) { | ||
1845 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0, | ||
1846 | AR_AN_RF2G1_CH0_OB, | ||
1847 | AR_AN_RF2G1_CH0_OB_S, | ||
1848 | pModal->ob); | ||
1849 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0, | ||
1850 | AR_AN_RF2G1_CH0_DB, | ||
1851 | AR_AN_RF2G1_CH0_DB_S, | ||
1852 | pModal->db); | ||
1853 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1, | ||
1854 | AR_AN_RF2G1_CH1_OB, | ||
1855 | AR_AN_RF2G1_CH1_OB_S, | ||
1856 | pModal->ob_ch1); | ||
1857 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1, | ||
1858 | AR_AN_RF2G1_CH1_DB, | ||
1859 | AR_AN_RF2G1_CH1_DB_S, | ||
1860 | pModal->db_ch1); | ||
1861 | } else { | ||
1862 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0, | ||
1863 | AR_AN_RF5G1_CH0_OB5, | ||
1864 | AR_AN_RF5G1_CH0_OB5_S, | ||
1865 | pModal->ob); | ||
1866 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0, | ||
1867 | AR_AN_RF5G1_CH0_DB5, | ||
1868 | AR_AN_RF5G1_CH0_DB5_S, | ||
1869 | pModal->db); | ||
1870 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1, | ||
1871 | AR_AN_RF5G1_CH1_OB5, | ||
1872 | AR_AN_RF5G1_CH1_OB5_S, | ||
1873 | pModal->ob_ch1); | ||
1874 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1, | ||
1875 | AR_AN_RF5G1_CH1_DB5, | ||
1876 | AR_AN_RF5G1_CH1_DB5_S, | ||
1877 | pModal->db_ch1); | ||
1878 | } | ||
1879 | ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2, | ||
1880 | AR_AN_TOP2_XPABIAS_LVL, | ||
1881 | AR_AN_TOP2_XPABIAS_LVL_S, | ||
1882 | pModal->xpaBiasLvl); | ||
1883 | ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2, | ||
1884 | AR_AN_TOP2_LOCALBIAS, | ||
1885 | AR_AN_TOP2_LOCALBIAS_S, | ||
1886 | pModal->local_bias); | ||
1887 | REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG, | ||
1888 | pModal->force_xpaon); | ||
1889 | } | ||
1890 | |||
1891 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, | ||
1892 | pModal->switchSettling); | ||
1893 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, | ||
1894 | pModal->adcDesiredSize); | ||
1895 | |||
1896 | if (!AR_SREV_9280_10_OR_LATER(ah)) | ||
1897 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, | ||
1898 | AR_PHY_DESIRED_SZ_PGA, | ||
1899 | pModal->pgaDesiredSize); | ||
1900 | |||
1901 | REG_WRITE(ah, AR_PHY_RF_CTL4, | ||
1902 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) | ||
1903 | | SM(pModal->txEndToXpaOff, | ||
1904 | AR_PHY_RF_CTL4_TX_END_XPAB_OFF) | ||
1905 | | SM(pModal->txFrameToXpaOn, | ||
1906 | AR_PHY_RF_CTL4_FRAME_XPAA_ON) | ||
1907 | | SM(pModal->txFrameToXpaOn, | ||
1908 | AR_PHY_RF_CTL4_FRAME_XPAB_ON)); | ||
1909 | |||
1910 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, | ||
1911 | pModal->txEndToRxOn); | ||
1912 | |||
1913 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
1914 | REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, | ||
1915 | pModal->thresh62); | ||
1916 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, | ||
1917 | AR_PHY_EXT_CCA0_THRESH62, | ||
1918 | pModal->thresh62); | ||
1919 | } else { | ||
1920 | REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62, | ||
1921 | pModal->thresh62); | ||
1922 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, | ||
1923 | AR_PHY_EXT_CCA_THRESH62, | ||
1924 | pModal->thresh62); | ||
1925 | } | ||
1926 | |||
1927 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) { | ||
1928 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, | ||
1929 | AR_PHY_TX_END_DATA_START, | ||
1930 | pModal->txFrameToDataStart); | ||
1931 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON, | ||
1932 | pModal->txFrameToPaOn); | ||
1933 | } | ||
1934 | |||
1935 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { | ||
1936 | if (IS_CHAN_HT40(chan)) | ||
1937 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, | ||
1938 | AR_PHY_SETTLING_SWITCH, | ||
1939 | pModal->swSettleHt40); | ||
1940 | } | ||
1941 | |||
1942 | if (AR_SREV_9280_20_OR_LATER(ah) && | ||
1943 | AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) | ||
1944 | REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL, | ||
1945 | AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK, | ||
1946 | pModal->miscBits); | ||
1947 | |||
1948 | |||
1949 | if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) { | ||
1950 | if (IS_CHAN_2GHZ(chan)) | ||
1951 | REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, | ||
1952 | eep->baseEepHeader.dacLpMode); | ||
1953 | else if (eep->baseEepHeader.dacHiPwrMode_5G) | ||
1954 | REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0); | ||
1955 | else | ||
1956 | REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, | ||
1957 | eep->baseEepHeader.dacLpMode); | ||
1958 | |||
1959 | REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, | ||
1960 | pModal->miscBits >> 2); | ||
1961 | |||
1962 | REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9, | ||
1963 | AR_PHY_TX_DESIRED_SCALE_CCK, | ||
1964 | eep->baseEepHeader.desiredScaleCCK); | ||
1965 | } | ||
1966 | } | ||
1967 | |||
1968 | static void ath9k_hw_def_set_addac(struct ath_hw *ah, | ||
1969 | struct ath9k_channel *chan) | ||
1970 | { | ||
1971 | #define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt]) | ||
1972 | struct modal_eep_header *pModal; | ||
1973 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; | ||
1974 | u8 biaslevel; | ||
1975 | |||
1976 | if (ah->hw_version.macVersion != AR_SREV_VERSION_9160) | ||
1977 | return; | ||
1978 | |||
1979 | if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7) | ||
1980 | return; | ||
1981 | |||
1982 | pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); | ||
1983 | |||
1984 | if (pModal->xpaBiasLvl != 0xff) { | ||
1985 | biaslevel = pModal->xpaBiasLvl; | ||
1986 | } else { | ||
1987 | u16 resetFreqBin, freqBin, freqCount = 0; | ||
1988 | struct chan_centers centers; | ||
1989 | |||
1990 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
1991 | |||
1992 | resetFreqBin = FREQ2FBIN(centers.synth_center, | ||
1993 | IS_CHAN_2GHZ(chan)); | ||
1994 | freqBin = XPA_LVL_FREQ(0) & 0xff; | ||
1995 | biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14); | ||
1996 | |||
1997 | freqCount++; | ||
1998 | |||
1999 | while (freqCount < 3) { | ||
2000 | if (XPA_LVL_FREQ(freqCount) == 0x0) | ||
2001 | break; | ||
2002 | |||
2003 | freqBin = XPA_LVL_FREQ(freqCount) & 0xff; | ||
2004 | if (resetFreqBin >= freqBin) | ||
2005 | biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14); | ||
2006 | else | ||
2007 | break; | ||
2008 | freqCount++; | ||
2009 | } | ||
2010 | } | ||
2011 | |||
2012 | if (IS_CHAN_2GHZ(chan)) { | ||
2013 | INI_RA(&ah->iniAddac, 7, 1) = (INI_RA(&ah->iniAddac, | ||
2014 | 7, 1) & (~0x18)) | biaslevel << 3; | ||
2015 | } else { | ||
2016 | INI_RA(&ah->iniAddac, 6, 1) = (INI_RA(&ah->iniAddac, | ||
2017 | 6, 1) & (~0xc0)) | biaslevel << 6; | ||
2018 | } | ||
2019 | #undef XPA_LVL_FREQ | ||
2020 | } | ||
2021 | |||
2022 | static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, | ||
2023 | struct ath9k_channel *chan, | ||
2024 | struct cal_data_per_freq *pRawDataSet, | ||
2025 | u8 *bChans, u16 availPiers, | ||
2026 | u16 tPdGainOverlap, int16_t *pMinCalPower, | ||
2027 | u16 *pPdGainBoundaries, u8 *pPDADCValues, | ||
2028 | u16 numXpdGains) | ||
2029 | { | ||
2030 | int i, j, k; | ||
2031 | int16_t ss; | ||
2032 | u16 idxL = 0, idxR = 0, numPiers; | ||
2033 | static u8 vpdTableL[AR5416_NUM_PD_GAINS] | ||
2034 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
2035 | static u8 vpdTableR[AR5416_NUM_PD_GAINS] | ||
2036 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
2037 | static u8 vpdTableI[AR5416_NUM_PD_GAINS] | ||
2038 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
2039 | |||
2040 | u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; | ||
2041 | u8 minPwrT4[AR5416_NUM_PD_GAINS]; | ||
2042 | u8 maxPwrT4[AR5416_NUM_PD_GAINS]; | ||
2043 | int16_t vpdStep; | ||
2044 | int16_t tmpVal; | ||
2045 | u16 sizeCurrVpdTable, maxIndex, tgtIndex; | ||
2046 | bool match; | ||
2047 | int16_t minDelta = 0; | ||
2048 | struct chan_centers centers; | ||
2049 | |||
2050 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
2051 | |||
2052 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | ||
2053 | if (bChans[numPiers] == AR5416_BCHAN_UNUSED) | ||
2054 | break; | ||
2055 | } | ||
2056 | |||
2057 | match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center, | ||
2058 | IS_CHAN_2GHZ(chan)), | ||
2059 | bChans, numPiers, &idxL, &idxR); | ||
2060 | |||
2061 | if (match) { | ||
2062 | for (i = 0; i < numXpdGains; i++) { | ||
2063 | minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; | ||
2064 | maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; | ||
2065 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
2066 | pRawDataSet[idxL].pwrPdg[i], | ||
2067 | pRawDataSet[idxL].vpdPdg[i], | ||
2068 | AR5416_PD_GAIN_ICEPTS, | ||
2069 | vpdTableI[i]); | ||
2070 | } | ||
2071 | } else { | ||
2072 | for (i = 0; i < numXpdGains; i++) { | ||
2073 | pVpdL = pRawDataSet[idxL].vpdPdg[i]; | ||
2074 | pPwrL = pRawDataSet[idxL].pwrPdg[i]; | ||
2075 | pVpdR = pRawDataSet[idxR].vpdPdg[i]; | ||
2076 | pPwrR = pRawDataSet[idxR].pwrPdg[i]; | ||
2077 | |||
2078 | minPwrT4[i] = max(pPwrL[0], pPwrR[0]); | ||
2079 | |||
2080 | maxPwrT4[i] = | ||
2081 | min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1], | ||
2082 | pPwrR[AR5416_PD_GAIN_ICEPTS - 1]); | ||
2083 | |||
2084 | |||
2085 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
2086 | pPwrL, pVpdL, | ||
2087 | AR5416_PD_GAIN_ICEPTS, | ||
2088 | vpdTableL[i]); | ||
2089 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
2090 | pPwrR, pVpdR, | ||
2091 | AR5416_PD_GAIN_ICEPTS, | ||
2092 | vpdTableR[i]); | ||
2093 | |||
2094 | for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { | ||
2095 | vpdTableI[i][j] = | ||
2096 | (u8)(ath9k_hw_interpolate((u16) | ||
2097 | FREQ2FBIN(centers. | ||
2098 | synth_center, | ||
2099 | IS_CHAN_2GHZ | ||
2100 | (chan)), | ||
2101 | bChans[idxL], bChans[idxR], | ||
2102 | vpdTableL[i][j], vpdTableR[i][j])); | ||
2103 | } | ||
2104 | } | ||
2105 | } | ||
2106 | |||
2107 | *pMinCalPower = (int16_t)(minPwrT4[0] / 2); | ||
2108 | |||
2109 | k = 0; | ||
2110 | |||
2111 | for (i = 0; i < numXpdGains; i++) { | ||
2112 | if (i == (numXpdGains - 1)) | ||
2113 | pPdGainBoundaries[i] = | ||
2114 | (u16)(maxPwrT4[i] / 2); | ||
2115 | else | ||
2116 | pPdGainBoundaries[i] = | ||
2117 | (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4); | ||
2118 | |||
2119 | pPdGainBoundaries[i] = | ||
2120 | min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); | ||
2121 | |||
2122 | if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { | ||
2123 | minDelta = pPdGainBoundaries[0] - 23; | ||
2124 | pPdGainBoundaries[0] = 23; | ||
2125 | } else { | ||
2126 | minDelta = 0; | ||
2127 | } | ||
2128 | |||
2129 | if (i == 0) { | ||
2130 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
2131 | ss = (int16_t)(0 - (minPwrT4[i] / 2)); | ||
2132 | else | ||
2133 | ss = 0; | ||
2134 | } else { | ||
2135 | ss = (int16_t)((pPdGainBoundaries[i - 1] - | ||
2136 | (minPwrT4[i] / 2)) - | ||
2137 | tPdGainOverlap + 1 + minDelta); | ||
2138 | } | ||
2139 | vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); | ||
2140 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
2141 | |||
2142 | while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
2143 | tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); | ||
2144 | pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); | ||
2145 | ss++; | ||
2146 | } | ||
2147 | |||
2148 | sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); | ||
2149 | tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap - | ||
2150 | (minPwrT4[i] / 2)); | ||
2151 | maxIndex = (tgtIndex < sizeCurrVpdTable) ? | ||
2152 | tgtIndex : sizeCurrVpdTable; | ||
2153 | |||
2154 | while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
2155 | pPDADCValues[k++] = vpdTableI[i][ss++]; | ||
2156 | } | ||
2157 | |||
2158 | vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - | ||
2159 | vpdTableI[i][sizeCurrVpdTable - 2]); | ||
2160 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
2161 | |||
2162 | if (tgtIndex > maxIndex) { | ||
2163 | while ((ss <= tgtIndex) && | ||
2164 | (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
2165 | tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] + | ||
2166 | (ss - maxIndex + 1) * vpdStep)); | ||
2167 | pPDADCValues[k++] = (u8)((tmpVal > 255) ? | ||
2168 | 255 : tmpVal); | ||
2169 | ss++; | ||
2170 | } | ||
2171 | } | ||
2172 | } | ||
2173 | |||
2174 | while (i < AR5416_PD_GAINS_IN_MASK) { | ||
2175 | pPdGainBoundaries[i] = pPdGainBoundaries[i - 1]; | ||
2176 | i++; | ||
2177 | } | ||
2178 | |||
2179 | while (k < AR5416_NUM_PDADC_VALUES) { | ||
2180 | pPDADCValues[k] = pPDADCValues[k - 1]; | ||
2181 | k++; | ||
2182 | } | ||
2183 | |||
2184 | return; | ||
2185 | } | ||
2186 | |||
2187 | static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | ||
2188 | struct ath9k_channel *chan, | ||
2189 | int16_t *pTxPowerIndexOffset) | ||
2190 | { | ||
2191 | #define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x) | ||
2192 | #define SM_PDGAIN_B(x, y) \ | ||
2193 | SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y) | ||
2194 | |||
2195 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; | ||
2196 | struct cal_data_per_freq *pRawDataset; | ||
2197 | u8 *pCalBChans = NULL; | ||
2198 | u16 pdGainOverlap_t2; | ||
2199 | static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; | ||
2200 | u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; | ||
2201 | u16 numPiers, i, j; | ||
2202 | int16_t tMinCalPower; | ||
2203 | u16 numXpdGain, xpdMask; | ||
2204 | u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 }; | ||
2205 | u32 reg32, regOffset, regChainOffset; | ||
2206 | int16_t modalIdx; | ||
2207 | |||
2208 | modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; | ||
2209 | xpdMask = pEepData->modalHeader[modalIdx].xpdGain; | ||
2210 | |||
2211 | if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
2212 | AR5416_EEP_MINOR_VER_2) { | ||
2213 | pdGainOverlap_t2 = | ||
2214 | pEepData->modalHeader[modalIdx].pdGainOverlap; | ||
2215 | } else { | ||
2216 | pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), | ||
2217 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); | ||
2218 | } | ||
2219 | |||
2220 | if (IS_CHAN_2GHZ(chan)) { | ||
2221 | pCalBChans = pEepData->calFreqPier2G; | ||
2222 | numPiers = AR5416_NUM_2G_CAL_PIERS; | ||
2223 | } else { | ||
2224 | pCalBChans = pEepData->calFreqPier5G; | ||
2225 | numPiers = AR5416_NUM_5G_CAL_PIERS; | ||
2226 | } | ||
2227 | |||
2228 | if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) { | ||
2229 | pRawDataset = pEepData->calPierData2G[0]; | ||
2230 | ah->initPDADC = ((struct calDataPerFreqOpLoop *) | ||
2231 | pRawDataset)->vpdPdg[0][0]; | ||
2232 | } | ||
2233 | |||
2234 | numXpdGain = 0; | ||
2235 | |||
2236 | for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { | ||
2237 | if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { | ||
2238 | if (numXpdGain >= AR5416_NUM_PD_GAINS) | ||
2239 | break; | ||
2240 | xpdGainValues[numXpdGain] = | ||
2241 | (u16)(AR5416_PD_GAINS_IN_MASK - i); | ||
2242 | numXpdGain++; | ||
2243 | } | ||
2244 | } | ||
2245 | |||
2246 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, | ||
2247 | (numXpdGain - 1) & 0x3); | ||
2248 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, | ||
2249 | xpdGainValues[0]); | ||
2250 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, | ||
2251 | xpdGainValues[1]); | ||
2252 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, | ||
2253 | xpdGainValues[2]); | ||
2254 | |||
2255 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
2256 | if (AR_SREV_5416_20_OR_LATER(ah) && | ||
2257 | (ah->rxchainmask == 5 || ah->txchainmask == 5) && | ||
2258 | (i != 0)) { | ||
2259 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; | ||
2260 | } else | ||
2261 | regChainOffset = i * 0x1000; | ||
2262 | |||
2263 | if (pEepData->baseEepHeader.txMask & (1 << i)) { | ||
2264 | if (IS_CHAN_2GHZ(chan)) | ||
2265 | pRawDataset = pEepData->calPierData2G[i]; | ||
2266 | else | ||
2267 | pRawDataset = pEepData->calPierData5G[i]; | ||
2268 | |||
2269 | |||
2270 | if (OLC_FOR_AR9280_20_LATER) { | ||
2271 | u8 pcdacIdx; | ||
2272 | u8 txPower; | ||
2273 | |||
2274 | ath9k_get_txgain_index(ah, chan, | ||
2275 | (struct calDataPerFreqOpLoop *)pRawDataset, | ||
2276 | pCalBChans, numPiers, &txPower, &pcdacIdx); | ||
2277 | ath9k_olc_get_pdadcs(ah, pcdacIdx, | ||
2278 | txPower/2, pdadcValues); | ||
2279 | } else { | ||
2280 | ath9k_hw_get_def_gain_boundaries_pdadcs(ah, | ||
2281 | chan, pRawDataset, | ||
2282 | pCalBChans, numPiers, | ||
2283 | pdGainOverlap_t2, | ||
2284 | &tMinCalPower, | ||
2285 | gainBoundaries, | ||
2286 | pdadcValues, | ||
2287 | numXpdGain); | ||
2288 | } | ||
2289 | |||
2290 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { | ||
2291 | if (OLC_FOR_AR9280_20_LATER) { | ||
2292 | REG_WRITE(ah, | ||
2293 | AR_PHY_TPCRG5 + regChainOffset, | ||
2294 | SM(0x6, | ||
2295 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | | ||
2296 | SM_PD_GAIN(1) | SM_PD_GAIN(2) | | ||
2297 | SM_PD_GAIN(3) | SM_PD_GAIN(4)); | ||
2298 | } else { | ||
2299 | REG_WRITE(ah, | ||
2300 | AR_PHY_TPCRG5 + regChainOffset, | ||
2301 | SM(pdGainOverlap_t2, | ||
2302 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP)| | ||
2303 | SM_PDGAIN_B(0, 1) | | ||
2304 | SM_PDGAIN_B(1, 2) | | ||
2305 | SM_PDGAIN_B(2, 3) | | ||
2306 | SM_PDGAIN_B(3, 4)); | ||
2307 | } | ||
2308 | } | ||
2309 | |||
2310 | regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; | ||
2311 | for (j = 0; j < 32; j++) { | ||
2312 | reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) | | ||
2313 | ((pdadcValues[4 * j + 1] & 0xFF) << 8) | | ||
2314 | ((pdadcValues[4 * j + 2] & 0xFF) << 16)| | ||
2315 | ((pdadcValues[4 * j + 3] & 0xFF) << 24); | ||
2316 | REG_WRITE(ah, regOffset, reg32); | ||
2317 | |||
2318 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
2319 | "PDADC (%d,%4x): %4.4x %8.8x\n", | ||
2320 | i, regChainOffset, regOffset, | ||
2321 | reg32); | ||
2322 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
2323 | "PDADC: Chain %d | PDADC %3d " | ||
2324 | "Value %3d | PDADC %3d Value %3d | " | ||
2325 | "PDADC %3d Value %3d | PDADC %3d " | ||
2326 | "Value %3d |\n", | ||
2327 | i, 4 * j, pdadcValues[4 * j], | ||
2328 | 4 * j + 1, pdadcValues[4 * j + 1], | ||
2329 | 4 * j + 2, pdadcValues[4 * j + 2], | ||
2330 | 4 * j + 3, | ||
2331 | pdadcValues[4 * j + 3]); | ||
2332 | |||
2333 | regOffset += 4; | ||
2334 | } | ||
2335 | } | ||
2336 | } | ||
2337 | |||
2338 | *pTxPowerIndexOffset = 0; | ||
2339 | #undef SM_PD_GAIN | ||
2340 | #undef SM_PDGAIN_B | ||
2341 | } | ||
2342 | |||
2343 | static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, | ||
2344 | struct ath9k_channel *chan, | ||
2345 | int16_t *ratesArray, | ||
2346 | u16 cfgCtl, | ||
2347 | u16 AntennaReduction, | ||
2348 | u16 twiceMaxRegulatoryPower, | ||
2349 | u16 powerLimit) | ||
2350 | { | ||
2351 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ | ||
2352 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */ | ||
2353 | |||
2354 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; | ||
2355 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
2356 | static const u16 tpScaleReductionTable[5] = | ||
2357 | { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; | ||
2358 | |||
2359 | int i; | ||
2360 | int16_t twiceLargestAntenna; | ||
2361 | struct cal_ctl_data *rep; | ||
2362 | struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { | ||
2363 | 0, { 0, 0, 0, 0} | ||
2364 | }; | ||
2365 | struct cal_target_power_leg targetPowerOfdmExt = { | ||
2366 | 0, { 0, 0, 0, 0} }, targetPowerCckExt = { | ||
2367 | 0, { 0, 0, 0, 0 } | ||
2368 | }; | ||
2369 | struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { | ||
2370 | 0, {0, 0, 0, 0} | ||
2371 | }; | ||
2372 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; | ||
2373 | u16 ctlModesFor11a[] = | ||
2374 | { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 }; | ||
2375 | u16 ctlModesFor11g[] = | ||
2376 | { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, | ||
2377 | CTL_2GHT40 | ||
2378 | }; | ||
2379 | u16 numCtlModes, *pCtlMode, ctlMode, freq; | ||
2380 | struct chan_centers centers; | ||
2381 | int tx_chainmask; | ||
2382 | u16 twiceMinEdgePower; | ||
2383 | |||
2384 | tx_chainmask = ah->txchainmask; | ||
2385 | |||
2386 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
2387 | |||
2388 | twiceLargestAntenna = max( | ||
2389 | pEepData->modalHeader | ||
2390 | [IS_CHAN_2GHZ(chan)].antennaGainCh[0], | ||
2391 | pEepData->modalHeader | ||
2392 | [IS_CHAN_2GHZ(chan)].antennaGainCh[1]); | ||
2393 | |||
2394 | twiceLargestAntenna = max((u8)twiceLargestAntenna, | ||
2395 | pEepData->modalHeader | ||
2396 | [IS_CHAN_2GHZ(chan)].antennaGainCh[2]); | ||
2397 | |||
2398 | twiceLargestAntenna = (int16_t)min(AntennaReduction - | ||
2399 | twiceLargestAntenna, 0); | ||
2400 | |||
2401 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; | ||
2402 | |||
2403 | if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) { | ||
2404 | maxRegAllowedPower -= | ||
2405 | (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); | ||
2406 | } | ||
2407 | |||
2408 | scaledPower = min(powerLimit, maxRegAllowedPower); | ||
2409 | |||
2410 | switch (ar5416_get_ntxchains(tx_chainmask)) { | ||
2411 | case 1: | ||
2412 | break; | ||
2413 | case 2: | ||
2414 | scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; | ||
2415 | break; | ||
2416 | case 3: | ||
2417 | scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; | ||
2418 | break; | ||
2419 | } | ||
2420 | |||
2421 | scaledPower = max((u16)0, scaledPower); | ||
2422 | |||
2423 | if (IS_CHAN_2GHZ(chan)) { | ||
2424 | numCtlModes = ARRAY_SIZE(ctlModesFor11g) - | ||
2425 | SUB_NUM_CTL_MODES_AT_2G_40; | ||
2426 | pCtlMode = ctlModesFor11g; | ||
2427 | |||
2428 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
2429 | pEepData->calTargetPowerCck, | ||
2430 | AR5416_NUM_2G_CCK_TARGET_POWERS, | ||
2431 | &targetPowerCck, 4, false); | ||
2432 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
2433 | pEepData->calTargetPower2G, | ||
2434 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
2435 | &targetPowerOfdm, 4, false); | ||
2436 | ath9k_hw_get_target_powers(ah, chan, | ||
2437 | pEepData->calTargetPower2GHT20, | ||
2438 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
2439 | &targetPowerHt20, 8, false); | ||
2440 | |||
2441 | if (IS_CHAN_HT40(chan)) { | ||
2442 | numCtlModes = ARRAY_SIZE(ctlModesFor11g); | ||
2443 | ath9k_hw_get_target_powers(ah, chan, | ||
2444 | pEepData->calTargetPower2GHT40, | ||
2445 | AR5416_NUM_2G_40_TARGET_POWERS, | ||
2446 | &targetPowerHt40, 8, true); | ||
2447 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
2448 | pEepData->calTargetPowerCck, | ||
2449 | AR5416_NUM_2G_CCK_TARGET_POWERS, | ||
2450 | &targetPowerCckExt, 4, true); | ||
2451 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
2452 | pEepData->calTargetPower2G, | ||
2453 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
2454 | &targetPowerOfdmExt, 4, true); | ||
2455 | } | ||
2456 | } else { | ||
2457 | numCtlModes = ARRAY_SIZE(ctlModesFor11a) - | ||
2458 | SUB_NUM_CTL_MODES_AT_5G_40; | ||
2459 | pCtlMode = ctlModesFor11a; | ||
2460 | |||
2461 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
2462 | pEepData->calTargetPower5G, | ||
2463 | AR5416_NUM_5G_20_TARGET_POWERS, | ||
2464 | &targetPowerOfdm, 4, false); | ||
2465 | ath9k_hw_get_target_powers(ah, chan, | ||
2466 | pEepData->calTargetPower5GHT20, | ||
2467 | AR5416_NUM_5G_20_TARGET_POWERS, | ||
2468 | &targetPowerHt20, 8, false); | ||
2469 | |||
2470 | if (IS_CHAN_HT40(chan)) { | ||
2471 | numCtlModes = ARRAY_SIZE(ctlModesFor11a); | ||
2472 | ath9k_hw_get_target_powers(ah, chan, | ||
2473 | pEepData->calTargetPower5GHT40, | ||
2474 | AR5416_NUM_5G_40_TARGET_POWERS, | ||
2475 | &targetPowerHt40, 8, true); | ||
2476 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
2477 | pEepData->calTargetPower5G, | ||
2478 | AR5416_NUM_5G_20_TARGET_POWERS, | ||
2479 | &targetPowerOfdmExt, 4, true); | ||
2480 | } | ||
2481 | } | ||
2482 | |||
2483 | for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { | ||
2484 | bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || | ||
2485 | (pCtlMode[ctlMode] == CTL_2GHT40); | ||
2486 | if (isHt40CtlMode) | ||
2487 | freq = centers.synth_center; | ||
2488 | else if (pCtlMode[ctlMode] & EXT_ADDITIVE) | ||
2489 | freq = centers.ext_center; | ||
2490 | else | ||
2491 | freq = centers.ctl_center; | ||
2492 | |||
2493 | if (ah->eep_ops->get_eeprom_ver(ah) == 14 && | ||
2494 | ah->eep_ops->get_eeprom_rev(ah) <= 2) | ||
2495 | twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
2496 | |||
2497 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
2498 | "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, " | ||
2499 | "EXT_ADDITIVE %d\n", | ||
2500 | ctlMode, numCtlModes, isHt40CtlMode, | ||
2501 | (pCtlMode[ctlMode] & EXT_ADDITIVE)); | ||
2502 | |||
2503 | for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { | ||
2504 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
2505 | " LOOP-Ctlidx %d: cfgCtl 0x%2.2x " | ||
2506 | "pCtlMode 0x%2.2x ctlIndex 0x%2.2x " | ||
2507 | "chan %d\n", | ||
2508 | i, cfgCtl, pCtlMode[ctlMode], | ||
2509 | pEepData->ctlIndex[i], chan->channel); | ||
2510 | |||
2511 | if ((((cfgCtl & ~CTL_MODE_M) | | ||
2512 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
2513 | pEepData->ctlIndex[i]) || | ||
2514 | (((cfgCtl & ~CTL_MODE_M) | | ||
2515 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
2516 | ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) { | ||
2517 | rep = &(pEepData->ctlData[i]); | ||
2518 | |||
2519 | twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq, | ||
2520 | rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1], | ||
2521 | IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES); | ||
2522 | |||
2523 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
2524 | " MATCH-EE_IDX %d: ch %d is2 %d " | ||
2525 | "2xMinEdge %d chainmask %d chains %d\n", | ||
2526 | i, freq, IS_CHAN_2GHZ(chan), | ||
2527 | twiceMinEdgePower, tx_chainmask, | ||
2528 | ar5416_get_ntxchains | ||
2529 | (tx_chainmask)); | ||
2530 | if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { | ||
2531 | twiceMaxEdgePower = min(twiceMaxEdgePower, | ||
2532 | twiceMinEdgePower); | ||
2533 | } else { | ||
2534 | twiceMaxEdgePower = twiceMinEdgePower; | ||
2535 | break; | ||
2536 | } | ||
2537 | } | ||
2538 | } | ||
2539 | |||
2540 | minCtlPower = min(twiceMaxEdgePower, scaledPower); | ||
2541 | |||
2542 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
2543 | " SEL-Min ctlMode %d pCtlMode %d " | ||
2544 | "2xMaxEdge %d sP %d minCtlPwr %d\n", | ||
2545 | ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, | ||
2546 | scaledPower, minCtlPower); | ||
2547 | |||
2548 | switch (pCtlMode[ctlMode]) { | ||
2549 | case CTL_11B: | ||
2550 | for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) { | ||
2551 | targetPowerCck.tPow2x[i] = | ||
2552 | min((u16)targetPowerCck.tPow2x[i], | ||
2553 | minCtlPower); | ||
2554 | } | ||
2555 | break; | ||
2556 | case CTL_11A: | ||
2557 | case CTL_11G: | ||
2558 | for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) { | ||
2559 | targetPowerOfdm.tPow2x[i] = | ||
2560 | min((u16)targetPowerOfdm.tPow2x[i], | ||
2561 | minCtlPower); | ||
2562 | } | ||
2563 | break; | ||
2564 | case CTL_5GHT20: | ||
2565 | case CTL_2GHT20: | ||
2566 | for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) { | ||
2567 | targetPowerHt20.tPow2x[i] = | ||
2568 | min((u16)targetPowerHt20.tPow2x[i], | ||
2569 | minCtlPower); | ||
2570 | } | ||
2571 | break; | ||
2572 | case CTL_11B_EXT: | ||
2573 | targetPowerCckExt.tPow2x[0] = min((u16) | ||
2574 | targetPowerCckExt.tPow2x[0], | ||
2575 | minCtlPower); | ||
2576 | break; | ||
2577 | case CTL_11A_EXT: | ||
2578 | case CTL_11G_EXT: | ||
2579 | targetPowerOfdmExt.tPow2x[0] = min((u16) | ||
2580 | targetPowerOfdmExt.tPow2x[0], | ||
2581 | minCtlPower); | ||
2582 | break; | ||
2583 | case CTL_5GHT40: | ||
2584 | case CTL_2GHT40: | ||
2585 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { | ||
2586 | targetPowerHt40.tPow2x[i] = | ||
2587 | min((u16)targetPowerHt40.tPow2x[i], | ||
2588 | minCtlPower); | ||
2589 | } | ||
2590 | break; | ||
2591 | default: | ||
2592 | break; | ||
2593 | } | ||
2594 | } | ||
2595 | |||
2596 | ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = | ||
2597 | ratesArray[rate18mb] = ratesArray[rate24mb] = | ||
2598 | targetPowerOfdm.tPow2x[0]; | ||
2599 | ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; | ||
2600 | ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; | ||
2601 | ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; | ||
2602 | ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; | ||
2603 | |||
2604 | for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) | ||
2605 | ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; | ||
2606 | |||
2607 | if (IS_CHAN_2GHZ(chan)) { | ||
2608 | ratesArray[rate1l] = targetPowerCck.tPow2x[0]; | ||
2609 | ratesArray[rate2s] = ratesArray[rate2l] = | ||
2610 | targetPowerCck.tPow2x[1]; | ||
2611 | ratesArray[rate5_5s] = ratesArray[rate5_5l] = | ||
2612 | targetPowerCck.tPow2x[2]; | ||
2613 | ratesArray[rate11s] = ratesArray[rate11l] = | ||
2614 | targetPowerCck.tPow2x[3]; | ||
2615 | } | ||
2616 | if (IS_CHAN_HT40(chan)) { | ||
2617 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { | ||
2618 | ratesArray[rateHt40_0 + i] = | ||
2619 | targetPowerHt40.tPow2x[i]; | ||
2620 | } | ||
2621 | ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; | ||
2622 | ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; | ||
2623 | ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; | ||
2624 | if (IS_CHAN_2GHZ(chan)) { | ||
2625 | ratesArray[rateExtCck] = | ||
2626 | targetPowerCckExt.tPow2x[0]; | ||
2627 | } | ||
2628 | } | ||
2629 | } | ||
2630 | |||
2631 | static void ath9k_hw_def_set_txpower(struct ath_hw *ah, | ||
2632 | struct ath9k_channel *chan, | ||
2633 | u16 cfgCtl, | ||
2634 | u8 twiceAntennaReduction, | ||
2635 | u8 twiceMaxRegulatoryPower, | ||
2636 | u8 powerLimit) | ||
2637 | { | ||
2638 | #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) | ||
2639 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; | ||
2640 | struct modal_eep_header *pModal = | ||
2641 | &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]); | ||
2642 | int16_t ratesArray[Ar5416RateSize]; | ||
2643 | int16_t txPowerIndexOffset = 0; | ||
2644 | u8 ht40PowerIncForPdadc = 2; | ||
2645 | int i, cck_ofdm_delta = 0; | ||
2646 | |||
2647 | memset(ratesArray, 0, sizeof(ratesArray)); | ||
2648 | |||
2649 | if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
2650 | AR5416_EEP_MINOR_VER_2) { | ||
2651 | ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; | ||
2652 | } | ||
2653 | |||
2654 | ath9k_hw_set_def_power_per_rate_table(ah, chan, | ||
2655 | &ratesArray[0], cfgCtl, | ||
2656 | twiceAntennaReduction, | ||
2657 | twiceMaxRegulatoryPower, | ||
2658 | powerLimit); | ||
2659 | |||
2660 | ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset); | ||
2661 | |||
2662 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { | ||
2663 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); | ||
2664 | if (ratesArray[i] > AR5416_MAX_RATE_POWER) | ||
2665 | ratesArray[i] = AR5416_MAX_RATE_POWER; | ||
2666 | } | ||
2667 | |||
2668 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
2669 | for (i = 0; i < Ar5416RateSize; i++) | ||
2670 | ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2; | ||
2671 | } | ||
2672 | |||
2673 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, | ||
2674 | ATH9K_POW_SM(ratesArray[rate18mb], 24) | ||
2675 | | ATH9K_POW_SM(ratesArray[rate12mb], 16) | ||
2676 | | ATH9K_POW_SM(ratesArray[rate9mb], 8) | ||
2677 | | ATH9K_POW_SM(ratesArray[rate6mb], 0)); | ||
2678 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, | ||
2679 | ATH9K_POW_SM(ratesArray[rate54mb], 24) | ||
2680 | | ATH9K_POW_SM(ratesArray[rate48mb], 16) | ||
2681 | | ATH9K_POW_SM(ratesArray[rate36mb], 8) | ||
2682 | | ATH9K_POW_SM(ratesArray[rate24mb], 0)); | ||
2683 | |||
2684 | if (IS_CHAN_2GHZ(chan)) { | ||
2685 | if (OLC_FOR_AR9280_20_LATER) { | ||
2686 | cck_ofdm_delta = 2; | ||
2687 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, | ||
2688 | ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24) | ||
2689 | | ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16) | ||
2690 | | ATH9K_POW_SM(ratesArray[rateXr], 8) | ||
2691 | | ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0)); | ||
2692 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, | ||
2693 | ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24) | ||
2694 | | ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16) | ||
2695 | | ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8) | ||
2696 | | ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0)); | ||
2697 | } else { | ||
2698 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, | ||
2699 | ATH9K_POW_SM(ratesArray[rate2s], 24) | ||
2700 | | ATH9K_POW_SM(ratesArray[rate2l], 16) | ||
2701 | | ATH9K_POW_SM(ratesArray[rateXr], 8) | ||
2702 | | ATH9K_POW_SM(ratesArray[rate1l], 0)); | ||
2703 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, | ||
2704 | ATH9K_POW_SM(ratesArray[rate11s], 24) | ||
2705 | | ATH9K_POW_SM(ratesArray[rate11l], 16) | ||
2706 | | ATH9K_POW_SM(ratesArray[rate5_5s], 8) | ||
2707 | | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); | ||
2708 | } | ||
2709 | } | ||
2710 | |||
2711 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, | ||
2712 | ATH9K_POW_SM(ratesArray[rateHt20_3], 24) | ||
2713 | | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) | ||
2714 | | ATH9K_POW_SM(ratesArray[rateHt20_1], 8) | ||
2715 | | ATH9K_POW_SM(ratesArray[rateHt20_0], 0)); | ||
2716 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, | ||
2717 | ATH9K_POW_SM(ratesArray[rateHt20_7], 24) | ||
2718 | | ATH9K_POW_SM(ratesArray[rateHt20_6], 16) | ||
2719 | | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) | ||
2720 | | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); | ||
2721 | |||
2722 | if (IS_CHAN_HT40(chan)) { | ||
2723 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, | ||
2724 | ATH9K_POW_SM(ratesArray[rateHt40_3] + | ||
2725 | ht40PowerIncForPdadc, 24) | ||
2726 | | ATH9K_POW_SM(ratesArray[rateHt40_2] + | ||
2727 | ht40PowerIncForPdadc, 16) | ||
2728 | | ATH9K_POW_SM(ratesArray[rateHt40_1] + | ||
2729 | ht40PowerIncForPdadc, 8) | ||
2730 | | ATH9K_POW_SM(ratesArray[rateHt40_0] + | ||
2731 | ht40PowerIncForPdadc, 0)); | ||
2732 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, | ||
2733 | ATH9K_POW_SM(ratesArray[rateHt40_7] + | ||
2734 | ht40PowerIncForPdadc, 24) | ||
2735 | | ATH9K_POW_SM(ratesArray[rateHt40_6] + | ||
2736 | ht40PowerIncForPdadc, 16) | ||
2737 | | ATH9K_POW_SM(ratesArray[rateHt40_5] + | ||
2738 | ht40PowerIncForPdadc, 8) | ||
2739 | | ATH9K_POW_SM(ratesArray[rateHt40_4] + | ||
2740 | ht40PowerIncForPdadc, 0)); | ||
2741 | if (OLC_FOR_AR9280_20_LATER) { | ||
2742 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, | ||
2743 | ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) | ||
2744 | | ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16) | ||
2745 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | ||
2746 | | ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0)); | ||
2747 | } else { | ||
2748 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, | ||
2749 | ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) | ||
2750 | | ATH9K_POW_SM(ratesArray[rateExtCck], 16) | ||
2751 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | ||
2752 | | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); | ||
2753 | } | ||
2754 | } | ||
2755 | |||
2756 | REG_WRITE(ah, AR_PHY_POWER_TX_SUB, | ||
2757 | ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) | ||
2758 | | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)); | ||
2759 | |||
2760 | i = rate6mb; | ||
2761 | |||
2762 | if (IS_CHAN_HT40(chan)) | ||
2763 | i = rateHt40_0; | ||
2764 | else if (IS_CHAN_HT20(chan)) | ||
2765 | i = rateHt20_0; | ||
2766 | |||
2767 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
2768 | ah->regulatory.max_power_level = | ||
2769 | ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2; | ||
2770 | else | ||
2771 | ah->regulatory.max_power_level = ratesArray[i]; | ||
2772 | |||
2773 | switch(ar5416_get_ntxchains(ah->txchainmask)) { | ||
2774 | case 1: | ||
2775 | break; | ||
2776 | case 2: | ||
2777 | ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; | ||
2778 | break; | ||
2779 | case 3: | ||
2780 | ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; | ||
2781 | break; | ||
2782 | default: | ||
2783 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
2784 | "Invalid chainmask configuration\n"); | ||
2785 | break; | ||
2786 | } | ||
2787 | } | ||
2788 | |||
2789 | static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah, | ||
2790 | enum ieee80211_band freq_band) | ||
2791 | { | ||
2792 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; | ||
2793 | struct modal_eep_header *pModal = | ||
2794 | &(eep->modalHeader[ATH9K_HAL_FREQ_BAND_2GHZ == freq_band]); | ||
2795 | struct base_eep_header *pBase = &eep->baseEepHeader; | ||
2796 | u8 num_ant_config; | ||
2797 | |||
2798 | num_ant_config = 1; | ||
2799 | |||
2800 | if (pBase->version >= 0x0E0D) | ||
2801 | if (pModal->useAnt1) | ||
2802 | num_ant_config += 1; | ||
2803 | |||
2804 | return num_ant_config; | ||
2805 | } | ||
2806 | |||
2807 | static u16 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah, | ||
2808 | struct ath9k_channel *chan) | ||
2809 | { | ||
2810 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; | ||
2811 | struct modal_eep_header *pModal = | ||
2812 | &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); | ||
2813 | |||
2814 | return pModal->antCtrlCommon & 0xFFFF; | ||
2815 | } | ||
2816 | |||
2817 | static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) | ||
2818 | { | ||
2819 | #define EEP_DEF_SPURCHAN \ | ||
2820 | (ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan) | ||
2821 | |||
2822 | u16 spur_val = AR_NO_SPUR; | ||
2823 | |||
2824 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
2825 | "Getting spur idx %d is2Ghz. %d val %x\n", | ||
2826 | i, is2GHz, ah->config.spurchans[i][is2GHz]); | ||
2827 | |||
2828 | switch (ah->config.spurmode) { | ||
2829 | case SPUR_DISABLE: | ||
2830 | break; | ||
2831 | case SPUR_ENABLE_IOCTL: | ||
2832 | spur_val = ah->config.spurchans[i][is2GHz]; | ||
2833 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
2834 | "Getting spur val from new loc. %d\n", spur_val); | ||
2835 | break; | ||
2836 | case SPUR_ENABLE_EEPROM: | ||
2837 | spur_val = EEP_DEF_SPURCHAN; | ||
2838 | break; | ||
2839 | } | ||
2840 | |||
2841 | return spur_val; | ||
2842 | |||
2843 | #undef EEP_DEF_SPURCHAN | ||
2844 | } | ||
2845 | |||
2846 | static struct eeprom_ops eep_def_ops = { | ||
2847 | .check_eeprom = ath9k_hw_def_check_eeprom, | ||
2848 | .get_eeprom = ath9k_hw_def_get_eeprom, | ||
2849 | .fill_eeprom = ath9k_hw_def_fill_eeprom, | ||
2850 | .get_eeprom_ver = ath9k_hw_def_get_eeprom_ver, | ||
2851 | .get_eeprom_rev = ath9k_hw_def_get_eeprom_rev, | ||
2852 | .get_num_ant_config = ath9k_hw_def_get_num_ant_config, | ||
2853 | .get_eeprom_antenna_cfg = ath9k_hw_def_get_eeprom_antenna_cfg, | ||
2854 | .set_board_values = ath9k_hw_def_set_board_values, | ||
2855 | .set_addac = ath9k_hw_def_set_addac, | ||
2856 | .set_txpower = ath9k_hw_def_set_txpower, | ||
2857 | .get_spur_channel = ath9k_hw_def_get_spur_channel | ||
2858 | }; | ||
2859 | |||
2860 | |||
2861 | static int ath9k_hw_AR9287_get_eeprom_ver(struct ath_hw *ah) | ||
2862 | { | ||
2863 | return (ah->eeprom.map9287.baseEepHeader.version >> 12) & 0xF; | ||
2864 | } | ||
2865 | |||
2866 | static int ath9k_hw_AR9287_get_eeprom_rev(struct ath_hw *ah) | ||
2867 | { | ||
2868 | return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF; | ||
2869 | } | ||
2870 | |||
2871 | static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah) | ||
2872 | { | ||
2873 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | ||
2874 | u16 *eep_data; | ||
2875 | int addr, eep_start_loc = AR9287_EEP_START_LOC; | ||
2876 | eep_data = (u16 *)eep; | ||
2877 | if (!ath9k_hw_use_flash(ah)) { | ||
2878 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
2879 | "Reading from EEPROM, not flash\n"); | ||
2880 | } | ||
2881 | |||
2882 | for (addr = 0; addr < sizeof(struct ar9287_eeprom) / sizeof(u16); | ||
2883 | addr++) { | ||
2884 | if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) { | ||
2885 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
2886 | "Unable to read eeprom region \n"); | ||
2887 | return false; | ||
2888 | } | ||
2889 | eep_data++; | ||
2890 | } | ||
2891 | return true; | ||
2892 | } | ||
2893 | static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) | ||
2894 | { | ||
2895 | u32 sum = 0, el, integer; | ||
2896 | u16 temp, word, magic, magic2, *eepdata; | ||
2897 | int i, addr; | ||
2898 | bool need_swap = false; | ||
2899 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | ||
2900 | |||
2901 | if (!ath9k_hw_use_flash(ah)) { | ||
2902 | if (!ath9k_hw_nvram_read | ||
2903 | (ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { | ||
2904 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
2905 | "Reading Magic # failed\n"); | ||
2906 | return false; | ||
2907 | } | ||
2908 | |||
2909 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
2910 | "Read Magic = 0x%04X\n", magic); | ||
2911 | if (magic != AR5416_EEPROM_MAGIC) { | ||
2912 | |||
2913 | |||
2914 | magic2 = swab16(magic); | ||
2915 | |||
2916 | if (magic2 == AR5416_EEPROM_MAGIC) { | ||
2917 | need_swap = true; | ||
2918 | eepdata = (u16 *)(&ah->eeprom); | ||
2919 | |||
2920 | for (addr = 0; | ||
2921 | addr < sizeof(struct ar9287_eeprom) / sizeof(u16); | ||
2922 | addr++) { | ||
2923 | temp = swab16(*eepdata); | ||
2924 | *eepdata = temp; | ||
2925 | eepdata++; | ||
2926 | } | ||
2927 | } else { | ||
2928 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
2929 | "Invalid EEPROM Magic. " | ||
2930 | "endianness mismatch.\n"); | ||
2931 | return -EINVAL; } | ||
2932 | } | ||
2933 | } | ||
2934 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", need_swap ? | ||
2935 | "True" : "False"); | ||
2936 | |||
2937 | if (need_swap) | ||
2938 | el = swab16(ah->eeprom.map9287.baseEepHeader.length); | ||
2939 | else | ||
2940 | el = ah->eeprom.map9287.baseEepHeader.length; | ||
2941 | |||
2942 | if (el > sizeof(struct ar9287_eeprom)) | ||
2943 | el = sizeof(struct ar9287_eeprom) / sizeof(u16); | ||
2944 | else | ||
2945 | el = el / sizeof(u16); | ||
2946 | |||
2947 | eepdata = (u16 *)(&ah->eeprom); | ||
2948 | for (i = 0; i < el; i++) | ||
2949 | sum ^= *eepdata++; | ||
2950 | |||
2951 | if (need_swap) { | ||
2952 | word = swab16(eep->baseEepHeader.length); | ||
2953 | eep->baseEepHeader.length = word; | ||
2954 | |||
2955 | word = swab16(eep->baseEepHeader.checksum); | ||
2956 | eep->baseEepHeader.checksum = word; | ||
2957 | |||
2958 | word = swab16(eep->baseEepHeader.version); | ||
2959 | eep->baseEepHeader.version = word; | ||
2960 | |||
2961 | word = swab16(eep->baseEepHeader.regDmn[0]); | ||
2962 | eep->baseEepHeader.regDmn[0] = word; | ||
2963 | |||
2964 | word = swab16(eep->baseEepHeader.regDmn[1]); | ||
2965 | eep->baseEepHeader.regDmn[1] = word; | ||
2966 | |||
2967 | word = swab16(eep->baseEepHeader.rfSilent); | ||
2968 | eep->baseEepHeader.rfSilent = word; | ||
2969 | |||
2970 | word = swab16(eep->baseEepHeader.blueToothOptions); | ||
2971 | eep->baseEepHeader.blueToothOptions = word; | ||
2972 | |||
2973 | word = swab16(eep->baseEepHeader.deviceCap); | ||
2974 | eep->baseEepHeader.deviceCap = word; | ||
2975 | |||
2976 | integer = swab32(eep->modalHeader.antCtrlCommon); | ||
2977 | eep->modalHeader.antCtrlCommon = integer; | ||
2978 | |||
2979 | for (i = 0; i < AR9287_MAX_CHAINS; i++) { | ||
2980 | integer = swab32(eep->modalHeader.antCtrlChain[i]); | ||
2981 | eep->modalHeader.antCtrlChain[i] = integer; | ||
2982 | } | ||
2983 | |||
2984 | for (i = 0; i < AR9287_EEPROM_MODAL_SPURS; i++) { | ||
2985 | word = swab16(eep->modalHeader.spurChans[i].spurChan); | ||
2986 | eep->modalHeader.spurChans[i].spurChan = word; | ||
2987 | } | ||
2988 | } | ||
2989 | |||
2990 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER | ||
2991 | || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { | ||
2992 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
2993 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | ||
2994 | sum, ah->eep_ops->get_eeprom_ver(ah)); | ||
2995 | return -EINVAL; | ||
2996 | } | ||
2997 | |||
2998 | return 0; | ||
2999 | } | ||
3000 | |||
3001 | static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah, | ||
3002 | enum eeprom_param param) | ||
3003 | { | ||
3004 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | ||
3005 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; | ||
3006 | struct base_eep_ar9287_header *pBase = &eep->baseEepHeader; | ||
3007 | u16 ver_minor; | ||
3008 | |||
3009 | ver_minor = pBase->version & AR9287_EEP_VER_MINOR_MASK; | ||
3010 | switch (param) { | ||
3011 | case EEP_NFTHRESH_2: | ||
3012 | return pModal->noiseFloorThreshCh[0]; | ||
3013 | case AR_EEPROM_MAC(0): | ||
3014 | return pBase->macAddr[0] << 8 | pBase->macAddr[1]; | ||
3015 | case AR_EEPROM_MAC(1): | ||
3016 | return pBase->macAddr[2] << 8 | pBase->macAddr[3]; | ||
3017 | case AR_EEPROM_MAC(2): | ||
3018 | return pBase->macAddr[4] << 8 | pBase->macAddr[5]; | ||
3019 | case EEP_REG_0: | ||
3020 | return pBase->regDmn[0]; | ||
3021 | case EEP_REG_1: | ||
3022 | return pBase->regDmn[1]; | ||
3023 | case EEP_OP_CAP: | ||
3024 | return pBase->deviceCap; | ||
3025 | case EEP_OP_MODE: | ||
3026 | return pBase->opCapFlags; | ||
3027 | case EEP_RF_SILENT: | ||
3028 | return pBase->rfSilent; | ||
3029 | case EEP_MINOR_REV: | ||
3030 | return ver_minor; | ||
3031 | case EEP_TX_MASK: | ||
3032 | return pBase->txMask; | ||
3033 | case EEP_RX_MASK: | ||
3034 | return pBase->rxMask; | ||
3035 | case EEP_DEV_TYPE: | ||
3036 | return pBase->deviceType; | ||
3037 | case EEP_OL_PWRCTRL: | ||
3038 | return pBase->openLoopPwrCntl; | ||
3039 | case EEP_TEMPSENSE_SLOPE: | ||
3040 | if (ver_minor >= AR9287_EEP_MINOR_VER_2) | ||
3041 | return pBase->tempSensSlope; | ||
3042 | else | ||
3043 | return 0; | ||
3044 | case EEP_TEMPSENSE_SLOPE_PAL_ON: | ||
3045 | if (ver_minor >= AR9287_EEP_MINOR_VER_3) | ||
3046 | return pBase->tempSensSlopePalOn; | ||
3047 | else | ||
3048 | return 0; | ||
3049 | default: | ||
3050 | return 0; | ||
3051 | } | ||
3052 | } | ||
3053 | |||
3054 | |||
3055 | static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah, | ||
3056 | struct ath9k_channel *chan, | ||
3057 | struct cal_data_per_freq_ar9287 *pRawDataSet, | ||
3058 | u8 *bChans, u16 availPiers, | ||
3059 | u16 tPdGainOverlap, int16_t *pMinCalPower, | ||
3060 | u16 *pPdGainBoundaries, u8 *pPDADCValues, | ||
3061 | u16 numXpdGains) | ||
3062 | { | ||
3063 | #define TMP_VAL_VPD_TABLE \ | ||
3064 | ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep)); | ||
3065 | int i, j, k; | ||
3066 | int16_t ss; | ||
3067 | u16 idxL = 0, idxR = 0, numPiers; | ||
3068 | u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; | ||
3069 | u8 minPwrT4[AR9287_NUM_PD_GAINS]; | ||
3070 | u8 maxPwrT4[AR9287_NUM_PD_GAINS]; | ||
3071 | int16_t vpdStep; | ||
3072 | int16_t tmpVal; | ||
3073 | u16 sizeCurrVpdTable, maxIndex, tgtIndex; | ||
3074 | bool match; | ||
3075 | int16_t minDelta = 0; | ||
3076 | struct chan_centers centers; | ||
3077 | static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS] | ||
3078 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
3079 | static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS] | ||
3080 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
3081 | static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS] | ||
3082 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
3083 | |||
3084 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
3085 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | ||
3086 | if (bChans[numPiers] == AR9287_BCHAN_UNUSED) | ||
3087 | break; | ||
3088 | } | ||
3089 | |||
3090 | match = ath9k_hw_get_lower_upper_index( | ||
3091 | (u8)FREQ2FBIN(centers.synth_center, | ||
3092 | IS_CHAN_2GHZ(chan)), bChans, numPiers, | ||
3093 | &idxL, &idxR); | ||
3094 | |||
3095 | if (match) { | ||
3096 | for (i = 0; i < numXpdGains; i++) { | ||
3097 | minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; | ||
3098 | maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; | ||
3099 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
3100 | pRawDataSet[idxL].pwrPdg[i], | ||
3101 | pRawDataSet[idxL].vpdPdg[i], | ||
3102 | AR9287_PD_GAIN_ICEPTS, vpdTableI[i]); | ||
3103 | } | ||
3104 | } else { | ||
3105 | for (i = 0; i < numXpdGains; i++) { | ||
3106 | pVpdL = pRawDataSet[idxL].vpdPdg[i]; | ||
3107 | pPwrL = pRawDataSet[idxL].pwrPdg[i]; | ||
3108 | pVpdR = pRawDataSet[idxR].vpdPdg[i]; | ||
3109 | pPwrR = pRawDataSet[idxR].pwrPdg[i]; | ||
3110 | |||
3111 | minPwrT4[i] = max(pPwrL[0], pPwrR[0]); | ||
3112 | |||
3113 | maxPwrT4[i] = | ||
3114 | min(pPwrL[AR9287_PD_GAIN_ICEPTS - 1], | ||
3115 | pPwrR[AR9287_PD_GAIN_ICEPTS - 1]); | ||
3116 | |||
3117 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
3118 | pPwrL, pVpdL, | ||
3119 | AR9287_PD_GAIN_ICEPTS, | ||
3120 | vpdTableL[i]); | ||
3121 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
3122 | pPwrR, pVpdR, | ||
3123 | AR9287_PD_GAIN_ICEPTS, | ||
3124 | vpdTableR[i]); | ||
3125 | |||
3126 | for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { | ||
3127 | vpdTableI[i][j] = | ||
3128 | (u8)(ath9k_hw_interpolate((u16) | ||
3129 | FREQ2FBIN(centers. synth_center, | ||
3130 | IS_CHAN_2GHZ(chan)), | ||
3131 | bChans[idxL], bChans[idxR], | ||
3132 | vpdTableL[i][j], vpdTableR[i][j])); | ||
3133 | } | ||
3134 | } | ||
3135 | } | ||
3136 | *pMinCalPower = (int16_t)(minPwrT4[0] / 2); | ||
3137 | |||
3138 | k = 0; | ||
3139 | for (i = 0; i < numXpdGains; i++) { | ||
3140 | if (i == (numXpdGains - 1)) | ||
3141 | pPdGainBoundaries[i] = (u16)(maxPwrT4[i] / 2); | ||
3142 | else | ||
3143 | pPdGainBoundaries[i] = (u16)((maxPwrT4[i] + | ||
3144 | minPwrT4[i+1]) / 4); | ||
3145 | |||
3146 | pPdGainBoundaries[i] = min((u16)AR5416_MAX_RATE_POWER, | ||
3147 | pPdGainBoundaries[i]); | ||
3148 | |||
3149 | |||
3150 | if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { | ||
3151 | minDelta = pPdGainBoundaries[0] - 23; | ||
3152 | pPdGainBoundaries[0] = 23; | ||
3153 | } else | ||
3154 | minDelta = 0; | ||
3155 | |||
3156 | if (i == 0) { | ||
3157 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
3158 | ss = (int16_t)(0 - (minPwrT4[i] / 2)); | ||
3159 | else | ||
3160 | ss = 0; | ||
3161 | } else | ||
3162 | ss = (int16_t)((pPdGainBoundaries[i-1] - | ||
3163 | (minPwrT4[i] / 2)) - | ||
3164 | tPdGainOverlap + 1 + minDelta); | ||
3165 | |||
3166 | vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); | ||
3167 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
3168 | while ((ss < 0) && (k < (AR9287_NUM_PDADC_VALUES - 1))) { | ||
3169 | tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); | ||
3170 | pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); | ||
3171 | ss++; | ||
3172 | } | ||
3173 | |||
3174 | sizeCurrVpdTable = (u8)((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); | ||
3175 | tgtIndex = (u8)(pPdGainBoundaries[i] + | ||
3176 | tPdGainOverlap - (minPwrT4[i] / 2)); | ||
3177 | maxIndex = (tgtIndex < sizeCurrVpdTable) ? | ||
3178 | tgtIndex : sizeCurrVpdTable; | ||
3179 | |||
3180 | while ((ss < maxIndex) && (k < (AR9287_NUM_PDADC_VALUES - 1))) | ||
3181 | pPDADCValues[k++] = vpdTableI[i][ss++]; | ||
3182 | |||
3183 | vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - | ||
3184 | vpdTableI[i][sizeCurrVpdTable - 2]); | ||
3185 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
3186 | if (tgtIndex > maxIndex) { | ||
3187 | while ((ss <= tgtIndex) && | ||
3188 | (k < (AR9287_NUM_PDADC_VALUES - 1))) { | ||
3189 | tmpVal = (int16_t) TMP_VAL_VPD_TABLE; | ||
3190 | pPDADCValues[k++] = (u8)((tmpVal > 255) ? | ||
3191 | 255 : tmpVal); | ||
3192 | ss++; | ||
3193 | } | ||
3194 | } | ||
3195 | } | ||
3196 | |||
3197 | while (i < AR9287_PD_GAINS_IN_MASK) { | ||
3198 | pPdGainBoundaries[i] = pPdGainBoundaries[i-1]; | ||
3199 | i++; | ||
3200 | } | ||
3201 | |||
3202 | while (k < AR9287_NUM_PDADC_VALUES) { | ||
3203 | pPDADCValues[k] = pPDADCValues[k-1]; | ||
3204 | k++; | ||
3205 | } | ||
3206 | |||
3207 | #undef TMP_VAL_VPD_TABLE | ||
3208 | } | ||
3209 | |||
3210 | static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, | ||
3211 | struct ath9k_channel *chan, | ||
3212 | struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop, | ||
3213 | u8 *pCalChans, u16 availPiers, | ||
3214 | int8_t *pPwr) | ||
3215 | { | ||
3216 | u8 pcdac, i = 0; | ||
3217 | u16 idxL = 0, idxR = 0, numPiers; | ||
3218 | bool match; | ||
3219 | struct chan_centers centers; | ||
3220 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
3221 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | ||
3222 | if (pCalChans[numPiers] == AR9287_BCHAN_UNUSED) | ||
3223 | break; | ||
3224 | } | ||
3225 | |||
3226 | match = ath9k_hw_get_lower_upper_index( | ||
3227 | (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), | ||
3228 | pCalChans, numPiers, | ||
3229 | &idxL, &idxR); | ||
3230 | |||
3231 | if (match) { | ||
3232 | pcdac = pRawDatasetOpLoop[idxL].pcdac[0][0]; | ||
3233 | *pPwr = pRawDatasetOpLoop[idxL].pwrPdg[0][0]; | ||
3234 | } else { | ||
3235 | pcdac = pRawDatasetOpLoop[idxR].pcdac[0][0]; | ||
3236 | *pPwr = (pRawDatasetOpLoop[idxL].pwrPdg[0][0] + | ||
3237 | pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2; | ||
3238 | } | ||
3239 | |||
3240 | while ((pcdac > ah->originalGain[i]) && | ||
3241 | (i < (AR9280_TX_GAIN_TABLE_SIZE - 1))) | ||
3242 | i++; | ||
3243 | } | ||
3244 | |||
3245 | static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah, | ||
3246 | int32_t txPower, u16 chain) | ||
3247 | { | ||
3248 | u32 tmpVal; | ||
3249 | u32 a; | ||
3250 | |||
3251 | tmpVal = REG_READ(ah, 0xa270); | ||
3252 | tmpVal = tmpVal & 0xFCFFFFFF; | ||
3253 | tmpVal = tmpVal | (0x3 << 24); | ||
3254 | REG_WRITE(ah, 0xa270, tmpVal); | ||
3255 | |||
3256 | tmpVal = REG_READ(ah, 0xb270); | ||
3257 | tmpVal = tmpVal & 0xFCFFFFFF; | ||
3258 | tmpVal = tmpVal | (0x3 << 24); | ||
3259 | REG_WRITE(ah, 0xb270, tmpVal); | ||
3260 | |||
3261 | if (chain == 0) { | ||
3262 | tmpVal = REG_READ(ah, 0xa398); | ||
3263 | tmpVal = tmpVal & 0xff00ffff; | ||
3264 | a = (txPower)&0xff; | ||
3265 | tmpVal = tmpVal | (a << 16); | ||
3266 | REG_WRITE(ah, 0xa398, tmpVal); | ||
3267 | } | ||
3268 | |||
3269 | if (chain == 1) { | ||
3270 | tmpVal = REG_READ(ah, 0xb398); | ||
3271 | tmpVal = tmpVal & 0xff00ffff; | ||
3272 | a = (txPower)&0xff; | ||
3273 | tmpVal = tmpVal | (a << 16); | ||
3274 | REG_WRITE(ah, 0xb398, tmpVal); | ||
3275 | } | ||
3276 | } | ||
3277 | |||
3278 | |||
3279 | static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah, | ||
3280 | struct ath9k_channel *chan, int16_t *pTxPowerIndexOffset) | ||
3281 | { | ||
3282 | struct cal_data_per_freq_ar9287 *pRawDataset; | ||
3283 | struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop; | ||
3284 | u8 *pCalBChans = NULL; | ||
3285 | u16 pdGainOverlap_t2; | ||
3286 | u8 pdadcValues[AR9287_NUM_PDADC_VALUES]; | ||
3287 | u16 gainBoundaries[AR9287_PD_GAINS_IN_MASK]; | ||
3288 | u16 numPiers = 0, i, j; | ||
3289 | int16_t tMinCalPower; | ||
3290 | u16 numXpdGain, xpdMask; | ||
3291 | u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0}; | ||
3292 | u32 reg32, regOffset, regChainOffset; | ||
3293 | int16_t modalIdx, diff = 0; | ||
3294 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; | ||
3295 | modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; | ||
3296 | xpdMask = pEepData->modalHeader.xpdGain; | ||
3297 | if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= | ||
3298 | AR9287_EEP_MINOR_VER_2) | ||
3299 | pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap; | ||
3300 | else | ||
3301 | pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), | ||
3302 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); | ||
3303 | |||
3304 | if (IS_CHAN_2GHZ(chan)) { | ||
3305 | pCalBChans = pEepData->calFreqPier2G; | ||
3306 | numPiers = AR9287_NUM_2G_CAL_PIERS; | ||
3307 | if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | ||
3308 | pRawDatasetOpenLoop = | ||
3309 | (struct cal_data_op_loop_ar9287 *) | ||
3310 | pEepData->calPierData2G[0]; | ||
3311 | ah->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0]; | ||
3312 | } | ||
3313 | } | ||
3314 | |||
3315 | numXpdGain = 0; | ||
3316 | for (i = 1; i <= AR9287_PD_GAINS_IN_MASK; i++) { | ||
3317 | if ((xpdMask >> (AR9287_PD_GAINS_IN_MASK - i)) & 1) { | ||
3318 | if (numXpdGain >= AR9287_NUM_PD_GAINS) | ||
3319 | break; | ||
3320 | xpdGainValues[numXpdGain] = | ||
3321 | (u16)(AR9287_PD_GAINS_IN_MASK-i); | ||
3322 | numXpdGain++; | ||
3323 | } | ||
3324 | } | ||
3325 | |||
3326 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, | ||
3327 | (numXpdGain - 1) & 0x3); | ||
3328 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, | ||
3329 | xpdGainValues[0]); | ||
3330 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, | ||
3331 | xpdGainValues[1]); | ||
3332 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, | ||
3333 | xpdGainValues[2]); | ||
3334 | |||
3335 | for (i = 0; i < AR9287_MAX_CHAINS; i++) { | ||
3336 | regChainOffset = i * 0x1000; | ||
3337 | if (pEepData->baseEepHeader.txMask & (1 << i)) { | ||
3338 | pRawDatasetOpenLoop = (struct cal_data_op_loop_ar9287 *) | ||
3339 | pEepData->calPierData2G[i]; | ||
3340 | if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | ||
3341 | int8_t txPower; | ||
3342 | ar9287_eeprom_get_tx_gain_index(ah, chan, | ||
3343 | pRawDatasetOpenLoop, | ||
3344 | pCalBChans, numPiers, | ||
3345 | &txPower); | ||
3346 | ar9287_eeprom_olpc_set_pdadcs(ah, txPower, i); | ||
3347 | } else { | ||
3348 | pRawDataset = | ||
3349 | (struct cal_data_per_freq_ar9287 *) | ||
3350 | pEepData->calPierData2G[i]; | ||
3351 | ath9k_hw_get_AR9287_gain_boundaries_pdadcs( | ||
3352 | ah, chan, pRawDataset, | ||
3353 | pCalBChans, numPiers, | ||
3354 | pdGainOverlap_t2, | ||
3355 | &tMinCalPower, gainBoundaries, | ||
3356 | pdadcValues, numXpdGain); | ||
3357 | } | ||
3358 | |||
3359 | if (i == 0) { | ||
3360 | if (!ath9k_hw_AR9287_get_eeprom( | ||
3361 | ah, EEP_OL_PWRCTRL)) { | ||
3362 | REG_WRITE(ah, AR_PHY_TPCRG5 + | ||
3363 | regChainOffset, | ||
3364 | SM(pdGainOverlap_t2, | ||
3365 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | | ||
3366 | SM(gainBoundaries[0], | ||
3367 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | ||
3368 | | SM(gainBoundaries[1], | ||
3369 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | ||
3370 | | SM(gainBoundaries[2], | ||
3371 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | ||
3372 | | SM(gainBoundaries[3], | ||
3373 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); | ||
3374 | } | ||
3375 | } | ||
3376 | |||
3377 | if ((int32_t)AR9287_PWR_TABLE_OFFSET_DB != | ||
3378 | pEepData->baseEepHeader.pwrTableOffset) { | ||
3379 | diff = (u16) | ||
3380 | (pEepData->baseEepHeader.pwrTableOffset | ||
3381 | - (int32_t)AR9287_PWR_TABLE_OFFSET_DB); | ||
3382 | diff *= 2; | ||
3383 | |||
3384 | for (j = 0; | ||
3385 | j < ((u16)AR9287_NUM_PDADC_VALUES-diff); | ||
3386 | j++) | ||
3387 | pdadcValues[j] = pdadcValues[j+diff]; | ||
3388 | |||
3389 | for (j = (u16)(AR9287_NUM_PDADC_VALUES-diff); | ||
3390 | j < AR9287_NUM_PDADC_VALUES; j++) | ||
3391 | pdadcValues[j] = | ||
3392 | pdadcValues[ | ||
3393 | AR9287_NUM_PDADC_VALUES-diff]; | ||
3394 | } | ||
3395 | if (!ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | ||
3396 | regOffset = AR_PHY_BASE + (672 << 2) + | ||
3397 | regChainOffset; | ||
3398 | for (j = 0; j < 32; j++) { | ||
3399 | reg32 = ((pdadcValues[4*j + 0] | ||
3400 | & 0xFF) << 0) | | ||
3401 | ((pdadcValues[4*j + 1] | ||
3402 | & 0xFF) << 8) | | ||
3403 | ((pdadcValues[4*j + 2] | ||
3404 | & 0xFF) << 16) | | ||
3405 | ((pdadcValues[4*j + 3] | ||
3406 | & 0xFF) << 24) ; | ||
3407 | REG_WRITE(ah, regOffset, reg32); | ||
3408 | |||
3409 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
3410 | "PDADC (%d,%4x): %4.4x %8.8x\n", | ||
3411 | i, regChainOffset, regOffset, | ||
3412 | reg32); | ||
3413 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
3414 | "PDADC: Chain %d | " | ||
3415 | "PDADC %3d Value %3d | " | ||
3416 | "PDADC %3d Value %3d | " | ||
3417 | "PDADC %3d Value %3d | " | ||
3418 | "PDADC %3d Value %3d |\n", | ||
3419 | i, 4 * j, pdadcValues[4 * j], | ||
3420 | 4 * j + 1, | ||
3421 | pdadcValues[4 * j + 1], | ||
3422 | 4 * j + 2, | ||
3423 | pdadcValues[4 * j + 2], | ||
3424 | 4 * j + 3, | ||
3425 | pdadcValues[4 * j + 3]); | ||
3426 | |||
3427 | regOffset += 4; | ||
3428 | } | ||
3429 | } | ||
3430 | } | ||
3431 | } | ||
3432 | |||
3433 | *pTxPowerIndexOffset = 0; | ||
3434 | } | ||
3435 | |||
3436 | |||
3437 | static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, | ||
3438 | struct ath9k_channel *chan, int16_t *ratesArray, u16 cfgCtl, | ||
3439 | u16 AntennaReduction, u16 twiceMaxRegulatoryPower, | ||
3440 | u16 powerLimit) | ||
3441 | { | ||
3442 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 | ||
3443 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 | ||
3444 | |||
3445 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
3446 | static const u16 tpScaleReductionTable[5] = { 0, 3, 6, 9, | ||
3447 | AR5416_MAX_RATE_POWER }; | ||
3448 | int i; | ||
3449 | int16_t twiceLargestAntenna; | ||
3450 | struct cal_ctl_data_ar9287 *rep; | ||
3451 | struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} }, | ||
3452 | targetPowerCck = {0, {0, 0, 0, 0} }; | ||
3453 | struct cal_target_power_leg targetPowerOfdmExt = {0, {0, 0, 0, 0} }, | ||
3454 | targetPowerCckExt = {0, {0, 0, 0, 0} }; | ||
3455 | struct cal_target_power_ht targetPowerHt20, | ||
3456 | targetPowerHt40 = {0, {0, 0, 0, 0} }; | ||
3457 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; | ||
3458 | u16 ctlModesFor11g[] = {CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, | ||
3459 | CTL_11G_EXT, CTL_2GHT40}; | ||
3460 | u16 numCtlModes = 0, *pCtlMode = NULL, ctlMode, freq; | ||
3461 | struct chan_centers centers; | ||
3462 | int tx_chainmask; | ||
3463 | u16 twiceMinEdgePower; | ||
3464 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; | ||
3465 | tx_chainmask = ah->txchainmask; | ||
3466 | |||
3467 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
3468 | |||
3469 | twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0], | ||
3470 | pEepData->modalHeader.antennaGainCh[1]); | ||
3471 | |||
3472 | twiceLargestAntenna = (int16_t)min((AntennaReduction) - | ||
3473 | twiceLargestAntenna, 0); | ||
3474 | |||
3475 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; | ||
3476 | if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) | ||
3477 | maxRegAllowedPower -= | ||
3478 | (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); | ||
3479 | |||
3480 | scaledPower = min(powerLimit, maxRegAllowedPower); | ||
3481 | |||
3482 | switch (ar5416_get_ntxchains(tx_chainmask)) { | ||
3483 | case 1: | ||
3484 | break; | ||
3485 | case 2: | ||
3486 | scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; | ||
3487 | break; | ||
3488 | case 3: | ||
3489 | scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; | ||
3490 | break; | ||
3491 | } | ||
3492 | scaledPower = max((u16)0, scaledPower); | ||
3493 | |||
3494 | if (IS_CHAN_2GHZ(chan)) { | ||
3495 | numCtlModes = ARRAY_SIZE(ctlModesFor11g) - | ||
3496 | SUB_NUM_CTL_MODES_AT_2G_40; | ||
3497 | pCtlMode = ctlModesFor11g; | ||
3498 | |||
3499 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
3500 | pEepData->calTargetPowerCck, | ||
3501 | AR9287_NUM_2G_CCK_TARGET_POWERS, | ||
3502 | &targetPowerCck, 4, false); | ||
3503 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
3504 | pEepData->calTargetPower2G, | ||
3505 | AR9287_NUM_2G_20_TARGET_POWERS, | ||
3506 | &targetPowerOfdm, 4, false); | ||
3507 | ath9k_hw_get_target_powers(ah, chan, | ||
3508 | pEepData->calTargetPower2GHT20, | ||
3509 | AR9287_NUM_2G_20_TARGET_POWERS, | ||
3510 | &targetPowerHt20, 8, false); | ||
3511 | |||
3512 | if (IS_CHAN_HT40(chan)) { | ||
3513 | numCtlModes = ARRAY_SIZE(ctlModesFor11g); | ||
3514 | ath9k_hw_get_target_powers(ah, chan, | ||
3515 | pEepData->calTargetPower2GHT40, | ||
3516 | AR9287_NUM_2G_40_TARGET_POWERS, | ||
3517 | &targetPowerHt40, 8, true); | ||
3518 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
3519 | pEepData->calTargetPowerCck, | ||
3520 | AR9287_NUM_2G_CCK_TARGET_POWERS, | ||
3521 | &targetPowerCckExt, 4, true); | ||
3522 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
3523 | pEepData->calTargetPower2G, | ||
3524 | AR9287_NUM_2G_20_TARGET_POWERS, | ||
3525 | &targetPowerOfdmExt, 4, true); | ||
3526 | } | ||
3527 | } | ||
3528 | |||
3529 | for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { | ||
3530 | |||
3531 | bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || | ||
3532 | (pCtlMode[ctlMode] == CTL_2GHT40); | ||
3533 | if (isHt40CtlMode) | ||
3534 | freq = centers.synth_center; | ||
3535 | else if (pCtlMode[ctlMode] & EXT_ADDITIVE) | ||
3536 | freq = centers.ext_center; | ||
3537 | else | ||
3538 | freq = centers.ctl_center; | ||
3539 | |||
3540 | |||
3541 | if (ah->eep_ops->get_eeprom_ver(ah) == 14 && | ||
3542 | ah->eep_ops->get_eeprom_rev(ah) <= 2) | ||
3543 | twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
3544 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
3545 | "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d," | ||
3546 | "EXT_ADDITIVE %d\n", ctlMode, numCtlModes, | ||
3547 | isHt40CtlMode, (pCtlMode[ctlMode] & EXT_ADDITIVE)); | ||
3548 | for (i = 0; (i < AR9287_NUM_CTLS) | ||
3549 | && pEepData->ctlIndex[i]; i++) { | ||
3550 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
3551 | "LOOP-Ctlidx %d: cfgCtl 0x%2.2x" | ||
3552 | "pCtlMode 0x%2.2x ctlIndex 0x%2.2x" | ||
3553 | "chan %d chanctl=xxxx\n", | ||
3554 | i, cfgCtl, pCtlMode[ctlMode], | ||
3555 | pEepData->ctlIndex[i], chan->channel); | ||
3556 | |||
3557 | if ((((cfgCtl & ~CTL_MODE_M) | | ||
3558 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
3559 | pEepData->ctlIndex[i]) || | ||
3560 | (((cfgCtl & ~CTL_MODE_M) | | ||
3561 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
3562 | ((pEepData->ctlIndex[i] & | ||
3563 | CTL_MODE_M) | SD_NO_CTL))) { | ||
3564 | |||
3565 | rep = &(pEepData->ctlData[i]); | ||
3566 | twiceMinEdgePower = ath9k_hw_get_max_edge_power( | ||
3567 | freq, | ||
3568 | rep->ctlEdges[ar5416_get_ntxchains( | ||
3569 | tx_chainmask) - 1], | ||
3570 | IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES); | ||
3571 | |||
3572 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
3573 | "MATCH-EE_IDX %d: ch %d is2 %d" | ||
3574 | "2xMinEdge %d chainmask %d chains %d\n", | ||
3575 | i, freq, IS_CHAN_2GHZ(chan), | ||
3576 | twiceMinEdgePower, tx_chainmask, | ||
3577 | ar5416_get_ntxchains(tx_chainmask)); | ||
3578 | |||
3579 | if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) | ||
3580 | twiceMaxEdgePower = min( | ||
3581 | twiceMaxEdgePower, | ||
3582 | twiceMinEdgePower); | ||
3583 | else { | ||
3584 | twiceMaxEdgePower = twiceMinEdgePower; | ||
3585 | break; | ||
3586 | } | ||
3587 | } | ||
3588 | } | ||
3589 | |||
3590 | minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); | ||
3591 | |||
3592 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
3593 | "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d" | ||
3594 | "sP %d minCtlPwr %d\n", | ||
3595 | ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, | ||
3596 | scaledPower, minCtlPower); | ||
3597 | |||
3598 | |||
3599 | switch (pCtlMode[ctlMode]) { | ||
3600 | |||
3601 | case CTL_11B: | ||
3602 | for (i = 0; | ||
3603 | i < ARRAY_SIZE(targetPowerCck.tPow2x); | ||
3604 | i++) { | ||
3605 | targetPowerCck.tPow2x[i] = (u8)min( | ||
3606 | (u16)targetPowerCck.tPow2x[i], | ||
3607 | minCtlPower); | ||
3608 | } | ||
3609 | break; | ||
3610 | case CTL_11A: | ||
3611 | case CTL_11G: | ||
3612 | for (i = 0; | ||
3613 | i < ARRAY_SIZE(targetPowerOfdm.tPow2x); | ||
3614 | i++) { | ||
3615 | targetPowerOfdm.tPow2x[i] = (u8)min( | ||
3616 | (u16)targetPowerOfdm.tPow2x[i], | ||
3617 | minCtlPower); | ||
3618 | } | ||
3619 | break; | ||
3620 | case CTL_5GHT20: | ||
3621 | case CTL_2GHT20: | ||
3622 | for (i = 0; | ||
3623 | i < ARRAY_SIZE(targetPowerHt20.tPow2x); | ||
3624 | i++) { | ||
3625 | targetPowerHt20.tPow2x[i] = (u8)min( | ||
3626 | (u16)targetPowerHt20.tPow2x[i], | ||
3627 | minCtlPower); | ||
3628 | } | ||
3629 | break; | ||
3630 | case CTL_11B_EXT: | ||
3631 | targetPowerCckExt.tPow2x[0] = (u8)min( | ||
3632 | (u16)targetPowerCckExt.tPow2x[0], | ||
3633 | minCtlPower); | ||
3634 | break; | ||
3635 | case CTL_11A_EXT: | ||
3636 | case CTL_11G_EXT: | ||
3637 | targetPowerOfdmExt.tPow2x[0] = (u8)min( | ||
3638 | (u16)targetPowerOfdmExt.tPow2x[0], | ||
3639 | minCtlPower); | ||
3640 | break; | ||
3641 | case CTL_5GHT40: | ||
3642 | case CTL_2GHT40: | ||
3643 | for (i = 0; | ||
3644 | i < ARRAY_SIZE(targetPowerHt40.tPow2x); | ||
3645 | i++) { | ||
3646 | targetPowerHt40.tPow2x[i] = (u8)min( | ||
3647 | (u16)targetPowerHt40.tPow2x[i], | ||
3648 | minCtlPower); | ||
3649 | } | ||
3650 | break; | ||
3651 | default: | ||
3652 | break; | ||
3653 | } | ||
3654 | } | ||
3655 | |||
3656 | ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = | ||
3657 | ratesArray[rate18mb] = ratesArray[rate24mb] = | ||
3658 | targetPowerOfdm.tPow2x[0]; | ||
3659 | ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; | ||
3660 | ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; | ||
3661 | ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; | ||
3662 | ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; | ||
3663 | |||
3664 | for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) | ||
3665 | ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; | ||
3666 | |||
3667 | if (IS_CHAN_2GHZ(chan)) { | ||
3668 | ratesArray[rate1l] = targetPowerCck.tPow2x[0]; | ||
3669 | ratesArray[rate2s] = ratesArray[rate2l] = | ||
3670 | targetPowerCck.tPow2x[1]; | ||
3671 | ratesArray[rate5_5s] = ratesArray[rate5_5l] = | ||
3672 | targetPowerCck.tPow2x[2]; | ||
3673 | ratesArray[rate11s] = ratesArray[rate11l] = | ||
3674 | targetPowerCck.tPow2x[3]; | ||
3675 | } | ||
3676 | if (IS_CHAN_HT40(chan)) { | ||
3677 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) | ||
3678 | ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i]; | ||
3679 | |||
3680 | ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; | ||
3681 | ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; | ||
3682 | ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; | ||
3683 | if (IS_CHAN_2GHZ(chan)) | ||
3684 | ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; | ||
3685 | } | ||
3686 | #undef REDUCE_SCALED_POWER_BY_TWO_CHAIN | ||
3687 | #undef REDUCE_SCALED_POWER_BY_THREE_CHAIN | ||
3688 | } | ||
3689 | |||
3690 | static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, | ||
3691 | struct ath9k_channel *chan, u16 cfgCtl, | ||
3692 | u8 twiceAntennaReduction, u8 twiceMaxRegulatoryPower, | ||
3693 | u8 powerLimit) | ||
3694 | { | ||
3695 | #define INCREASE_MAXPOW_BY_TWO_CHAIN 6 | ||
3696 | #define INCREASE_MAXPOW_BY_THREE_CHAIN 10 | ||
3697 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; | ||
3698 | struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; | ||
3699 | int16_t ratesArray[Ar5416RateSize]; | ||
3700 | int16_t txPowerIndexOffset = 0; | ||
3701 | u8 ht40PowerIncForPdadc = 2; | ||
3702 | int i; | ||
3703 | memset(ratesArray, 0, sizeof(ratesArray)); | ||
3704 | |||
3705 | if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= | ||
3706 | AR9287_EEP_MINOR_VER_2) | ||
3707 | ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; | ||
3708 | |||
3709 | ath9k_hw_set_AR9287_power_per_rate_table(ah, chan, | ||
3710 | &ratesArray[0], cfgCtl, | ||
3711 | twiceAntennaReduction, | ||
3712 | twiceMaxRegulatoryPower, | ||
3713 | powerLimit); | ||
3714 | |||
3715 | |||
3716 | ath9k_hw_set_AR9287_power_cal_table(ah, chan, &txPowerIndexOffset); | ||
3717 | |||
3718 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { | ||
3719 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); | ||
3720 | if (ratesArray[i] > AR9287_MAX_RATE_POWER) | ||
3721 | ratesArray[i] = AR9287_MAX_RATE_POWER; | ||
3722 | } | ||
3723 | |||
3724 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
3725 | for (i = 0; i < Ar5416RateSize; i++) | ||
3726 | ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; | ||
3727 | } | ||
3728 | |||
3729 | |||
3730 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, | ||
3731 | ATH9K_POW_SM(ratesArray[rate18mb], 24) | ||
3732 | | ATH9K_POW_SM(ratesArray[rate12mb], 16) | ||
3733 | | ATH9K_POW_SM(ratesArray[rate9mb], 8) | ||
3734 | | ATH9K_POW_SM(ratesArray[rate6mb], 0) | ||
3735 | ); | ||
3736 | |||
3737 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, | ||
3738 | ATH9K_POW_SM(ratesArray[rate54mb], 24) | ||
3739 | | ATH9K_POW_SM(ratesArray[rate48mb], 16) | ||
3740 | | ATH9K_POW_SM(ratesArray[rate36mb], 8) | ||
3741 | | ATH9K_POW_SM(ratesArray[rate24mb], 0) | ||
3742 | ); | ||
3743 | |||
3744 | if (IS_CHAN_2GHZ(chan)) { | ||
3745 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, | ||
3746 | ATH9K_POW_SM(ratesArray[rate2s], 24) | ||
3747 | | ATH9K_POW_SM(ratesArray[rate2l], 16) | ||
3748 | | ATH9K_POW_SM(ratesArray[rateXr], 8) | ||
3749 | | ATH9K_POW_SM(ratesArray[rate1l], 0) | ||
3750 | ); | ||
3751 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, | ||
3752 | ATH9K_POW_SM(ratesArray[rate11s], 24) | ||
3753 | | ATH9K_POW_SM(ratesArray[rate11l], 16) | ||
3754 | | ATH9K_POW_SM(ratesArray[rate5_5s], 8) | ||
3755 | | ATH9K_POW_SM(ratesArray[rate5_5l], 0) | ||
3756 | ); | ||
3757 | } | ||
3758 | |||
3759 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, | ||
3760 | ATH9K_POW_SM(ratesArray[rateHt20_3], 24) | ||
3761 | | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) | ||
3762 | | ATH9K_POW_SM(ratesArray[rateHt20_1], 8) | ||
3763 | | ATH9K_POW_SM(ratesArray[rateHt20_0], 0) | ||
3764 | ); | ||
3765 | |||
3766 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, | ||
3767 | ATH9K_POW_SM(ratesArray[rateHt20_7], 24) | ||
3768 | | ATH9K_POW_SM(ratesArray[rateHt20_6], 16) | ||
3769 | | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) | ||
3770 | | ATH9K_POW_SM(ratesArray[rateHt20_4], 0) | ||
3771 | ); | ||
3772 | |||
3773 | if (IS_CHAN_HT40(chan)) { | ||
3774 | if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | ||
3775 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, | ||
3776 | ATH9K_POW_SM(ratesArray[rateHt40_3], 24) | ||
3777 | | ATH9K_POW_SM(ratesArray[rateHt40_2], 16) | ||
3778 | | ATH9K_POW_SM(ratesArray[rateHt40_1], 8) | ||
3779 | | ATH9K_POW_SM(ratesArray[rateHt40_0], 0) | ||
3780 | ); | ||
3781 | |||
3782 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, | ||
3783 | ATH9K_POW_SM(ratesArray[rateHt40_7], 24) | ||
3784 | | ATH9K_POW_SM(ratesArray[rateHt40_6], 16) | ||
3785 | | ATH9K_POW_SM(ratesArray[rateHt40_5], 8) | ||
3786 | | ATH9K_POW_SM(ratesArray[rateHt40_4], 0) | ||
3787 | ); | ||
3788 | } else { | ||
3789 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, | ||
3790 | ATH9K_POW_SM(ratesArray[rateHt40_3] + | ||
3791 | ht40PowerIncForPdadc, 24) | ||
3792 | | ATH9K_POW_SM(ratesArray[rateHt40_2] + | ||
3793 | ht40PowerIncForPdadc, 16) | ||
3794 | | ATH9K_POW_SM(ratesArray[rateHt40_1] + | ||
3795 | ht40PowerIncForPdadc, 8) | ||
3796 | | ATH9K_POW_SM(ratesArray[rateHt40_0] + | ||
3797 | ht40PowerIncForPdadc, 0) | ||
3798 | ); | ||
3799 | |||
3800 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, | ||
3801 | ATH9K_POW_SM(ratesArray[rateHt40_7] + | ||
3802 | ht40PowerIncForPdadc, 24) | ||
3803 | | ATH9K_POW_SM(ratesArray[rateHt40_6] + | ||
3804 | ht40PowerIncForPdadc, 16) | ||
3805 | | ATH9K_POW_SM(ratesArray[rateHt40_5] + | ||
3806 | ht40PowerIncForPdadc, 8) | ||
3807 | | ATH9K_POW_SM(ratesArray[rateHt40_4] + | ||
3808 | ht40PowerIncForPdadc, 0) | ||
3809 | ); | ||
3810 | |||
3811 | } | ||
3812 | |||
3813 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, | ||
3814 | ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) | ||
3815 | | ATH9K_POW_SM(ratesArray[rateExtCck], 16) | ||
3816 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | ||
3817 | | ATH9K_POW_SM(ratesArray[rateDupCck], 0) | ||
3818 | ); | ||
3819 | } | ||
3820 | |||
3821 | |||
3822 | if (IS_CHAN_2GHZ(chan)) | ||
3823 | i = rate1l; | ||
3824 | else | ||
3825 | i = rate6mb; | ||
3826 | |||
3827 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
3828 | ah->regulatory.max_power_level = | ||
3829 | ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2; | ||
3830 | else | ||
3831 | ah->regulatory.max_power_level = ratesArray[i]; | ||
3832 | |||
3833 | switch (ar5416_get_ntxchains(ah->txchainmask)) { | ||
3834 | case 1: | ||
3835 | break; | ||
3836 | case 2: | ||
3837 | ah->regulatory.max_power_level += | ||
3838 | INCREASE_MAXPOW_BY_TWO_CHAIN; | ||
3839 | break; | ||
3840 | case 3: | ||
3841 | ah->regulatory.max_power_level += | ||
3842 | INCREASE_MAXPOW_BY_THREE_CHAIN; | ||
3843 | break; | ||
3844 | default: | ||
3845 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
3846 | "Invalid chainmask configuration\n"); | ||
3847 | break; | ||
3848 | } | ||
3849 | } | ||
3850 | |||
3851 | static void ath9k_hw_AR9287_set_addac(struct ath_hw *ah, | ||
3852 | struct ath9k_channel *chan) | ||
3853 | { | ||
3854 | return; | ||
3855 | } | ||
3856 | |||
3857 | static void ath9k_hw_AR9287_set_board_values(struct ath_hw *ah, | ||
3858 | struct ath9k_channel *chan) | ||
3859 | { | ||
3860 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | ||
3861 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; | ||
3862 | |||
3863 | u16 antWrites[AR9287_ANT_16S]; | ||
3864 | u32 regChainOffset; | ||
3865 | u8 txRxAttenLocal; | ||
3866 | int i, j, offset_num; | ||
3867 | |||
3868 | pModal = &eep->modalHeader; | ||
3869 | |||
3870 | antWrites[0] = (u16)((pModal->antCtrlCommon >> 28) & 0xF); | ||
3871 | antWrites[1] = (u16)((pModal->antCtrlCommon >> 24) & 0xF); | ||
3872 | antWrites[2] = (u16)((pModal->antCtrlCommon >> 20) & 0xF); | ||
3873 | antWrites[3] = (u16)((pModal->antCtrlCommon >> 16) & 0xF); | ||
3874 | antWrites[4] = (u16)((pModal->antCtrlCommon >> 12) & 0xF); | ||
3875 | antWrites[5] = (u16)((pModal->antCtrlCommon >> 8) & 0xF); | ||
3876 | antWrites[6] = (u16)((pModal->antCtrlCommon >> 4) & 0xF); | ||
3877 | antWrites[7] = (u16)(pModal->antCtrlCommon & 0xF); | ||
3878 | |||
3879 | offset_num = 8; | ||
3880 | |||
3881 | for (i = 0, j = offset_num; i < AR9287_MAX_CHAINS; i++) { | ||
3882 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 28) & 0xf); | ||
3883 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 10) & 0x3); | ||
3884 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 8) & 0x3); | ||
3885 | antWrites[j++] = 0; | ||
3886 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 6) & 0x3); | ||
3887 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 4) & 0x3); | ||
3888 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 2) & 0x3); | ||
3889 | antWrites[j++] = (u16)(pModal->antCtrlChain[i] & 0x3); | ||
3890 | } | ||
3891 | |||
3892 | |||
3893 | REG_WRITE(ah, AR_PHY_SWITCH_COM, | ||
3894 | ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); | ||
3895 | |||
3896 | for (i = 0; i < AR9287_MAX_CHAINS; i++) { | ||
3897 | regChainOffset = i * 0x1000; | ||
3898 | |||
3899 | REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, | ||
3900 | pModal->antCtrlChain[i]); | ||
3901 | |||
3902 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, | ||
3903 | (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) | ||
3904 | & ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | | ||
3905 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | | ||
3906 | SM(pModal->iqCalICh[i], | ||
3907 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | | ||
3908 | SM(pModal->iqCalQCh[i], | ||
3909 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); | ||
3910 | |||
3911 | txRxAttenLocal = pModal->txRxAttenCh[i]; | ||
3912 | |||
3913 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
3914 | AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, | ||
3915 | pModal->bswMargin[i]); | ||
3916 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
3917 | AR_PHY_GAIN_2GHZ_XATTEN1_DB, | ||
3918 | pModal->bswAtten[i]); | ||
3919 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, | ||
3920 | AR9280_PHY_RXGAIN_TXRX_ATTEN, | ||
3921 | txRxAttenLocal); | ||
3922 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, | ||
3923 | AR9280_PHY_RXGAIN_TXRX_MARGIN, | ||
3924 | pModal->rxTxMarginCh[i]); | ||
3925 | } | ||
3926 | |||
3927 | |||
3928 | if (IS_CHAN_HT40(chan)) | ||
3929 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, | ||
3930 | AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40); | ||
3931 | else | ||
3932 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, | ||
3933 | AR_PHY_SETTLING_SWITCH, pModal->switchSettling); | ||
3934 | |||
3935 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, | ||
3936 | AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize); | ||
3937 | |||
3938 | REG_WRITE(ah, AR_PHY_RF_CTL4, | ||
3939 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) | ||
3940 | | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) | ||
3941 | | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) | ||
3942 | | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); | ||
3943 | |||
3944 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, | ||
3945 | AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn); | ||
3946 | |||
3947 | REG_RMW_FIELD(ah, AR_PHY_CCA, | ||
3948 | AR9280_PHY_CCA_THRESH62, pModal->thresh62); | ||
3949 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, | ||
3950 | AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62); | ||
3951 | |||
3952 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB1, | ||
3953 | AR9287_AN_RF2G3_DB1_S, pModal->db1); | ||
3954 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB2, | ||
3955 | AR9287_AN_RF2G3_DB2_S, pModal->db2); | ||
3956 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, | ||
3957 | AR9287_AN_RF2G3_OB_CCK, | ||
3958 | AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck); | ||
3959 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, | ||
3960 | AR9287_AN_RF2G3_OB_PSK, | ||
3961 | AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk); | ||
3962 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, | ||
3963 | AR9287_AN_RF2G3_OB_QAM, | ||
3964 | AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam); | ||
3965 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, | ||
3966 | AR9287_AN_RF2G3_OB_PAL_OFF, | ||
3967 | AR9287_AN_RF2G3_OB_PAL_OFF_S, | ||
3968 | pModal->ob_pal_off); | ||
3969 | |||
3970 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | ||
3971 | AR9287_AN_RF2G3_DB1, AR9287_AN_RF2G3_DB1_S, | ||
3972 | pModal->db1); | ||
3973 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, AR9287_AN_RF2G3_DB2, | ||
3974 | AR9287_AN_RF2G3_DB2_S, pModal->db2); | ||
3975 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | ||
3976 | AR9287_AN_RF2G3_OB_CCK, | ||
3977 | AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck); | ||
3978 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | ||
3979 | AR9287_AN_RF2G3_OB_PSK, | ||
3980 | AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk); | ||
3981 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | ||
3982 | AR9287_AN_RF2G3_OB_QAM, | ||
3983 | AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam); | ||
3984 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | ||
3985 | AR9287_AN_RF2G3_OB_PAL_OFF, | ||
3986 | AR9287_AN_RF2G3_OB_PAL_OFF_S, | ||
3987 | pModal->ob_pal_off); | ||
3988 | |||
3989 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, | ||
3990 | AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart); | ||
3991 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, | ||
3992 | AR_PHY_TX_END_PA_ON, pModal->txFrameToPaOn); | ||
3993 | |||
3994 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TOP2, | ||
3995 | AR9287_AN_TOP2_XPABIAS_LVL, | ||
3996 | AR9287_AN_TOP2_XPABIAS_LVL_S, | ||
3997 | pModal->xpaBiasLvl); | ||
3998 | } | ||
3999 | |||
4000 | static u8 ath9k_hw_AR9287_get_num_ant_config(struct ath_hw *ah, | ||
4001 | enum ieee80211_band freq_band) | ||
4002 | { | ||
4003 | return 1; | ||
4004 | } | ||
4005 | |||
4006 | |||
4007 | |||
4008 | |||
4009 | static u16 ath9k_hw_AR9287_get_eeprom_antenna_cfg(struct ath_hw *ah, | ||
4010 | struct ath9k_channel *chan) | ||
4011 | { | ||
4012 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | ||
4013 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; | ||
4014 | return pModal->antCtrlCommon & 0xFFFF; | ||
4015 | } | ||
4016 | |||
4017 | |||
4018 | static u16 ath9k_hw_AR9287_get_spur_channel(struct ath_hw *ah, | ||
4019 | u16 i, bool is2GHz) | ||
4020 | { | ||
4021 | #define EEP_MAP9287_SPURCHAN \ | ||
4022 | (ah->eeprom.map9287.modalHeader.spurChans[i].spurChan) | ||
4023 | u16 spur_val = AR_NO_SPUR; | ||
4024 | |||
4025 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
4026 | "Getting spur idx %d is2Ghz. %d val %x\n", | ||
4027 | i, is2GHz, ah->config.spurchans[i][is2GHz]); | ||
4028 | |||
4029 | switch (ah->config.spurmode) { | ||
4030 | case SPUR_DISABLE: | ||
4031 | break; | ||
4032 | case SPUR_ENABLE_IOCTL: | ||
4033 | spur_val = ah->config.spurchans[i][is2GHz]; | ||
4034 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
4035 | "Getting spur val from new loc. %d\n", spur_val); | ||
4036 | break; | ||
4037 | case SPUR_ENABLE_EEPROM: | ||
4038 | spur_val = EEP_MAP9287_SPURCHAN; | ||
4039 | break; | ||
4040 | } | ||
4041 | |||
4042 | return spur_val; | ||
4043 | |||
4044 | #undef EEP_MAP9287_SPURCHAN | ||
4045 | } | ||
4046 | |||
4047 | static struct eeprom_ops eep_AR9287_ops = { | ||
4048 | .check_eeprom = ath9k_hw_AR9287_check_eeprom, | ||
4049 | .get_eeprom = ath9k_hw_AR9287_get_eeprom, | ||
4050 | .fill_eeprom = ath9k_hw_AR9287_fill_eeprom, | ||
4051 | .get_eeprom_ver = ath9k_hw_AR9287_get_eeprom_ver, | ||
4052 | .get_eeprom_rev = ath9k_hw_AR9287_get_eeprom_rev, | ||
4053 | .get_num_ant_config = ath9k_hw_AR9287_get_num_ant_config, | ||
4054 | .get_eeprom_antenna_cfg = ath9k_hw_AR9287_get_eeprom_antenna_cfg, | ||
4055 | .set_board_values = ath9k_hw_AR9287_set_board_values, | ||
4056 | .set_addac = ath9k_hw_AR9287_set_addac, | ||
4057 | .set_txpower = ath9k_hw_AR9287_set_txpower, | ||
4058 | .get_spur_channel = ath9k_hw_AR9287_get_spur_channel | ||
4059 | }; | ||
4060 | |||
4061 | |||
4062 | int ath9k_hw_eeprom_init(struct ath_hw *ah) | 257 | int ath9k_hw_eeprom_init(struct ath_hw *ah) |
4063 | { | 258 | { |
4064 | int status; | 259 | int status; |
260 | |||
4065 | if (AR_SREV_9287(ah)) { | 261 | if (AR_SREV_9287(ah)) { |
4066 | ah->eep_map = EEP_MAP_AR9287; | 262 | ah->eep_map = EEP_MAP_AR9287; |
4067 | ah->eep_ops = &eep_AR9287_ops; | 263 | ah->eep_ops = &eep_AR9287_ops; |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index db77e90ed9ab..4fe33f7eee9d 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h | |||
@@ -385,106 +385,124 @@ struct calDataPerFreqOpLoop { | |||
385 | } __packed; | 385 | } __packed; |
386 | 386 | ||
387 | struct modal_eep_4k_header { | 387 | struct modal_eep_4k_header { |
388 | u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS]; | 388 | u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS]; |
389 | u32 antCtrlCommon; | 389 | u32 antCtrlCommon; |
390 | u8 antennaGainCh[AR5416_EEP4K_MAX_CHAINS]; | 390 | u8 antennaGainCh[AR5416_EEP4K_MAX_CHAINS]; |
391 | u8 switchSettling; | 391 | u8 switchSettling; |
392 | u8 txRxAttenCh[AR5416_EEP4K_MAX_CHAINS]; | 392 | u8 txRxAttenCh[AR5416_EEP4K_MAX_CHAINS]; |
393 | u8 rxTxMarginCh[AR5416_EEP4K_MAX_CHAINS]; | 393 | u8 rxTxMarginCh[AR5416_EEP4K_MAX_CHAINS]; |
394 | u8 adcDesiredSize; | 394 | u8 adcDesiredSize; |
395 | u8 pgaDesiredSize; | 395 | u8 pgaDesiredSize; |
396 | u8 xlnaGainCh[AR5416_EEP4K_MAX_CHAINS]; | 396 | u8 xlnaGainCh[AR5416_EEP4K_MAX_CHAINS]; |
397 | u8 txEndToXpaOff; | 397 | u8 txEndToXpaOff; |
398 | u8 txEndToRxOn; | 398 | u8 txEndToRxOn; |
399 | u8 txFrameToXpaOn; | 399 | u8 txFrameToXpaOn; |
400 | u8 thresh62; | 400 | u8 thresh62; |
401 | u8 noiseFloorThreshCh[AR5416_EEP4K_MAX_CHAINS]; | 401 | u8 noiseFloorThreshCh[AR5416_EEP4K_MAX_CHAINS]; |
402 | u8 xpdGain; | 402 | u8 xpdGain; |
403 | u8 xpd; | 403 | u8 xpd; |
404 | u8 iqCalICh[AR5416_EEP4K_MAX_CHAINS]; | 404 | u8 iqCalICh[AR5416_EEP4K_MAX_CHAINS]; |
405 | u8 iqCalQCh[AR5416_EEP4K_MAX_CHAINS]; | 405 | u8 iqCalQCh[AR5416_EEP4K_MAX_CHAINS]; |
406 | u8 pdGainOverlap; | 406 | u8 pdGainOverlap; |
407 | u8 ob_01; | 407 | #ifdef __BIG_ENDIAN_BITFIELD |
408 | u8 db1_01; | 408 | u8 ob_1:4, ob_0:4; |
409 | u8 xpaBiasLvl; | 409 | u8 db1_1:4, db1_0:4; |
410 | u8 txFrameToDataStart; | 410 | #else |
411 | u8 txFrameToPaOn; | 411 | u8 ob_0:4, ob_1:4; |
412 | u8 ht40PowerIncForPdadc; | 412 | u8 db1_0:4, db1_1:4; |
413 | u8 bswAtten[AR5416_EEP4K_MAX_CHAINS]; | 413 | #endif |
414 | u8 bswMargin[AR5416_EEP4K_MAX_CHAINS]; | 414 | u8 xpaBiasLvl; |
415 | u8 swSettleHt40; | 415 | u8 txFrameToDataStart; |
416 | u8 xatten2Db[AR5416_EEP4K_MAX_CHAINS]; | 416 | u8 txFrameToPaOn; |
417 | u8 xatten2Margin[AR5416_EEP4K_MAX_CHAINS]; | 417 | u8 ht40PowerIncForPdadc; |
418 | u8 db2_01; | 418 | u8 bswAtten[AR5416_EEP4K_MAX_CHAINS]; |
419 | u8 version; | 419 | u8 bswMargin[AR5416_EEP4K_MAX_CHAINS]; |
420 | u16 ob_234; | 420 | u8 swSettleHt40; |
421 | u16 db1_234; | 421 | u8 xatten2Db[AR5416_EEP4K_MAX_CHAINS]; |
422 | u16 db2_234; | 422 | u8 xatten2Margin[AR5416_EEP4K_MAX_CHAINS]; |
423 | u8 futureModal[4]; | 423 | #ifdef __BIG_ENDIAN_BITFIELD |
424 | 424 | u8 db2_1:4, db2_0:4; | |
425 | #else | ||
426 | u8 db2_0:4, db2_1:4; | ||
427 | #endif | ||
428 | u8 version; | ||
429 | #ifdef __BIG_ENDIAN_BITFIELD | ||
430 | u8 ob_3:4, ob_2:4; | ||
431 | u8 antdiv_ctl1:4, ob_4:4; | ||
432 | u8 db1_3:4, db1_2:4; | ||
433 | u8 antdiv_ctl2:4, db1_4:4; | ||
434 | u8 db2_2:4, db2_3:4; | ||
435 | u8 reserved:4, db2_4:4; | ||
436 | #else | ||
437 | u8 ob_2:4, ob_3:4; | ||
438 | u8 ob_4:4, antdiv_ctl1:4; | ||
439 | u8 db1_2:4, db1_3:4; | ||
440 | u8 db1_4:4, antdiv_ctl2:4; | ||
441 | u8 db2_2:4, db2_3:4; | ||
442 | u8 db2_4:4, reserved:4; | ||
443 | #endif | ||
444 | u8 futureModal[4]; | ||
425 | struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; | 445 | struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; |
426 | } __packed; | 446 | } __packed; |
427 | 447 | ||
428 | struct base_eep_ar9287_header { | 448 | struct base_eep_ar9287_header { |
429 | u16 length; | 449 | u16 length; |
430 | u16 checksum; | 450 | u16 checksum; |
431 | u16 version; | 451 | u16 version; |
432 | u8 opCapFlags; | 452 | u8 opCapFlags; |
433 | u8 eepMisc; | 453 | u8 eepMisc; |
434 | u16 regDmn[2]; | 454 | u16 regDmn[2]; |
435 | u8 macAddr[6]; | 455 | u8 macAddr[6]; |
436 | u8 rxMask; | 456 | u8 rxMask; |
437 | u8 txMask; | 457 | u8 txMask; |
438 | u16 rfSilent; | 458 | u16 rfSilent; |
439 | u16 blueToothOptions; | 459 | u16 blueToothOptions; |
440 | u16 deviceCap; | 460 | u16 deviceCap; |
441 | u32 binBuildNumber; | 461 | u32 binBuildNumber; |
442 | u8 deviceType; | 462 | u8 deviceType; |
443 | u8 openLoopPwrCntl; | 463 | u8 openLoopPwrCntl; |
444 | int8_t pwrTableOffset; | 464 | int8_t pwrTableOffset; |
445 | int8_t tempSensSlope; | 465 | int8_t tempSensSlope; |
446 | int8_t tempSensSlopePalOn; | 466 | int8_t tempSensSlopePalOn; |
447 | u8 futureBase[29]; | 467 | u8 futureBase[29]; |
448 | } __packed; | 468 | } __packed; |
449 | 469 | ||
450 | struct modal_eep_ar9287_header { | 470 | struct modal_eep_ar9287_header { |
451 | u32 antCtrlChain[AR9287_MAX_CHAINS]; | 471 | u32 antCtrlChain[AR9287_MAX_CHAINS]; |
452 | u32 antCtrlCommon; | 472 | u32 antCtrlCommon; |
453 | int8_t antennaGainCh[AR9287_MAX_CHAINS]; | 473 | int8_t antennaGainCh[AR9287_MAX_CHAINS]; |
454 | u8 switchSettling; | 474 | u8 switchSettling; |
455 | u8 txRxAttenCh[AR9287_MAX_CHAINS]; | 475 | u8 txRxAttenCh[AR9287_MAX_CHAINS]; |
456 | u8 rxTxMarginCh[AR9287_MAX_CHAINS]; | 476 | u8 rxTxMarginCh[AR9287_MAX_CHAINS]; |
457 | int8_t adcDesiredSize; | 477 | int8_t adcDesiredSize; |
458 | u8 txEndToXpaOff; | 478 | u8 txEndToXpaOff; |
459 | u8 txEndToRxOn; | 479 | u8 txEndToRxOn; |
460 | u8 txFrameToXpaOn; | 480 | u8 txFrameToXpaOn; |
461 | u8 thresh62; | 481 | u8 thresh62; |
462 | int8_t noiseFloorThreshCh[AR9287_MAX_CHAINS]; | 482 | int8_t noiseFloorThreshCh[AR9287_MAX_CHAINS]; |
463 | u8 xpdGain; | 483 | u8 xpdGain; |
464 | u8 xpd; | 484 | u8 xpd; |
465 | int8_t iqCalICh[AR9287_MAX_CHAINS]; | 485 | int8_t iqCalICh[AR9287_MAX_CHAINS]; |
466 | int8_t iqCalQCh[AR9287_MAX_CHAINS]; | 486 | int8_t iqCalQCh[AR9287_MAX_CHAINS]; |
467 | u8 pdGainOverlap; | 487 | u8 pdGainOverlap; |
468 | u8 xpaBiasLvl; | 488 | u8 xpaBiasLvl; |
469 | u8 txFrameToDataStart; | 489 | u8 txFrameToDataStart; |
470 | u8 txFrameToPaOn; | 490 | u8 txFrameToPaOn; |
471 | u8 ht40PowerIncForPdadc; | 491 | u8 ht40PowerIncForPdadc; |
472 | u8 bswAtten[AR9287_MAX_CHAINS]; | 492 | u8 bswAtten[AR9287_MAX_CHAINS]; |
473 | u8 bswMargin[AR9287_MAX_CHAINS]; | 493 | u8 bswMargin[AR9287_MAX_CHAINS]; |
474 | u8 swSettleHt40; | 494 | u8 swSettleHt40; |
475 | u8 version; | 495 | u8 version; |
476 | u8 db1; | 496 | u8 db1; |
477 | u8 db2; | 497 | u8 db2; |
478 | u8 ob_cck; | 498 | u8 ob_cck; |
479 | u8 ob_psk; | 499 | u8 ob_psk; |
480 | u8 ob_qam; | 500 | u8 ob_qam; |
481 | u8 ob_pal_off; | 501 | u8 ob_pal_off; |
482 | u8 futureModal[30]; | 502 | u8 futureModal[30]; |
483 | struct spur_chan spurChans[AR9287_EEPROM_MODAL_SPURS]; | 503 | struct spur_chan spurChans[AR9287_EEPROM_MODAL_SPURS]; |
484 | } __packed; | 504 | } __packed; |
485 | 505 | ||
486 | |||
487 | |||
488 | struct cal_data_per_freq { | 506 | struct cal_data_per_freq { |
489 | u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; | 507 | u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; |
490 | u8 vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; | 508 | u8 vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; |
@@ -525,7 +543,6 @@ struct cal_data_op_loop_ar9287 { | |||
525 | u8 empty[2][5]; | 543 | u8 empty[2][5]; |
526 | } __packed; | 544 | } __packed; |
527 | 545 | ||
528 | |||
529 | struct cal_data_per_freq_ar9287 { | 546 | struct cal_data_per_freq_ar9287 { |
530 | u8 pwrPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; | 547 | u8 pwrPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; |
531 | u8 vpdPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; | 548 | u8 vpdPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; |
@@ -601,26 +618,25 @@ struct ar5416_eeprom_4k { | |||
601 | } __packed; | 618 | } __packed; |
602 | 619 | ||
603 | struct ar9287_eeprom { | 620 | struct ar9287_eeprom { |
604 | struct base_eep_ar9287_header baseEepHeader; | 621 | struct base_eep_ar9287_header baseEepHeader; |
605 | u8 custData[AR9287_DATA_SZ]; | 622 | u8 custData[AR9287_DATA_SZ]; |
606 | struct modal_eep_ar9287_header modalHeader; | 623 | struct modal_eep_ar9287_header modalHeader; |
607 | u8 calFreqPier2G[AR9287_NUM_2G_CAL_PIERS]; | 624 | u8 calFreqPier2G[AR9287_NUM_2G_CAL_PIERS]; |
608 | union cal_data_per_freq_ar9287_u | 625 | union cal_data_per_freq_ar9287_u |
609 | calPierData2G[AR9287_MAX_CHAINS][AR9287_NUM_2G_CAL_PIERS]; | 626 | calPierData2G[AR9287_MAX_CHAINS][AR9287_NUM_2G_CAL_PIERS]; |
610 | struct cal_target_power_leg | 627 | struct cal_target_power_leg |
611 | calTargetPowerCck[AR9287_NUM_2G_CCK_TARGET_POWERS]; | 628 | calTargetPowerCck[AR9287_NUM_2G_CCK_TARGET_POWERS]; |
612 | struct cal_target_power_leg | 629 | struct cal_target_power_leg |
613 | calTargetPower2G[AR9287_NUM_2G_20_TARGET_POWERS]; | 630 | calTargetPower2G[AR9287_NUM_2G_20_TARGET_POWERS]; |
614 | struct cal_target_power_ht | 631 | struct cal_target_power_ht |
615 | calTargetPower2GHT20[AR9287_NUM_2G_20_TARGET_POWERS]; | 632 | calTargetPower2GHT20[AR9287_NUM_2G_20_TARGET_POWERS]; |
616 | struct cal_target_power_ht | 633 | struct cal_target_power_ht |
617 | calTargetPower2GHT40[AR9287_NUM_2G_40_TARGET_POWERS]; | 634 | calTargetPower2GHT40[AR9287_NUM_2G_40_TARGET_POWERS]; |
618 | u8 ctlIndex[AR9287_NUM_CTLS]; | 635 | u8 ctlIndex[AR9287_NUM_CTLS]; |
619 | struct cal_ctl_data_ar9287 ctlData[AR9287_NUM_CTLS]; | 636 | struct cal_ctl_data_ar9287 ctlData[AR9287_NUM_CTLS]; |
620 | u8 padding; | 637 | u8 padding; |
621 | } __packed; | 638 | } __packed; |
622 | 639 | ||
623 | |||
624 | enum reg_ext_bitmap { | 640 | enum reg_ext_bitmap { |
625 | REG_EXT_JAPAN_MIDBAND = 1, | 641 | REG_EXT_JAPAN_MIDBAND = 1, |
626 | REG_EXT_FCC_DFS_HT40 = 2, | 642 | REG_EXT_FCC_DFS_HT40 = 2, |
@@ -661,10 +677,39 @@ struct eeprom_ops { | |||
661 | u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); | 677 | u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); |
662 | }; | 678 | }; |
663 | 679 | ||
680 | void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask, | ||
681 | u32 shift, u32 val); | ||
682 | int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight, | ||
683 | int16_t targetLeft, | ||
684 | int16_t targetRight); | ||
685 | bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize, | ||
686 | u16 *indexL, u16 *indexR); | ||
687 | bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data); | ||
688 | void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, | ||
689 | u8 *pVpdList, u16 numIntercepts, | ||
690 | u8 *pRetVpdList); | ||
691 | void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah, | ||
692 | struct ath9k_channel *chan, | ||
693 | struct cal_target_power_leg *powInfo, | ||
694 | u16 numChannels, | ||
695 | struct cal_target_power_leg *pNewPower, | ||
696 | u16 numRates, bool isExtTarget); | ||
697 | void ath9k_hw_get_target_powers(struct ath_hw *ah, | ||
698 | struct ath9k_channel *chan, | ||
699 | struct cal_target_power_ht *powInfo, | ||
700 | u16 numChannels, | ||
701 | struct cal_target_power_ht *pNewPower, | ||
702 | u16 numRates, bool isHt40Target); | ||
703 | u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, | ||
704 | bool is2GHz, int num_band_edges); | ||
705 | int ath9k_hw_eeprom_init(struct ath_hw *ah); | ||
706 | |||
664 | #define ar5416_get_ntxchains(_txchainmask) \ | 707 | #define ar5416_get_ntxchains(_txchainmask) \ |
665 | (((_txchainmask >> 2) & 1) + \ | 708 | (((_txchainmask >> 2) & 1) + \ |
666 | ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) | 709 | ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) |
667 | 710 | ||
668 | int ath9k_hw_eeprom_init(struct ath_hw *ah); | 711 | extern const struct eeprom_ops eep_def_ops; |
712 | extern const struct eeprom_ops eep_4k_ops; | ||
713 | extern const struct eeprom_ops eep_AR9287_ops; | ||
669 | 714 | ||
670 | #endif /* EEPROM_H */ | 715 | #endif /* EEPROM_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c new file mode 100644 index 000000000000..d34dd23e806a --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
@@ -0,0 +1,1186 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "ath9k.h" | ||
18 | |||
19 | static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah) | ||
20 | { | ||
21 | return ((ah->eeprom.map4k.baseEepHeader.version >> 12) & 0xF); | ||
22 | } | ||
23 | |||
24 | static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah) | ||
25 | { | ||
26 | return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF); | ||
27 | } | ||
28 | |||
29 | static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) | ||
30 | { | ||
31 | #define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) | ||
32 | u16 *eep_data = (u16 *)&ah->eeprom.map4k; | ||
33 | int addr, eep_start_loc = 0; | ||
34 | |||
35 | eep_start_loc = 64; | ||
36 | |||
37 | if (!ath9k_hw_use_flash(ah)) { | ||
38 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
39 | "Reading from EEPROM, not flash\n"); | ||
40 | } | ||
41 | |||
42 | for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { | ||
43 | if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) { | ||
44 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
45 | "Unable to read eeprom region \n"); | ||
46 | return false; | ||
47 | } | ||
48 | eep_data++; | ||
49 | } | ||
50 | |||
51 | return true; | ||
52 | #undef SIZE_EEPROM_4K | ||
53 | } | ||
54 | |||
55 | static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | ||
56 | { | ||
57 | #define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) | ||
58 | struct ar5416_eeprom_4k *eep = | ||
59 | (struct ar5416_eeprom_4k *) &ah->eeprom.map4k; | ||
60 | u16 *eepdata, temp, magic, magic2; | ||
61 | u32 sum = 0, el; | ||
62 | bool need_swap = false; | ||
63 | int i, addr; | ||
64 | |||
65 | |||
66 | if (!ath9k_hw_use_flash(ah)) { | ||
67 | if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, | ||
68 | &magic)) { | ||
69 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
70 | "Reading Magic # failed\n"); | ||
71 | return false; | ||
72 | } | ||
73 | |||
74 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
75 | "Read Magic = 0x%04X\n", magic); | ||
76 | |||
77 | if (magic != AR5416_EEPROM_MAGIC) { | ||
78 | magic2 = swab16(magic); | ||
79 | |||
80 | if (magic2 == AR5416_EEPROM_MAGIC) { | ||
81 | need_swap = true; | ||
82 | eepdata = (u16 *) (&ah->eeprom); | ||
83 | |||
84 | for (addr = 0; addr < EEPROM_4K_SIZE; addr++) { | ||
85 | temp = swab16(*eepdata); | ||
86 | *eepdata = temp; | ||
87 | eepdata++; | ||
88 | } | ||
89 | } else { | ||
90 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
91 | "Invalid EEPROM Magic. " | ||
92 | "endianness mismatch.\n"); | ||
93 | return -EINVAL; | ||
94 | } | ||
95 | } | ||
96 | } | ||
97 | |||
98 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", | ||
99 | need_swap ? "True" : "False"); | ||
100 | |||
101 | if (need_swap) | ||
102 | el = swab16(ah->eeprom.map4k.baseEepHeader.length); | ||
103 | else | ||
104 | el = ah->eeprom.map4k.baseEepHeader.length; | ||
105 | |||
106 | if (el > sizeof(struct ar5416_eeprom_4k)) | ||
107 | el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16); | ||
108 | else | ||
109 | el = el / sizeof(u16); | ||
110 | |||
111 | eepdata = (u16 *)(&ah->eeprom); | ||
112 | |||
113 | for (i = 0; i < el; i++) | ||
114 | sum ^= *eepdata++; | ||
115 | |||
116 | if (need_swap) { | ||
117 | u32 integer; | ||
118 | u16 word; | ||
119 | |||
120 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
121 | "EEPROM Endianness is not native.. Changing\n"); | ||
122 | |||
123 | word = swab16(eep->baseEepHeader.length); | ||
124 | eep->baseEepHeader.length = word; | ||
125 | |||
126 | word = swab16(eep->baseEepHeader.checksum); | ||
127 | eep->baseEepHeader.checksum = word; | ||
128 | |||
129 | word = swab16(eep->baseEepHeader.version); | ||
130 | eep->baseEepHeader.version = word; | ||
131 | |||
132 | word = swab16(eep->baseEepHeader.regDmn[0]); | ||
133 | eep->baseEepHeader.regDmn[0] = word; | ||
134 | |||
135 | word = swab16(eep->baseEepHeader.regDmn[1]); | ||
136 | eep->baseEepHeader.regDmn[1] = word; | ||
137 | |||
138 | word = swab16(eep->baseEepHeader.rfSilent); | ||
139 | eep->baseEepHeader.rfSilent = word; | ||
140 | |||
141 | word = swab16(eep->baseEepHeader.blueToothOptions); | ||
142 | eep->baseEepHeader.blueToothOptions = word; | ||
143 | |||
144 | word = swab16(eep->baseEepHeader.deviceCap); | ||
145 | eep->baseEepHeader.deviceCap = word; | ||
146 | |||
147 | integer = swab32(eep->modalHeader.antCtrlCommon); | ||
148 | eep->modalHeader.antCtrlCommon = integer; | ||
149 | |||
150 | for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { | ||
151 | integer = swab32(eep->modalHeader.antCtrlChain[i]); | ||
152 | eep->modalHeader.antCtrlChain[i] = integer; | ||
153 | } | ||
154 | |||
155 | for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { | ||
156 | word = swab16(eep->modalHeader.spurChans[i].spurChan); | ||
157 | eep->modalHeader.spurChans[i].spurChan = word; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || | ||
162 | ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { | ||
163 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
164 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | ||
165 | sum, ah->eep_ops->get_eeprom_ver(ah)); | ||
166 | return -EINVAL; | ||
167 | } | ||
168 | |||
169 | return 0; | ||
170 | #undef EEPROM_4K_SIZE | ||
171 | } | ||
172 | |||
173 | static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, | ||
174 | enum eeprom_param param) | ||
175 | { | ||
176 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | ||
177 | struct modal_eep_4k_header *pModal = &eep->modalHeader; | ||
178 | struct base_eep_header_4k *pBase = &eep->baseEepHeader; | ||
179 | |||
180 | switch (param) { | ||
181 | case EEP_NFTHRESH_2: | ||
182 | return pModal->noiseFloorThreshCh[0]; | ||
183 | case AR_EEPROM_MAC(0): | ||
184 | return pBase->macAddr[0] << 8 | pBase->macAddr[1]; | ||
185 | case AR_EEPROM_MAC(1): | ||
186 | return pBase->macAddr[2] << 8 | pBase->macAddr[3]; | ||
187 | case AR_EEPROM_MAC(2): | ||
188 | return pBase->macAddr[4] << 8 | pBase->macAddr[5]; | ||
189 | case EEP_REG_0: | ||
190 | return pBase->regDmn[0]; | ||
191 | case EEP_REG_1: | ||
192 | return pBase->regDmn[1]; | ||
193 | case EEP_OP_CAP: | ||
194 | return pBase->deviceCap; | ||
195 | case EEP_OP_MODE: | ||
196 | return pBase->opCapFlags; | ||
197 | case EEP_RF_SILENT: | ||
198 | return pBase->rfSilent; | ||
199 | case EEP_OB_2: | ||
200 | return pModal->ob_0; | ||
201 | case EEP_DB_2: | ||
202 | return pModal->db1_1; | ||
203 | case EEP_MINOR_REV: | ||
204 | return pBase->version & AR5416_EEP_VER_MINOR_MASK; | ||
205 | case EEP_TX_MASK: | ||
206 | return pBase->txMask; | ||
207 | case EEP_RX_MASK: | ||
208 | return pBase->rxMask; | ||
209 | case EEP_FRAC_N_5G: | ||
210 | return 0; | ||
211 | default: | ||
212 | return 0; | ||
213 | } | ||
214 | } | ||
215 | |||
216 | static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah, | ||
217 | struct ath9k_channel *chan, | ||
218 | struct cal_data_per_freq_4k *pRawDataSet, | ||
219 | u8 *bChans, u16 availPiers, | ||
220 | u16 tPdGainOverlap, int16_t *pMinCalPower, | ||
221 | u16 *pPdGainBoundaries, u8 *pPDADCValues, | ||
222 | u16 numXpdGains) | ||
223 | { | ||
224 | #define TMP_VAL_VPD_TABLE \ | ||
225 | ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep)); | ||
226 | int i, j, k; | ||
227 | int16_t ss; | ||
228 | u16 idxL = 0, idxR = 0, numPiers; | ||
229 | static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS] | ||
230 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
231 | static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS] | ||
232 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
233 | static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS] | ||
234 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
235 | |||
236 | u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; | ||
237 | u8 minPwrT4[AR5416_EEP4K_NUM_PD_GAINS]; | ||
238 | u8 maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS]; | ||
239 | int16_t vpdStep; | ||
240 | int16_t tmpVal; | ||
241 | u16 sizeCurrVpdTable, maxIndex, tgtIndex; | ||
242 | bool match; | ||
243 | int16_t minDelta = 0; | ||
244 | struct chan_centers centers; | ||
245 | #define PD_GAIN_BOUNDARY_DEFAULT 58; | ||
246 | |||
247 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
248 | |||
249 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | ||
250 | if (bChans[numPiers] == AR5416_BCHAN_UNUSED) | ||
251 | break; | ||
252 | } | ||
253 | |||
254 | match = ath9k_hw_get_lower_upper_index( | ||
255 | (u8)FREQ2FBIN(centers.synth_center, | ||
256 | IS_CHAN_2GHZ(chan)), bChans, numPiers, | ||
257 | &idxL, &idxR); | ||
258 | |||
259 | if (match) { | ||
260 | for (i = 0; i < numXpdGains; i++) { | ||
261 | minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; | ||
262 | maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; | ||
263 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
264 | pRawDataSet[idxL].pwrPdg[i], | ||
265 | pRawDataSet[idxL].vpdPdg[i], | ||
266 | AR5416_EEP4K_PD_GAIN_ICEPTS, | ||
267 | vpdTableI[i]); | ||
268 | } | ||
269 | } else { | ||
270 | for (i = 0; i < numXpdGains; i++) { | ||
271 | pVpdL = pRawDataSet[idxL].vpdPdg[i]; | ||
272 | pPwrL = pRawDataSet[idxL].pwrPdg[i]; | ||
273 | pVpdR = pRawDataSet[idxR].vpdPdg[i]; | ||
274 | pPwrR = pRawDataSet[idxR].pwrPdg[i]; | ||
275 | |||
276 | minPwrT4[i] = max(pPwrL[0], pPwrR[0]); | ||
277 | |||
278 | maxPwrT4[i] = | ||
279 | min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1], | ||
280 | pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]); | ||
281 | |||
282 | |||
283 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
284 | pPwrL, pVpdL, | ||
285 | AR5416_EEP4K_PD_GAIN_ICEPTS, | ||
286 | vpdTableL[i]); | ||
287 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
288 | pPwrR, pVpdR, | ||
289 | AR5416_EEP4K_PD_GAIN_ICEPTS, | ||
290 | vpdTableR[i]); | ||
291 | |||
292 | for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { | ||
293 | vpdTableI[i][j] = | ||
294 | (u8)(ath9k_hw_interpolate((u16) | ||
295 | FREQ2FBIN(centers. | ||
296 | synth_center, | ||
297 | IS_CHAN_2GHZ | ||
298 | (chan)), | ||
299 | bChans[idxL], bChans[idxR], | ||
300 | vpdTableL[i][j], vpdTableR[i][j])); | ||
301 | } | ||
302 | } | ||
303 | } | ||
304 | |||
305 | *pMinCalPower = (int16_t)(minPwrT4[0] / 2); | ||
306 | |||
307 | k = 0; | ||
308 | |||
309 | for (i = 0; i < numXpdGains; i++) { | ||
310 | if (i == (numXpdGains - 1)) | ||
311 | pPdGainBoundaries[i] = | ||
312 | (u16)(maxPwrT4[i] / 2); | ||
313 | else | ||
314 | pPdGainBoundaries[i] = | ||
315 | (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4); | ||
316 | |||
317 | pPdGainBoundaries[i] = | ||
318 | min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); | ||
319 | |||
320 | if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { | ||
321 | minDelta = pPdGainBoundaries[0] - 23; | ||
322 | pPdGainBoundaries[0] = 23; | ||
323 | } else { | ||
324 | minDelta = 0; | ||
325 | } | ||
326 | |||
327 | if (i == 0) { | ||
328 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
329 | ss = (int16_t)(0 - (minPwrT4[i] / 2)); | ||
330 | else | ||
331 | ss = 0; | ||
332 | } else { | ||
333 | ss = (int16_t)((pPdGainBoundaries[i - 1] - | ||
334 | (minPwrT4[i] / 2)) - | ||
335 | tPdGainOverlap + 1 + minDelta); | ||
336 | } | ||
337 | vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); | ||
338 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
339 | |||
340 | while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
341 | tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); | ||
342 | pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); | ||
343 | ss++; | ||
344 | } | ||
345 | |||
346 | sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); | ||
347 | tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap - | ||
348 | (minPwrT4[i] / 2)); | ||
349 | maxIndex = (tgtIndex < sizeCurrVpdTable) ? | ||
350 | tgtIndex : sizeCurrVpdTable; | ||
351 | |||
352 | while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) | ||
353 | pPDADCValues[k++] = vpdTableI[i][ss++]; | ||
354 | |||
355 | vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - | ||
356 | vpdTableI[i][sizeCurrVpdTable - 2]); | ||
357 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
358 | |||
359 | if (tgtIndex >= maxIndex) { | ||
360 | while ((ss <= tgtIndex) && | ||
361 | (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
362 | tmpVal = (int16_t) TMP_VAL_VPD_TABLE; | ||
363 | pPDADCValues[k++] = (u8)((tmpVal > 255) ? | ||
364 | 255 : tmpVal); | ||
365 | ss++; | ||
366 | } | ||
367 | } | ||
368 | } | ||
369 | |||
370 | while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) { | ||
371 | pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT; | ||
372 | i++; | ||
373 | } | ||
374 | |||
375 | while (k < AR5416_NUM_PDADC_VALUES) { | ||
376 | pPDADCValues[k] = pPDADCValues[k - 1]; | ||
377 | k++; | ||
378 | } | ||
379 | |||
380 | return; | ||
381 | #undef TMP_VAL_VPD_TABLE | ||
382 | } | ||
383 | |||
384 | static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | ||
385 | struct ath9k_channel *chan, | ||
386 | int16_t *pTxPowerIndexOffset) | ||
387 | { | ||
388 | struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; | ||
389 | struct cal_data_per_freq_4k *pRawDataset; | ||
390 | u8 *pCalBChans = NULL; | ||
391 | u16 pdGainOverlap_t2; | ||
392 | static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; | ||
393 | u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK]; | ||
394 | u16 numPiers, i, j; | ||
395 | int16_t tMinCalPower; | ||
396 | u16 numXpdGain, xpdMask; | ||
397 | u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 }; | ||
398 | u32 reg32, regOffset, regChainOffset; | ||
399 | |||
400 | xpdMask = pEepData->modalHeader.xpdGain; | ||
401 | |||
402 | if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
403 | AR5416_EEP_MINOR_VER_2) { | ||
404 | pdGainOverlap_t2 = | ||
405 | pEepData->modalHeader.pdGainOverlap; | ||
406 | } else { | ||
407 | pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), | ||
408 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); | ||
409 | } | ||
410 | |||
411 | pCalBChans = pEepData->calFreqPier2G; | ||
412 | numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS; | ||
413 | |||
414 | numXpdGain = 0; | ||
415 | |||
416 | for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) { | ||
417 | if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) { | ||
418 | if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS) | ||
419 | break; | ||
420 | xpdGainValues[numXpdGain] = | ||
421 | (u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i); | ||
422 | numXpdGain++; | ||
423 | } | ||
424 | } | ||
425 | |||
426 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, | ||
427 | (numXpdGain - 1) & 0x3); | ||
428 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, | ||
429 | xpdGainValues[0]); | ||
430 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, | ||
431 | xpdGainValues[1]); | ||
432 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0); | ||
433 | |||
434 | for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { | ||
435 | if (AR_SREV_5416_20_OR_LATER(ah) && | ||
436 | (ah->rxchainmask == 5 || ah->txchainmask == 5) && | ||
437 | (i != 0)) { | ||
438 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; | ||
439 | } else | ||
440 | regChainOffset = i * 0x1000; | ||
441 | |||
442 | if (pEepData->baseEepHeader.txMask & (1 << i)) { | ||
443 | pRawDataset = pEepData->calPierData2G[i]; | ||
444 | |||
445 | ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan, | ||
446 | pRawDataset, pCalBChans, | ||
447 | numPiers, pdGainOverlap_t2, | ||
448 | &tMinCalPower, gainBoundaries, | ||
449 | pdadcValues, numXpdGain); | ||
450 | |||
451 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { | ||
452 | REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, | ||
453 | SM(pdGainOverlap_t2, | ||
454 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | ||
455 | | SM(gainBoundaries[0], | ||
456 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | ||
457 | | SM(gainBoundaries[1], | ||
458 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | ||
459 | | SM(gainBoundaries[2], | ||
460 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | ||
461 | | SM(gainBoundaries[3], | ||
462 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); | ||
463 | } | ||
464 | |||
465 | regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; | ||
466 | for (j = 0; j < 32; j++) { | ||
467 | reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) | | ||
468 | ((pdadcValues[4 * j + 1] & 0xFF) << 8) | | ||
469 | ((pdadcValues[4 * j + 2] & 0xFF) << 16)| | ||
470 | ((pdadcValues[4 * j + 3] & 0xFF) << 24); | ||
471 | REG_WRITE(ah, regOffset, reg32); | ||
472 | |||
473 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
474 | "PDADC (%d,%4x): %4.4x %8.8x\n", | ||
475 | i, regChainOffset, regOffset, | ||
476 | reg32); | ||
477 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
478 | "PDADC: Chain %d | " | ||
479 | "PDADC %3d Value %3d | " | ||
480 | "PDADC %3d Value %3d | " | ||
481 | "PDADC %3d Value %3d | " | ||
482 | "PDADC %3d Value %3d |\n", | ||
483 | i, 4 * j, pdadcValues[4 * j], | ||
484 | 4 * j + 1, pdadcValues[4 * j + 1], | ||
485 | 4 * j + 2, pdadcValues[4 * j + 2], | ||
486 | 4 * j + 3, | ||
487 | pdadcValues[4 * j + 3]); | ||
488 | |||
489 | regOffset += 4; | ||
490 | } | ||
491 | } | ||
492 | } | ||
493 | |||
494 | *pTxPowerIndexOffset = 0; | ||
495 | } | ||
496 | |||
497 | static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, | ||
498 | struct ath9k_channel *chan, | ||
499 | int16_t *ratesArray, | ||
500 | u16 cfgCtl, | ||
501 | u16 AntennaReduction, | ||
502 | u16 twiceMaxRegulatoryPower, | ||
503 | u16 powerLimit) | ||
504 | { | ||
505 | #define CMP_TEST_GRP \ | ||
506 | (((cfgCtl & ~CTL_MODE_M)| (pCtlMode[ctlMode] & CTL_MODE_M)) == \ | ||
507 | pEepData->ctlIndex[i]) \ | ||
508 | || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \ | ||
509 | ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL)) | ||
510 | |||
511 | int i; | ||
512 | int16_t twiceLargestAntenna; | ||
513 | u16 twiceMinEdgePower; | ||
514 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
515 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; | ||
516 | u16 numCtlModes, *pCtlMode, ctlMode, freq; | ||
517 | struct chan_centers centers; | ||
518 | struct cal_ctl_data_4k *rep; | ||
519 | struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; | ||
520 | static const u16 tpScaleReductionTable[5] = | ||
521 | { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; | ||
522 | struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { | ||
523 | 0, { 0, 0, 0, 0} | ||
524 | }; | ||
525 | struct cal_target_power_leg targetPowerOfdmExt = { | ||
526 | 0, { 0, 0, 0, 0} }, targetPowerCckExt = { | ||
527 | 0, { 0, 0, 0, 0 } | ||
528 | }; | ||
529 | struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { | ||
530 | 0, {0, 0, 0, 0} | ||
531 | }; | ||
532 | u16 ctlModesFor11g[] = | ||
533 | { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, | ||
534 | CTL_2GHT40 | ||
535 | }; | ||
536 | |||
537 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
538 | |||
539 | twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0]; | ||
540 | twiceLargestAntenna = (int16_t)min(AntennaReduction - | ||
541 | twiceLargestAntenna, 0); | ||
542 | |||
543 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; | ||
544 | if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) { | ||
545 | maxRegAllowedPower -= | ||
546 | (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); | ||
547 | } | ||
548 | |||
549 | scaledPower = min(powerLimit, maxRegAllowedPower); | ||
550 | scaledPower = max((u16)0, scaledPower); | ||
551 | |||
552 | numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; | ||
553 | pCtlMode = ctlModesFor11g; | ||
554 | |||
555 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
556 | pEepData->calTargetPowerCck, | ||
557 | AR5416_NUM_2G_CCK_TARGET_POWERS, | ||
558 | &targetPowerCck, 4, false); | ||
559 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
560 | pEepData->calTargetPower2G, | ||
561 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
562 | &targetPowerOfdm, 4, false); | ||
563 | ath9k_hw_get_target_powers(ah, chan, | ||
564 | pEepData->calTargetPower2GHT20, | ||
565 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
566 | &targetPowerHt20, 8, false); | ||
567 | |||
568 | if (IS_CHAN_HT40(chan)) { | ||
569 | numCtlModes = ARRAY_SIZE(ctlModesFor11g); | ||
570 | ath9k_hw_get_target_powers(ah, chan, | ||
571 | pEepData->calTargetPower2GHT40, | ||
572 | AR5416_NUM_2G_40_TARGET_POWERS, | ||
573 | &targetPowerHt40, 8, true); | ||
574 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
575 | pEepData->calTargetPowerCck, | ||
576 | AR5416_NUM_2G_CCK_TARGET_POWERS, | ||
577 | &targetPowerCckExt, 4, true); | ||
578 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
579 | pEepData->calTargetPower2G, | ||
580 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
581 | &targetPowerOfdmExt, 4, true); | ||
582 | } | ||
583 | |||
584 | for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { | ||
585 | bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || | ||
586 | (pCtlMode[ctlMode] == CTL_2GHT40); | ||
587 | |||
588 | if (isHt40CtlMode) | ||
589 | freq = centers.synth_center; | ||
590 | else if (pCtlMode[ctlMode] & EXT_ADDITIVE) | ||
591 | freq = centers.ext_center; | ||
592 | else | ||
593 | freq = centers.ctl_center; | ||
594 | |||
595 | if (ah->eep_ops->get_eeprom_ver(ah) == 14 && | ||
596 | ah->eep_ops->get_eeprom_rev(ah) <= 2) | ||
597 | twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
598 | |||
599 | for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) && | ||
600 | pEepData->ctlIndex[i]; i++) { | ||
601 | |||
602 | if (CMP_TEST_GRP) { | ||
603 | rep = &(pEepData->ctlData[i]); | ||
604 | |||
605 | twiceMinEdgePower = ath9k_hw_get_max_edge_power( | ||
606 | freq, | ||
607 | rep->ctlEdges[ | ||
608 | ar5416_get_ntxchains(ah->txchainmask) - 1], | ||
609 | IS_CHAN_2GHZ(chan), | ||
610 | AR5416_EEP4K_NUM_BAND_EDGES); | ||
611 | |||
612 | if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { | ||
613 | twiceMaxEdgePower = | ||
614 | min(twiceMaxEdgePower, | ||
615 | twiceMinEdgePower); | ||
616 | } else { | ||
617 | twiceMaxEdgePower = twiceMinEdgePower; | ||
618 | break; | ||
619 | } | ||
620 | } | ||
621 | } | ||
622 | |||
623 | minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); | ||
624 | |||
625 | switch (pCtlMode[ctlMode]) { | ||
626 | case CTL_11B: | ||
627 | for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) { | ||
628 | targetPowerCck.tPow2x[i] = | ||
629 | min((u16)targetPowerCck.tPow2x[i], | ||
630 | minCtlPower); | ||
631 | } | ||
632 | break; | ||
633 | case CTL_11G: | ||
634 | for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) { | ||
635 | targetPowerOfdm.tPow2x[i] = | ||
636 | min((u16)targetPowerOfdm.tPow2x[i], | ||
637 | minCtlPower); | ||
638 | } | ||
639 | break; | ||
640 | case CTL_2GHT20: | ||
641 | for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) { | ||
642 | targetPowerHt20.tPow2x[i] = | ||
643 | min((u16)targetPowerHt20.tPow2x[i], | ||
644 | minCtlPower); | ||
645 | } | ||
646 | break; | ||
647 | case CTL_11B_EXT: | ||
648 | targetPowerCckExt.tPow2x[0] = | ||
649 | min((u16)targetPowerCckExt.tPow2x[0], | ||
650 | minCtlPower); | ||
651 | break; | ||
652 | case CTL_11G_EXT: | ||
653 | targetPowerOfdmExt.tPow2x[0] = | ||
654 | min((u16)targetPowerOfdmExt.tPow2x[0], | ||
655 | minCtlPower); | ||
656 | break; | ||
657 | case CTL_2GHT40: | ||
658 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { | ||
659 | targetPowerHt40.tPow2x[i] = | ||
660 | min((u16)targetPowerHt40.tPow2x[i], | ||
661 | minCtlPower); | ||
662 | } | ||
663 | break; | ||
664 | default: | ||
665 | break; | ||
666 | } | ||
667 | } | ||
668 | |||
669 | ratesArray[rate6mb] = | ||
670 | ratesArray[rate9mb] = | ||
671 | ratesArray[rate12mb] = | ||
672 | ratesArray[rate18mb] = | ||
673 | ratesArray[rate24mb] = | ||
674 | targetPowerOfdm.tPow2x[0]; | ||
675 | |||
676 | ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; | ||
677 | ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; | ||
678 | ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; | ||
679 | ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; | ||
680 | |||
681 | for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) | ||
682 | ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; | ||
683 | |||
684 | ratesArray[rate1l] = targetPowerCck.tPow2x[0]; | ||
685 | ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1]; | ||
686 | ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2]; | ||
687 | ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3]; | ||
688 | |||
689 | if (IS_CHAN_HT40(chan)) { | ||
690 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { | ||
691 | ratesArray[rateHt40_0 + i] = | ||
692 | targetPowerHt40.tPow2x[i]; | ||
693 | } | ||
694 | ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; | ||
695 | ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; | ||
696 | ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; | ||
697 | ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; | ||
698 | } | ||
699 | |||
700 | #undef CMP_TEST_GRP | ||
701 | } | ||
702 | |||
703 | static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, | ||
704 | struct ath9k_channel *chan, | ||
705 | u16 cfgCtl, | ||
706 | u8 twiceAntennaReduction, | ||
707 | u8 twiceMaxRegulatoryPower, | ||
708 | u8 powerLimit) | ||
709 | { | ||
710 | struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; | ||
711 | struct modal_eep_4k_header *pModal = &pEepData->modalHeader; | ||
712 | int16_t ratesArray[Ar5416RateSize]; | ||
713 | int16_t txPowerIndexOffset = 0; | ||
714 | u8 ht40PowerIncForPdadc = 2; | ||
715 | int i; | ||
716 | |||
717 | memset(ratesArray, 0, sizeof(ratesArray)); | ||
718 | |||
719 | if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
720 | AR5416_EEP_MINOR_VER_2) { | ||
721 | ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; | ||
722 | } | ||
723 | |||
724 | ath9k_hw_set_4k_power_per_rate_table(ah, chan, | ||
725 | &ratesArray[0], cfgCtl, | ||
726 | twiceAntennaReduction, | ||
727 | twiceMaxRegulatoryPower, | ||
728 | powerLimit); | ||
729 | |||
730 | ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset); | ||
731 | |||
732 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { | ||
733 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); | ||
734 | if (ratesArray[i] > AR5416_MAX_RATE_POWER) | ||
735 | ratesArray[i] = AR5416_MAX_RATE_POWER; | ||
736 | } | ||
737 | |||
738 | |||
739 | /* Update regulatory */ | ||
740 | |||
741 | i = rate6mb; | ||
742 | if (IS_CHAN_HT40(chan)) | ||
743 | i = rateHt40_0; | ||
744 | else if (IS_CHAN_HT20(chan)) | ||
745 | i = rateHt20_0; | ||
746 | |||
747 | ah->regulatory.max_power_level = ratesArray[i]; | ||
748 | |||
749 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
750 | for (i = 0; i < Ar5416RateSize; i++) | ||
751 | ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2; | ||
752 | } | ||
753 | |||
754 | /* OFDM power per rate */ | ||
755 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, | ||
756 | ATH9K_POW_SM(ratesArray[rate18mb], 24) | ||
757 | | ATH9K_POW_SM(ratesArray[rate12mb], 16) | ||
758 | | ATH9K_POW_SM(ratesArray[rate9mb], 8) | ||
759 | | ATH9K_POW_SM(ratesArray[rate6mb], 0)); | ||
760 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, | ||
761 | ATH9K_POW_SM(ratesArray[rate54mb], 24) | ||
762 | | ATH9K_POW_SM(ratesArray[rate48mb], 16) | ||
763 | | ATH9K_POW_SM(ratesArray[rate36mb], 8) | ||
764 | | ATH9K_POW_SM(ratesArray[rate24mb], 0)); | ||
765 | |||
766 | /* CCK power per rate */ | ||
767 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, | ||
768 | ATH9K_POW_SM(ratesArray[rate2s], 24) | ||
769 | | ATH9K_POW_SM(ratesArray[rate2l], 16) | ||
770 | | ATH9K_POW_SM(ratesArray[rateXr], 8) | ||
771 | | ATH9K_POW_SM(ratesArray[rate1l], 0)); | ||
772 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, | ||
773 | ATH9K_POW_SM(ratesArray[rate11s], 24) | ||
774 | | ATH9K_POW_SM(ratesArray[rate11l], 16) | ||
775 | | ATH9K_POW_SM(ratesArray[rate5_5s], 8) | ||
776 | | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); | ||
777 | |||
778 | /* HT20 power per rate */ | ||
779 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, | ||
780 | ATH9K_POW_SM(ratesArray[rateHt20_3], 24) | ||
781 | | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) | ||
782 | | ATH9K_POW_SM(ratesArray[rateHt20_1], 8) | ||
783 | | ATH9K_POW_SM(ratesArray[rateHt20_0], 0)); | ||
784 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, | ||
785 | ATH9K_POW_SM(ratesArray[rateHt20_7], 24) | ||
786 | | ATH9K_POW_SM(ratesArray[rateHt20_6], 16) | ||
787 | | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) | ||
788 | | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); | ||
789 | |||
790 | /* HT40 power per rate */ | ||
791 | if (IS_CHAN_HT40(chan)) { | ||
792 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, | ||
793 | ATH9K_POW_SM(ratesArray[rateHt40_3] + | ||
794 | ht40PowerIncForPdadc, 24) | ||
795 | | ATH9K_POW_SM(ratesArray[rateHt40_2] + | ||
796 | ht40PowerIncForPdadc, 16) | ||
797 | | ATH9K_POW_SM(ratesArray[rateHt40_1] + | ||
798 | ht40PowerIncForPdadc, 8) | ||
799 | | ATH9K_POW_SM(ratesArray[rateHt40_0] + | ||
800 | ht40PowerIncForPdadc, 0)); | ||
801 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, | ||
802 | ATH9K_POW_SM(ratesArray[rateHt40_7] + | ||
803 | ht40PowerIncForPdadc, 24) | ||
804 | | ATH9K_POW_SM(ratesArray[rateHt40_6] + | ||
805 | ht40PowerIncForPdadc, 16) | ||
806 | | ATH9K_POW_SM(ratesArray[rateHt40_5] + | ||
807 | ht40PowerIncForPdadc, 8) | ||
808 | | ATH9K_POW_SM(ratesArray[rateHt40_4] + | ||
809 | ht40PowerIncForPdadc, 0)); | ||
810 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, | ||
811 | ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) | ||
812 | | ATH9K_POW_SM(ratesArray[rateExtCck], 16) | ||
813 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | ||
814 | | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); | ||
815 | } | ||
816 | } | ||
817 | |||
818 | static void ath9k_hw_4k_set_addac(struct ath_hw *ah, | ||
819 | struct ath9k_channel *chan) | ||
820 | { | ||
821 | struct modal_eep_4k_header *pModal; | ||
822 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | ||
823 | u8 biaslevel; | ||
824 | |||
825 | if (ah->hw_version.macVersion != AR_SREV_VERSION_9160) | ||
826 | return; | ||
827 | |||
828 | if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7) | ||
829 | return; | ||
830 | |||
831 | pModal = &eep->modalHeader; | ||
832 | |||
833 | if (pModal->xpaBiasLvl != 0xff) { | ||
834 | biaslevel = pModal->xpaBiasLvl; | ||
835 | INI_RA(&ah->iniAddac, 7, 1) = | ||
836 | (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3; | ||
837 | } | ||
838 | } | ||
839 | |||
840 | static void ath9k_hw_4k_set_gain(struct ath_hw *ah, | ||
841 | struct modal_eep_4k_header *pModal, | ||
842 | struct ar5416_eeprom_4k *eep, | ||
843 | u8 txRxAttenLocal) | ||
844 | { | ||
845 | REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0, | ||
846 | pModal->antCtrlChain[0]); | ||
847 | |||
848 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), | ||
849 | (REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & | ||
850 | ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | | ||
851 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | | ||
852 | SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | | ||
853 | SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); | ||
854 | |||
855 | if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
856 | AR5416_EEP_MINOR_VER_3) { | ||
857 | txRxAttenLocal = pModal->txRxAttenCh[0]; | ||
858 | |||
859 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, | ||
860 | AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]); | ||
861 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, | ||
862 | AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); | ||
863 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, | ||
864 | AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, | ||
865 | pModal->xatten2Margin[0]); | ||
866 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, | ||
867 | AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]); | ||
868 | |||
869 | /* Set the block 1 value to block 0 value */ | ||
870 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, | ||
871 | AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, | ||
872 | pModal->bswMargin[0]); | ||
873 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, | ||
874 | AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); | ||
875 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, | ||
876 | AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, | ||
877 | pModal->xatten2Margin[0]); | ||
878 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, | ||
879 | AR_PHY_GAIN_2GHZ_XATTEN2_DB, | ||
880 | pModal->xatten2Db[0]); | ||
881 | } | ||
882 | |||
883 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN, | ||
884 | AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); | ||
885 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN, | ||
886 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); | ||
887 | |||
888 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, | ||
889 | AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); | ||
890 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, | ||
891 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); | ||
892 | |||
893 | if (AR_SREV_9285_11(ah)) | ||
894 | REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); | ||
895 | } | ||
896 | |||
897 | /* | ||
898 | * Read EEPROM header info and program the device for correct operation | ||
899 | * given the channel value. | ||
900 | */ | ||
901 | static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | ||
902 | struct ath9k_channel *chan) | ||
903 | { | ||
904 | struct modal_eep_4k_header *pModal; | ||
905 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | ||
906 | u8 txRxAttenLocal; | ||
907 | u8 ob[5], db1[5], db2[5]; | ||
908 | u8 ant_div_control1, ant_div_control2; | ||
909 | u32 regVal; | ||
910 | |||
911 | pModal = &eep->modalHeader; | ||
912 | txRxAttenLocal = 23; | ||
913 | |||
914 | REG_WRITE(ah, AR_PHY_SWITCH_COM, | ||
915 | ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); | ||
916 | |||
917 | /* Single chain for 4K EEPROM*/ | ||
918 | ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal); | ||
919 | |||
920 | /* Initialize Ant Diversity settings from EEPROM */ | ||
921 | if (pModal->version >= 3) { | ||
922 | ant_div_control1 = pModal->antdiv_ctl1; | ||
923 | ant_div_control2 = pModal->antdiv_ctl2; | ||
924 | |||
925 | regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); | ||
926 | regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL)); | ||
927 | |||
928 | regVal |= SM(ant_div_control1, | ||
929 | AR_PHY_9285_ANT_DIV_CTL); | ||
930 | regVal |= SM(ant_div_control2, | ||
931 | AR_PHY_9285_ANT_DIV_ALT_LNACONF); | ||
932 | regVal |= SM((ant_div_control2 >> 2), | ||
933 | AR_PHY_9285_ANT_DIV_MAIN_LNACONF); | ||
934 | regVal |= SM((ant_div_control1 >> 1), | ||
935 | AR_PHY_9285_ANT_DIV_ALT_GAINTB); | ||
936 | regVal |= SM((ant_div_control1 >> 2), | ||
937 | AR_PHY_9285_ANT_DIV_MAIN_GAINTB); | ||
938 | |||
939 | |||
940 | REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal); | ||
941 | regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); | ||
942 | regVal = REG_READ(ah, AR_PHY_CCK_DETECT); | ||
943 | regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); | ||
944 | regVal |= SM((ant_div_control1 >> 3), | ||
945 | AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); | ||
946 | |||
947 | REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal); | ||
948 | regVal = REG_READ(ah, AR_PHY_CCK_DETECT); | ||
949 | } | ||
950 | |||
951 | if (pModal->version >= 2) { | ||
952 | ob[0] = pModal->ob_0; | ||
953 | ob[1] = pModal->ob_1; | ||
954 | ob[2] = pModal->ob_2; | ||
955 | ob[3] = pModal->ob_3; | ||
956 | ob[4] = pModal->ob_4; | ||
957 | |||
958 | db1[0] = pModal->db1_0; | ||
959 | db1[1] = pModal->db1_1; | ||
960 | db1[2] = pModal->db1_2; | ||
961 | db1[3] = pModal->db1_3; | ||
962 | db1[4] = pModal->db1_4; | ||
963 | |||
964 | db2[0] = pModal->db2_0; | ||
965 | db2[1] = pModal->db2_1; | ||
966 | db2[2] = pModal->db2_2; | ||
967 | db2[3] = pModal->db2_3; | ||
968 | db2[4] = pModal->db2_4; | ||
969 | } else if (pModal->version == 1) { | ||
970 | ob[0] = pModal->ob_0; | ||
971 | ob[1] = ob[2] = ob[3] = ob[4] = pModal->ob_1; | ||
972 | db1[0] = pModal->db1_0; | ||
973 | db1[1] = db1[2] = db1[3] = db1[4] = pModal->db1_1; | ||
974 | db2[0] = pModal->db2_0; | ||
975 | db2[1] = db2[2] = db2[3] = db2[4] = pModal->db2_1; | ||
976 | } else { | ||
977 | int i; | ||
978 | |||
979 | for (i = 0; i < 5; i++) { | ||
980 | ob[i] = pModal->ob_0; | ||
981 | db1[i] = pModal->db1_0; | ||
982 | db2[i] = pModal->db1_0; | ||
983 | } | ||
984 | } | ||
985 | |||
986 | if (AR_SREV_9271(ah)) { | ||
987 | ath9k_hw_analog_shift_rmw(ah, | ||
988 | AR9285_AN_RF2G3, | ||
989 | AR9271_AN_RF2G3_OB_cck, | ||
990 | AR9271_AN_RF2G3_OB_cck_S, | ||
991 | ob[0]); | ||
992 | ath9k_hw_analog_shift_rmw(ah, | ||
993 | AR9285_AN_RF2G3, | ||
994 | AR9271_AN_RF2G3_OB_psk, | ||
995 | AR9271_AN_RF2G3_OB_psk_S, | ||
996 | ob[1]); | ||
997 | ath9k_hw_analog_shift_rmw(ah, | ||
998 | AR9285_AN_RF2G3, | ||
999 | AR9271_AN_RF2G3_OB_qam, | ||
1000 | AR9271_AN_RF2G3_OB_qam_S, | ||
1001 | ob[2]); | ||
1002 | ath9k_hw_analog_shift_rmw(ah, | ||
1003 | AR9285_AN_RF2G3, | ||
1004 | AR9271_AN_RF2G3_DB_1, | ||
1005 | AR9271_AN_RF2G3_DB_1_S, | ||
1006 | db1[0]); | ||
1007 | ath9k_hw_analog_shift_rmw(ah, | ||
1008 | AR9285_AN_RF2G4, | ||
1009 | AR9271_AN_RF2G4_DB_2, | ||
1010 | AR9271_AN_RF2G4_DB_2_S, | ||
1011 | db2[0]); | ||
1012 | } else { | ||
1013 | ath9k_hw_analog_shift_rmw(ah, | ||
1014 | AR9285_AN_RF2G3, | ||
1015 | AR9285_AN_RF2G3_OB_0, | ||
1016 | AR9285_AN_RF2G3_OB_0_S, | ||
1017 | ob[0]); | ||
1018 | ath9k_hw_analog_shift_rmw(ah, | ||
1019 | AR9285_AN_RF2G3, | ||
1020 | AR9285_AN_RF2G3_OB_1, | ||
1021 | AR9285_AN_RF2G3_OB_1_S, | ||
1022 | ob[1]); | ||
1023 | ath9k_hw_analog_shift_rmw(ah, | ||
1024 | AR9285_AN_RF2G3, | ||
1025 | AR9285_AN_RF2G3_OB_2, | ||
1026 | AR9285_AN_RF2G3_OB_2_S, | ||
1027 | ob[2]); | ||
1028 | ath9k_hw_analog_shift_rmw(ah, | ||
1029 | AR9285_AN_RF2G3, | ||
1030 | AR9285_AN_RF2G3_OB_3, | ||
1031 | AR9285_AN_RF2G3_OB_3_S, | ||
1032 | ob[3]); | ||
1033 | ath9k_hw_analog_shift_rmw(ah, | ||
1034 | AR9285_AN_RF2G3, | ||
1035 | AR9285_AN_RF2G3_OB_4, | ||
1036 | AR9285_AN_RF2G3_OB_4_S, | ||
1037 | ob[4]); | ||
1038 | |||
1039 | ath9k_hw_analog_shift_rmw(ah, | ||
1040 | AR9285_AN_RF2G3, | ||
1041 | AR9285_AN_RF2G3_DB1_0, | ||
1042 | AR9285_AN_RF2G3_DB1_0_S, | ||
1043 | db1[0]); | ||
1044 | ath9k_hw_analog_shift_rmw(ah, | ||
1045 | AR9285_AN_RF2G3, | ||
1046 | AR9285_AN_RF2G3_DB1_1, | ||
1047 | AR9285_AN_RF2G3_DB1_1_S, | ||
1048 | db1[1]); | ||
1049 | ath9k_hw_analog_shift_rmw(ah, | ||
1050 | AR9285_AN_RF2G3, | ||
1051 | AR9285_AN_RF2G3_DB1_2, | ||
1052 | AR9285_AN_RF2G3_DB1_2_S, | ||
1053 | db1[2]); | ||
1054 | ath9k_hw_analog_shift_rmw(ah, | ||
1055 | AR9285_AN_RF2G4, | ||
1056 | AR9285_AN_RF2G4_DB1_3, | ||
1057 | AR9285_AN_RF2G4_DB1_3_S, | ||
1058 | db1[3]); | ||
1059 | ath9k_hw_analog_shift_rmw(ah, | ||
1060 | AR9285_AN_RF2G4, | ||
1061 | AR9285_AN_RF2G4_DB1_4, | ||
1062 | AR9285_AN_RF2G4_DB1_4_S, db1[4]); | ||
1063 | |||
1064 | ath9k_hw_analog_shift_rmw(ah, | ||
1065 | AR9285_AN_RF2G4, | ||
1066 | AR9285_AN_RF2G4_DB2_0, | ||
1067 | AR9285_AN_RF2G4_DB2_0_S, | ||
1068 | db2[0]); | ||
1069 | ath9k_hw_analog_shift_rmw(ah, | ||
1070 | AR9285_AN_RF2G4, | ||
1071 | AR9285_AN_RF2G4_DB2_1, | ||
1072 | AR9285_AN_RF2G4_DB2_1_S, | ||
1073 | db2[1]); | ||
1074 | ath9k_hw_analog_shift_rmw(ah, | ||
1075 | AR9285_AN_RF2G4, | ||
1076 | AR9285_AN_RF2G4_DB2_2, | ||
1077 | AR9285_AN_RF2G4_DB2_2_S, | ||
1078 | db2[2]); | ||
1079 | ath9k_hw_analog_shift_rmw(ah, | ||
1080 | AR9285_AN_RF2G4, | ||
1081 | AR9285_AN_RF2G4_DB2_3, | ||
1082 | AR9285_AN_RF2G4_DB2_3_S, | ||
1083 | db2[3]); | ||
1084 | ath9k_hw_analog_shift_rmw(ah, | ||
1085 | AR9285_AN_RF2G4, | ||
1086 | AR9285_AN_RF2G4_DB2_4, | ||
1087 | AR9285_AN_RF2G4_DB2_4_S, | ||
1088 | db2[4]); | ||
1089 | } | ||
1090 | |||
1091 | |||
1092 | if (AR_SREV_9285_11(ah)) | ||
1093 | REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); | ||
1094 | |||
1095 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, | ||
1096 | pModal->switchSettling); | ||
1097 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, | ||
1098 | pModal->adcDesiredSize); | ||
1099 | |||
1100 | REG_WRITE(ah, AR_PHY_RF_CTL4, | ||
1101 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) | | ||
1102 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) | | ||
1103 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) | | ||
1104 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); | ||
1105 | |||
1106 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, | ||
1107 | pModal->txEndToRxOn); | ||
1108 | REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, | ||
1109 | pModal->thresh62); | ||
1110 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62, | ||
1111 | pModal->thresh62); | ||
1112 | |||
1113 | if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
1114 | AR5416_EEP_MINOR_VER_2) { | ||
1115 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START, | ||
1116 | pModal->txFrameToDataStart); | ||
1117 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON, | ||
1118 | pModal->txFrameToPaOn); | ||
1119 | } | ||
1120 | |||
1121 | if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
1122 | AR5416_EEP_MINOR_VER_3) { | ||
1123 | if (IS_CHAN_HT40(chan)) | ||
1124 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, | ||
1125 | AR_PHY_SETTLING_SWITCH, | ||
1126 | pModal->swSettleHt40); | ||
1127 | } | ||
1128 | } | ||
1129 | |||
1130 | static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah, | ||
1131 | struct ath9k_channel *chan) | ||
1132 | { | ||
1133 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | ||
1134 | struct modal_eep_4k_header *pModal = &eep->modalHeader; | ||
1135 | |||
1136 | return pModal->antCtrlCommon & 0xFFFF; | ||
1137 | } | ||
1138 | |||
1139 | static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah, | ||
1140 | enum ieee80211_band freq_band) | ||
1141 | { | ||
1142 | return 1; | ||
1143 | } | ||
1144 | |||
1145 | static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) | ||
1146 | { | ||
1147 | #define EEP_MAP4K_SPURCHAN \ | ||
1148 | (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan) | ||
1149 | |||
1150 | u16 spur_val = AR_NO_SPUR; | ||
1151 | |||
1152 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
1153 | "Getting spur idx %d is2Ghz. %d val %x\n", | ||
1154 | i, is2GHz, ah->config.spurchans[i][is2GHz]); | ||
1155 | |||
1156 | switch (ah->config.spurmode) { | ||
1157 | case SPUR_DISABLE: | ||
1158 | break; | ||
1159 | case SPUR_ENABLE_IOCTL: | ||
1160 | spur_val = ah->config.spurchans[i][is2GHz]; | ||
1161 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
1162 | "Getting spur val from new loc. %d\n", spur_val); | ||
1163 | break; | ||
1164 | case SPUR_ENABLE_EEPROM: | ||
1165 | spur_val = EEP_MAP4K_SPURCHAN; | ||
1166 | break; | ||
1167 | } | ||
1168 | |||
1169 | return spur_val; | ||
1170 | |||
1171 | #undef EEP_MAP4K_SPURCHAN | ||
1172 | } | ||
1173 | |||
1174 | const struct eeprom_ops eep_4k_ops = { | ||
1175 | .check_eeprom = ath9k_hw_4k_check_eeprom, | ||
1176 | .get_eeprom = ath9k_hw_4k_get_eeprom, | ||
1177 | .fill_eeprom = ath9k_hw_4k_fill_eeprom, | ||
1178 | .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver, | ||
1179 | .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev, | ||
1180 | .get_num_ant_config = ath9k_hw_4k_get_num_ant_config, | ||
1181 | .get_eeprom_antenna_cfg = ath9k_hw_4k_get_eeprom_antenna_cfg, | ||
1182 | .set_board_values = ath9k_hw_4k_set_board_values, | ||
1183 | .set_addac = ath9k_hw_4k_set_addac, | ||
1184 | .set_txpower = ath9k_hw_4k_set_txpower, | ||
1185 | .get_spur_channel = ath9k_hw_4k_get_spur_channel | ||
1186 | }; | ||
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c new file mode 100644 index 000000000000..aeb7f484b6e1 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c | |||
@@ -0,0 +1,1183 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "ath9k.h" | ||
18 | |||
19 | static int ath9k_hw_AR9287_get_eeprom_ver(struct ath_hw *ah) | ||
20 | { | ||
21 | return (ah->eeprom.map9287.baseEepHeader.version >> 12) & 0xF; | ||
22 | } | ||
23 | |||
24 | static int ath9k_hw_AR9287_get_eeprom_rev(struct ath_hw *ah) | ||
25 | { | ||
26 | return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF; | ||
27 | } | ||
28 | |||
29 | static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah) | ||
30 | { | ||
31 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | ||
32 | u16 *eep_data; | ||
33 | int addr, eep_start_loc = AR9287_EEP_START_LOC; | ||
34 | eep_data = (u16 *)eep; | ||
35 | |||
36 | if (!ath9k_hw_use_flash(ah)) { | ||
37 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
38 | "Reading from EEPROM, not flash\n"); | ||
39 | } | ||
40 | |||
41 | for (addr = 0; addr < sizeof(struct ar9287_eeprom) / sizeof(u16); | ||
42 | addr++) { | ||
43 | if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) { | ||
44 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
45 | "Unable to read eeprom region \n"); | ||
46 | return false; | ||
47 | } | ||
48 | eep_data++; | ||
49 | } | ||
50 | return true; | ||
51 | } | ||
52 | |||
53 | static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) | ||
54 | { | ||
55 | u32 sum = 0, el, integer; | ||
56 | u16 temp, word, magic, magic2, *eepdata; | ||
57 | int i, addr; | ||
58 | bool need_swap = false; | ||
59 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | ||
60 | |||
61 | if (!ath9k_hw_use_flash(ah)) { | ||
62 | if (!ath9k_hw_nvram_read | ||
63 | (ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { | ||
64 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
65 | "Reading Magic # failed\n"); | ||
66 | return false; | ||
67 | } | ||
68 | |||
69 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
70 | "Read Magic = 0x%04X\n", magic); | ||
71 | if (magic != AR5416_EEPROM_MAGIC) { | ||
72 | magic2 = swab16(magic); | ||
73 | |||
74 | if (magic2 == AR5416_EEPROM_MAGIC) { | ||
75 | need_swap = true; | ||
76 | eepdata = (u16 *)(&ah->eeprom); | ||
77 | |||
78 | for (addr = 0; | ||
79 | addr < sizeof(struct ar9287_eeprom) / sizeof(u16); | ||
80 | addr++) { | ||
81 | temp = swab16(*eepdata); | ||
82 | *eepdata = temp; | ||
83 | eepdata++; | ||
84 | } | ||
85 | } else { | ||
86 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
87 | "Invalid EEPROM Magic. " | ||
88 | "endianness mismatch.\n"); | ||
89 | return -EINVAL; | ||
90 | } | ||
91 | } | ||
92 | } | ||
93 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", need_swap ? | ||
94 | "True" : "False"); | ||
95 | |||
96 | if (need_swap) | ||
97 | el = swab16(ah->eeprom.map9287.baseEepHeader.length); | ||
98 | else | ||
99 | el = ah->eeprom.map9287.baseEepHeader.length; | ||
100 | |||
101 | if (el > sizeof(struct ar9287_eeprom)) | ||
102 | el = sizeof(struct ar9287_eeprom) / sizeof(u16); | ||
103 | else | ||
104 | el = el / sizeof(u16); | ||
105 | |||
106 | eepdata = (u16 *)(&ah->eeprom); | ||
107 | for (i = 0; i < el; i++) | ||
108 | sum ^= *eepdata++; | ||
109 | |||
110 | if (need_swap) { | ||
111 | word = swab16(eep->baseEepHeader.length); | ||
112 | eep->baseEepHeader.length = word; | ||
113 | |||
114 | word = swab16(eep->baseEepHeader.checksum); | ||
115 | eep->baseEepHeader.checksum = word; | ||
116 | |||
117 | word = swab16(eep->baseEepHeader.version); | ||
118 | eep->baseEepHeader.version = word; | ||
119 | |||
120 | word = swab16(eep->baseEepHeader.regDmn[0]); | ||
121 | eep->baseEepHeader.regDmn[0] = word; | ||
122 | |||
123 | word = swab16(eep->baseEepHeader.regDmn[1]); | ||
124 | eep->baseEepHeader.regDmn[1] = word; | ||
125 | |||
126 | word = swab16(eep->baseEepHeader.rfSilent); | ||
127 | eep->baseEepHeader.rfSilent = word; | ||
128 | |||
129 | word = swab16(eep->baseEepHeader.blueToothOptions); | ||
130 | eep->baseEepHeader.blueToothOptions = word; | ||
131 | |||
132 | word = swab16(eep->baseEepHeader.deviceCap); | ||
133 | eep->baseEepHeader.deviceCap = word; | ||
134 | |||
135 | integer = swab32(eep->modalHeader.antCtrlCommon); | ||
136 | eep->modalHeader.antCtrlCommon = integer; | ||
137 | |||
138 | for (i = 0; i < AR9287_MAX_CHAINS; i++) { | ||
139 | integer = swab32(eep->modalHeader.antCtrlChain[i]); | ||
140 | eep->modalHeader.antCtrlChain[i] = integer; | ||
141 | } | ||
142 | |||
143 | for (i = 0; i < AR9287_EEPROM_MODAL_SPURS; i++) { | ||
144 | word = swab16(eep->modalHeader.spurChans[i].spurChan); | ||
145 | eep->modalHeader.spurChans[i].spurChan = word; | ||
146 | } | ||
147 | } | ||
148 | |||
149 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER | ||
150 | || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { | ||
151 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
152 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | ||
153 | sum, ah->eep_ops->get_eeprom_ver(ah)); | ||
154 | return -EINVAL; | ||
155 | } | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah, | ||
161 | enum eeprom_param param) | ||
162 | { | ||
163 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | ||
164 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; | ||
165 | struct base_eep_ar9287_header *pBase = &eep->baseEepHeader; | ||
166 | u16 ver_minor; | ||
167 | |||
168 | ver_minor = pBase->version & AR9287_EEP_VER_MINOR_MASK; | ||
169 | switch (param) { | ||
170 | case EEP_NFTHRESH_2: | ||
171 | return pModal->noiseFloorThreshCh[0]; | ||
172 | case AR_EEPROM_MAC(0): | ||
173 | return pBase->macAddr[0] << 8 | pBase->macAddr[1]; | ||
174 | case AR_EEPROM_MAC(1): | ||
175 | return pBase->macAddr[2] << 8 | pBase->macAddr[3]; | ||
176 | case AR_EEPROM_MAC(2): | ||
177 | return pBase->macAddr[4] << 8 | pBase->macAddr[5]; | ||
178 | case EEP_REG_0: | ||
179 | return pBase->regDmn[0]; | ||
180 | case EEP_REG_1: | ||
181 | return pBase->regDmn[1]; | ||
182 | case EEP_OP_CAP: | ||
183 | return pBase->deviceCap; | ||
184 | case EEP_OP_MODE: | ||
185 | return pBase->opCapFlags; | ||
186 | case EEP_RF_SILENT: | ||
187 | return pBase->rfSilent; | ||
188 | case EEP_MINOR_REV: | ||
189 | return ver_minor; | ||
190 | case EEP_TX_MASK: | ||
191 | return pBase->txMask; | ||
192 | case EEP_RX_MASK: | ||
193 | return pBase->rxMask; | ||
194 | case EEP_DEV_TYPE: | ||
195 | return pBase->deviceType; | ||
196 | case EEP_OL_PWRCTRL: | ||
197 | return pBase->openLoopPwrCntl; | ||
198 | case EEP_TEMPSENSE_SLOPE: | ||
199 | if (ver_minor >= AR9287_EEP_MINOR_VER_2) | ||
200 | return pBase->tempSensSlope; | ||
201 | else | ||
202 | return 0; | ||
203 | case EEP_TEMPSENSE_SLOPE_PAL_ON: | ||
204 | if (ver_minor >= AR9287_EEP_MINOR_VER_3) | ||
205 | return pBase->tempSensSlopePalOn; | ||
206 | else | ||
207 | return 0; | ||
208 | default: | ||
209 | return 0; | ||
210 | } | ||
211 | } | ||
212 | |||
213 | |||
214 | static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah, | ||
215 | struct ath9k_channel *chan, | ||
216 | struct cal_data_per_freq_ar9287 *pRawDataSet, | ||
217 | u8 *bChans, u16 availPiers, | ||
218 | u16 tPdGainOverlap, int16_t *pMinCalPower, | ||
219 | u16 *pPdGainBoundaries, u8 *pPDADCValues, | ||
220 | u16 numXpdGains) | ||
221 | { | ||
222 | #define TMP_VAL_VPD_TABLE \ | ||
223 | ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep)); | ||
224 | |||
225 | int i, j, k; | ||
226 | int16_t ss; | ||
227 | u16 idxL = 0, idxR = 0, numPiers; | ||
228 | u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; | ||
229 | u8 minPwrT4[AR9287_NUM_PD_GAINS]; | ||
230 | u8 maxPwrT4[AR9287_NUM_PD_GAINS]; | ||
231 | int16_t vpdStep; | ||
232 | int16_t tmpVal; | ||
233 | u16 sizeCurrVpdTable, maxIndex, tgtIndex; | ||
234 | bool match; | ||
235 | int16_t minDelta = 0; | ||
236 | struct chan_centers centers; | ||
237 | static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS] | ||
238 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
239 | static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS] | ||
240 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
241 | static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS] | ||
242 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
243 | |||
244 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
245 | |||
246 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | ||
247 | if (bChans[numPiers] == AR9287_BCHAN_UNUSED) | ||
248 | break; | ||
249 | } | ||
250 | |||
251 | match = ath9k_hw_get_lower_upper_index( | ||
252 | (u8)FREQ2FBIN(centers.synth_center, | ||
253 | IS_CHAN_2GHZ(chan)), bChans, numPiers, | ||
254 | &idxL, &idxR); | ||
255 | |||
256 | if (match) { | ||
257 | for (i = 0; i < numXpdGains; i++) { | ||
258 | minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; | ||
259 | maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; | ||
260 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
261 | pRawDataSet[idxL].pwrPdg[i], | ||
262 | pRawDataSet[idxL].vpdPdg[i], | ||
263 | AR9287_PD_GAIN_ICEPTS, vpdTableI[i]); | ||
264 | } | ||
265 | } else { | ||
266 | for (i = 0; i < numXpdGains; i++) { | ||
267 | pVpdL = pRawDataSet[idxL].vpdPdg[i]; | ||
268 | pPwrL = pRawDataSet[idxL].pwrPdg[i]; | ||
269 | pVpdR = pRawDataSet[idxR].vpdPdg[i]; | ||
270 | pPwrR = pRawDataSet[idxR].pwrPdg[i]; | ||
271 | |||
272 | minPwrT4[i] = max(pPwrL[0], pPwrR[0]); | ||
273 | |||
274 | maxPwrT4[i] = | ||
275 | min(pPwrL[AR9287_PD_GAIN_ICEPTS - 1], | ||
276 | pPwrR[AR9287_PD_GAIN_ICEPTS - 1]); | ||
277 | |||
278 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
279 | pPwrL, pVpdL, | ||
280 | AR9287_PD_GAIN_ICEPTS, | ||
281 | vpdTableL[i]); | ||
282 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
283 | pPwrR, pVpdR, | ||
284 | AR9287_PD_GAIN_ICEPTS, | ||
285 | vpdTableR[i]); | ||
286 | |||
287 | for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { | ||
288 | vpdTableI[i][j] = | ||
289 | (u8)(ath9k_hw_interpolate((u16) | ||
290 | FREQ2FBIN(centers. synth_center, | ||
291 | IS_CHAN_2GHZ(chan)), | ||
292 | bChans[idxL], bChans[idxR], | ||
293 | vpdTableL[i][j], vpdTableR[i][j])); | ||
294 | } | ||
295 | } | ||
296 | } | ||
297 | *pMinCalPower = (int16_t)(minPwrT4[0] / 2); | ||
298 | |||
299 | k = 0; | ||
300 | for (i = 0; i < numXpdGains; i++) { | ||
301 | if (i == (numXpdGains - 1)) | ||
302 | pPdGainBoundaries[i] = (u16)(maxPwrT4[i] / 2); | ||
303 | else | ||
304 | pPdGainBoundaries[i] = (u16)((maxPwrT4[i] + | ||
305 | minPwrT4[i+1]) / 4); | ||
306 | |||
307 | pPdGainBoundaries[i] = min((u16)AR5416_MAX_RATE_POWER, | ||
308 | pPdGainBoundaries[i]); | ||
309 | |||
310 | |||
311 | if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { | ||
312 | minDelta = pPdGainBoundaries[0] - 23; | ||
313 | pPdGainBoundaries[0] = 23; | ||
314 | } else | ||
315 | minDelta = 0; | ||
316 | |||
317 | if (i == 0) { | ||
318 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
319 | ss = (int16_t)(0 - (minPwrT4[i] / 2)); | ||
320 | else | ||
321 | ss = 0; | ||
322 | } else | ||
323 | ss = (int16_t)((pPdGainBoundaries[i-1] - | ||
324 | (minPwrT4[i] / 2)) - | ||
325 | tPdGainOverlap + 1 + minDelta); | ||
326 | |||
327 | vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); | ||
328 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
329 | while ((ss < 0) && (k < (AR9287_NUM_PDADC_VALUES - 1))) { | ||
330 | tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); | ||
331 | pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); | ||
332 | ss++; | ||
333 | } | ||
334 | |||
335 | sizeCurrVpdTable = (u8)((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); | ||
336 | tgtIndex = (u8)(pPdGainBoundaries[i] + | ||
337 | tPdGainOverlap - (minPwrT4[i] / 2)); | ||
338 | maxIndex = (tgtIndex < sizeCurrVpdTable) ? | ||
339 | tgtIndex : sizeCurrVpdTable; | ||
340 | |||
341 | while ((ss < maxIndex) && (k < (AR9287_NUM_PDADC_VALUES - 1))) | ||
342 | pPDADCValues[k++] = vpdTableI[i][ss++]; | ||
343 | |||
344 | vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - | ||
345 | vpdTableI[i][sizeCurrVpdTable - 2]); | ||
346 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
347 | if (tgtIndex > maxIndex) { | ||
348 | while ((ss <= tgtIndex) && | ||
349 | (k < (AR9287_NUM_PDADC_VALUES - 1))) { | ||
350 | tmpVal = (int16_t) TMP_VAL_VPD_TABLE; | ||
351 | pPDADCValues[k++] = (u8)((tmpVal > 255) ? | ||
352 | 255 : tmpVal); | ||
353 | ss++; | ||
354 | } | ||
355 | } | ||
356 | } | ||
357 | |||
358 | while (i < AR9287_PD_GAINS_IN_MASK) { | ||
359 | pPdGainBoundaries[i] = pPdGainBoundaries[i-1]; | ||
360 | i++; | ||
361 | } | ||
362 | |||
363 | while (k < AR9287_NUM_PDADC_VALUES) { | ||
364 | pPDADCValues[k] = pPDADCValues[k-1]; | ||
365 | k++; | ||
366 | } | ||
367 | |||
368 | #undef TMP_VAL_VPD_TABLE | ||
369 | } | ||
370 | |||
371 | static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, | ||
372 | struct ath9k_channel *chan, | ||
373 | struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop, | ||
374 | u8 *pCalChans, u16 availPiers, | ||
375 | int8_t *pPwr) | ||
376 | { | ||
377 | u8 pcdac, i = 0; | ||
378 | u16 idxL = 0, idxR = 0, numPiers; | ||
379 | bool match; | ||
380 | struct chan_centers centers; | ||
381 | |||
382 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
383 | |||
384 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | ||
385 | if (pCalChans[numPiers] == AR9287_BCHAN_UNUSED) | ||
386 | break; | ||
387 | } | ||
388 | |||
389 | match = ath9k_hw_get_lower_upper_index( | ||
390 | (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), | ||
391 | pCalChans, numPiers, | ||
392 | &idxL, &idxR); | ||
393 | |||
394 | if (match) { | ||
395 | pcdac = pRawDatasetOpLoop[idxL].pcdac[0][0]; | ||
396 | *pPwr = pRawDatasetOpLoop[idxL].pwrPdg[0][0]; | ||
397 | } else { | ||
398 | pcdac = pRawDatasetOpLoop[idxR].pcdac[0][0]; | ||
399 | *pPwr = (pRawDatasetOpLoop[idxL].pwrPdg[0][0] + | ||
400 | pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2; | ||
401 | } | ||
402 | |||
403 | while ((pcdac > ah->originalGain[i]) && | ||
404 | (i < (AR9280_TX_GAIN_TABLE_SIZE - 1))) | ||
405 | i++; | ||
406 | } | ||
407 | |||
408 | static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah, | ||
409 | int32_t txPower, u16 chain) | ||
410 | { | ||
411 | u32 tmpVal; | ||
412 | u32 a; | ||
413 | |||
414 | tmpVal = REG_READ(ah, 0xa270); | ||
415 | tmpVal = tmpVal & 0xFCFFFFFF; | ||
416 | tmpVal = tmpVal | (0x3 << 24); | ||
417 | REG_WRITE(ah, 0xa270, tmpVal); | ||
418 | |||
419 | tmpVal = REG_READ(ah, 0xb270); | ||
420 | tmpVal = tmpVal & 0xFCFFFFFF; | ||
421 | tmpVal = tmpVal | (0x3 << 24); | ||
422 | REG_WRITE(ah, 0xb270, tmpVal); | ||
423 | |||
424 | if (chain == 0) { | ||
425 | tmpVal = REG_READ(ah, 0xa398); | ||
426 | tmpVal = tmpVal & 0xff00ffff; | ||
427 | a = (txPower)&0xff; | ||
428 | tmpVal = tmpVal | (a << 16); | ||
429 | REG_WRITE(ah, 0xa398, tmpVal); | ||
430 | } | ||
431 | |||
432 | if (chain == 1) { | ||
433 | tmpVal = REG_READ(ah, 0xb398); | ||
434 | tmpVal = tmpVal & 0xff00ffff; | ||
435 | a = (txPower)&0xff; | ||
436 | tmpVal = tmpVal | (a << 16); | ||
437 | REG_WRITE(ah, 0xb398, tmpVal); | ||
438 | } | ||
439 | } | ||
440 | |||
441 | static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah, | ||
442 | struct ath9k_channel *chan, | ||
443 | int16_t *pTxPowerIndexOffset) | ||
444 | { | ||
445 | struct cal_data_per_freq_ar9287 *pRawDataset; | ||
446 | struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop; | ||
447 | u8 *pCalBChans = NULL; | ||
448 | u16 pdGainOverlap_t2; | ||
449 | u8 pdadcValues[AR9287_NUM_PDADC_VALUES]; | ||
450 | u16 gainBoundaries[AR9287_PD_GAINS_IN_MASK]; | ||
451 | u16 numPiers = 0, i, j; | ||
452 | int16_t tMinCalPower; | ||
453 | u16 numXpdGain, xpdMask; | ||
454 | u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0}; | ||
455 | u32 reg32, regOffset, regChainOffset; | ||
456 | int16_t modalIdx, diff = 0; | ||
457 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; | ||
458 | modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; | ||
459 | xpdMask = pEepData->modalHeader.xpdGain; | ||
460 | if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= | ||
461 | AR9287_EEP_MINOR_VER_2) | ||
462 | pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap; | ||
463 | else | ||
464 | pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), | ||
465 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); | ||
466 | |||
467 | if (IS_CHAN_2GHZ(chan)) { | ||
468 | pCalBChans = pEepData->calFreqPier2G; | ||
469 | numPiers = AR9287_NUM_2G_CAL_PIERS; | ||
470 | if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | ||
471 | pRawDatasetOpenLoop = | ||
472 | (struct cal_data_op_loop_ar9287 *) | ||
473 | pEepData->calPierData2G[0]; | ||
474 | ah->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0]; | ||
475 | } | ||
476 | } | ||
477 | |||
478 | numXpdGain = 0; | ||
479 | for (i = 1; i <= AR9287_PD_GAINS_IN_MASK; i++) { | ||
480 | if ((xpdMask >> (AR9287_PD_GAINS_IN_MASK - i)) & 1) { | ||
481 | if (numXpdGain >= AR9287_NUM_PD_GAINS) | ||
482 | break; | ||
483 | xpdGainValues[numXpdGain] = | ||
484 | (u16)(AR9287_PD_GAINS_IN_MASK-i); | ||
485 | numXpdGain++; | ||
486 | } | ||
487 | } | ||
488 | |||
489 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, | ||
490 | (numXpdGain - 1) & 0x3); | ||
491 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, | ||
492 | xpdGainValues[0]); | ||
493 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, | ||
494 | xpdGainValues[1]); | ||
495 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, | ||
496 | xpdGainValues[2]); | ||
497 | |||
498 | for (i = 0; i < AR9287_MAX_CHAINS; i++) { | ||
499 | regChainOffset = i * 0x1000; | ||
500 | if (pEepData->baseEepHeader.txMask & (1 << i)) { | ||
501 | pRawDatasetOpenLoop = (struct cal_data_op_loop_ar9287 *) | ||
502 | pEepData->calPierData2G[i]; | ||
503 | if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | ||
504 | int8_t txPower; | ||
505 | ar9287_eeprom_get_tx_gain_index(ah, chan, | ||
506 | pRawDatasetOpenLoop, | ||
507 | pCalBChans, numPiers, | ||
508 | &txPower); | ||
509 | ar9287_eeprom_olpc_set_pdadcs(ah, txPower, i); | ||
510 | } else { | ||
511 | pRawDataset = | ||
512 | (struct cal_data_per_freq_ar9287 *) | ||
513 | pEepData->calPierData2G[i]; | ||
514 | ath9k_hw_get_AR9287_gain_boundaries_pdadcs( | ||
515 | ah, chan, pRawDataset, | ||
516 | pCalBChans, numPiers, | ||
517 | pdGainOverlap_t2, | ||
518 | &tMinCalPower, gainBoundaries, | ||
519 | pdadcValues, numXpdGain); | ||
520 | } | ||
521 | |||
522 | if (i == 0) { | ||
523 | if (!ath9k_hw_AR9287_get_eeprom( | ||
524 | ah, EEP_OL_PWRCTRL)) { | ||
525 | REG_WRITE(ah, AR_PHY_TPCRG5 + | ||
526 | regChainOffset, | ||
527 | SM(pdGainOverlap_t2, | ||
528 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | | ||
529 | SM(gainBoundaries[0], | ||
530 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | ||
531 | | SM(gainBoundaries[1], | ||
532 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | ||
533 | | SM(gainBoundaries[2], | ||
534 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | ||
535 | | SM(gainBoundaries[3], | ||
536 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); | ||
537 | } | ||
538 | } | ||
539 | |||
540 | if ((int32_t)AR9287_PWR_TABLE_OFFSET_DB != | ||
541 | pEepData->baseEepHeader.pwrTableOffset) { | ||
542 | diff = (u16) | ||
543 | (pEepData->baseEepHeader.pwrTableOffset | ||
544 | - (int32_t)AR9287_PWR_TABLE_OFFSET_DB); | ||
545 | diff *= 2; | ||
546 | |||
547 | for (j = 0; | ||
548 | j < ((u16)AR9287_NUM_PDADC_VALUES-diff); | ||
549 | j++) | ||
550 | pdadcValues[j] = pdadcValues[j+diff]; | ||
551 | |||
552 | for (j = (u16)(AR9287_NUM_PDADC_VALUES-diff); | ||
553 | j < AR9287_NUM_PDADC_VALUES; j++) | ||
554 | pdadcValues[j] = | ||
555 | pdadcValues[ | ||
556 | AR9287_NUM_PDADC_VALUES-diff]; | ||
557 | } | ||
558 | |||
559 | if (!ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | ||
560 | regOffset = AR_PHY_BASE + (672 << 2) + | ||
561 | regChainOffset; | ||
562 | for (j = 0; j < 32; j++) { | ||
563 | reg32 = ((pdadcValues[4*j + 0] | ||
564 | & 0xFF) << 0) | | ||
565 | ((pdadcValues[4*j + 1] | ||
566 | & 0xFF) << 8) | | ||
567 | ((pdadcValues[4*j + 2] | ||
568 | & 0xFF) << 16) | | ||
569 | ((pdadcValues[4*j + 3] | ||
570 | & 0xFF) << 24) ; | ||
571 | REG_WRITE(ah, regOffset, reg32); | ||
572 | |||
573 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
574 | "PDADC (%d,%4x): %4.4x %8.8x\n", | ||
575 | i, regChainOffset, regOffset, | ||
576 | reg32); | ||
577 | |||
578 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
579 | "PDADC: Chain %d | " | ||
580 | "PDADC %3d Value %3d | " | ||
581 | "PDADC %3d Value %3d | " | ||
582 | "PDADC %3d Value %3d | " | ||
583 | "PDADC %3d Value %3d |\n", | ||
584 | i, 4 * j, pdadcValues[4 * j], | ||
585 | 4 * j + 1, | ||
586 | pdadcValues[4 * j + 1], | ||
587 | 4 * j + 2, | ||
588 | pdadcValues[4 * j + 2], | ||
589 | 4 * j + 3, | ||
590 | pdadcValues[4 * j + 3]); | ||
591 | |||
592 | regOffset += 4; | ||
593 | } | ||
594 | } | ||
595 | } | ||
596 | } | ||
597 | |||
598 | *pTxPowerIndexOffset = 0; | ||
599 | } | ||
600 | |||
601 | static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, | ||
602 | struct ath9k_channel *chan, int16_t *ratesArray, u16 cfgCtl, | ||
603 | u16 AntennaReduction, u16 twiceMaxRegulatoryPower, | ||
604 | u16 powerLimit) | ||
605 | { | ||
606 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 | ||
607 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 | ||
608 | |||
609 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
610 | static const u16 tpScaleReductionTable[5] = | ||
611 | { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; | ||
612 | int i; | ||
613 | int16_t twiceLargestAntenna; | ||
614 | struct cal_ctl_data_ar9287 *rep; | ||
615 | struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} }, | ||
616 | targetPowerCck = {0, {0, 0, 0, 0} }; | ||
617 | struct cal_target_power_leg targetPowerOfdmExt = {0, {0, 0, 0, 0} }, | ||
618 | targetPowerCckExt = {0, {0, 0, 0, 0} }; | ||
619 | struct cal_target_power_ht targetPowerHt20, | ||
620 | targetPowerHt40 = {0, {0, 0, 0, 0} }; | ||
621 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; | ||
622 | u16 ctlModesFor11g[] = | ||
623 | {CTL_11B, CTL_11G, CTL_2GHT20, | ||
624 | CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40}; | ||
625 | u16 numCtlModes = 0, *pCtlMode = NULL, ctlMode, freq; | ||
626 | struct chan_centers centers; | ||
627 | int tx_chainmask; | ||
628 | u16 twiceMinEdgePower; | ||
629 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; | ||
630 | tx_chainmask = ah->txchainmask; | ||
631 | |||
632 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
633 | |||
634 | twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0], | ||
635 | pEepData->modalHeader.antennaGainCh[1]); | ||
636 | |||
637 | twiceLargestAntenna = (int16_t)min((AntennaReduction) - | ||
638 | twiceLargestAntenna, 0); | ||
639 | |||
640 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; | ||
641 | if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) | ||
642 | maxRegAllowedPower -= | ||
643 | (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); | ||
644 | |||
645 | scaledPower = min(powerLimit, maxRegAllowedPower); | ||
646 | |||
647 | switch (ar5416_get_ntxchains(tx_chainmask)) { | ||
648 | case 1: | ||
649 | break; | ||
650 | case 2: | ||
651 | scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; | ||
652 | break; | ||
653 | case 3: | ||
654 | scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; | ||
655 | break; | ||
656 | } | ||
657 | scaledPower = max((u16)0, scaledPower); | ||
658 | |||
659 | if (IS_CHAN_2GHZ(chan)) { | ||
660 | numCtlModes = | ||
661 | ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; | ||
662 | pCtlMode = ctlModesFor11g; | ||
663 | |||
664 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
665 | pEepData->calTargetPowerCck, | ||
666 | AR9287_NUM_2G_CCK_TARGET_POWERS, | ||
667 | &targetPowerCck, 4, false); | ||
668 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
669 | pEepData->calTargetPower2G, | ||
670 | AR9287_NUM_2G_20_TARGET_POWERS, | ||
671 | &targetPowerOfdm, 4, false); | ||
672 | ath9k_hw_get_target_powers(ah, chan, | ||
673 | pEepData->calTargetPower2GHT20, | ||
674 | AR9287_NUM_2G_20_TARGET_POWERS, | ||
675 | &targetPowerHt20, 8, false); | ||
676 | |||
677 | if (IS_CHAN_HT40(chan)) { | ||
678 | numCtlModes = ARRAY_SIZE(ctlModesFor11g); | ||
679 | ath9k_hw_get_target_powers(ah, chan, | ||
680 | pEepData->calTargetPower2GHT40, | ||
681 | AR9287_NUM_2G_40_TARGET_POWERS, | ||
682 | &targetPowerHt40, 8, true); | ||
683 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
684 | pEepData->calTargetPowerCck, | ||
685 | AR9287_NUM_2G_CCK_TARGET_POWERS, | ||
686 | &targetPowerCckExt, 4, true); | ||
687 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
688 | pEepData->calTargetPower2G, | ||
689 | AR9287_NUM_2G_20_TARGET_POWERS, | ||
690 | &targetPowerOfdmExt, 4, true); | ||
691 | } | ||
692 | } | ||
693 | |||
694 | for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { | ||
695 | bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || | ||
696 | (pCtlMode[ctlMode] == CTL_2GHT40); | ||
697 | if (isHt40CtlMode) | ||
698 | freq = centers.synth_center; | ||
699 | else if (pCtlMode[ctlMode] & EXT_ADDITIVE) | ||
700 | freq = centers.ext_center; | ||
701 | else | ||
702 | freq = centers.ctl_center; | ||
703 | |||
704 | if (ah->eep_ops->get_eeprom_ver(ah) == 14 && | ||
705 | ah->eep_ops->get_eeprom_rev(ah) <= 2) | ||
706 | twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
707 | |||
708 | for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { | ||
709 | if ((((cfgCtl & ~CTL_MODE_M) | | ||
710 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
711 | pEepData->ctlIndex[i]) || | ||
712 | (((cfgCtl & ~CTL_MODE_M) | | ||
713 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
714 | ((pEepData->ctlIndex[i] & | ||
715 | CTL_MODE_M) | SD_NO_CTL))) { | ||
716 | |||
717 | rep = &(pEepData->ctlData[i]); | ||
718 | twiceMinEdgePower = ath9k_hw_get_max_edge_power( | ||
719 | freq, | ||
720 | rep->ctlEdges[ar5416_get_ntxchains( | ||
721 | tx_chainmask) - 1], | ||
722 | IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES); | ||
723 | |||
724 | if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) | ||
725 | twiceMaxEdgePower = min( | ||
726 | twiceMaxEdgePower, | ||
727 | twiceMinEdgePower); | ||
728 | else { | ||
729 | twiceMaxEdgePower = twiceMinEdgePower; | ||
730 | break; | ||
731 | } | ||
732 | } | ||
733 | } | ||
734 | |||
735 | minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); | ||
736 | |||
737 | switch (pCtlMode[ctlMode]) { | ||
738 | case CTL_11B: | ||
739 | for (i = 0; | ||
740 | i < ARRAY_SIZE(targetPowerCck.tPow2x); | ||
741 | i++) { | ||
742 | targetPowerCck.tPow2x[i] = (u8)min( | ||
743 | (u16)targetPowerCck.tPow2x[i], | ||
744 | minCtlPower); | ||
745 | } | ||
746 | break; | ||
747 | case CTL_11A: | ||
748 | case CTL_11G: | ||
749 | for (i = 0; | ||
750 | i < ARRAY_SIZE(targetPowerOfdm.tPow2x); | ||
751 | i++) { | ||
752 | targetPowerOfdm.tPow2x[i] = (u8)min( | ||
753 | (u16)targetPowerOfdm.tPow2x[i], | ||
754 | minCtlPower); | ||
755 | } | ||
756 | break; | ||
757 | case CTL_5GHT20: | ||
758 | case CTL_2GHT20: | ||
759 | for (i = 0; | ||
760 | i < ARRAY_SIZE(targetPowerHt20.tPow2x); | ||
761 | i++) { | ||
762 | targetPowerHt20.tPow2x[i] = (u8)min( | ||
763 | (u16)targetPowerHt20.tPow2x[i], | ||
764 | minCtlPower); | ||
765 | } | ||
766 | break; | ||
767 | case CTL_11B_EXT: | ||
768 | targetPowerCckExt.tPow2x[0] = (u8)min( | ||
769 | (u16)targetPowerCckExt.tPow2x[0], | ||
770 | minCtlPower); | ||
771 | break; | ||
772 | case CTL_11A_EXT: | ||
773 | case CTL_11G_EXT: | ||
774 | targetPowerOfdmExt.tPow2x[0] = (u8)min( | ||
775 | (u16)targetPowerOfdmExt.tPow2x[0], | ||
776 | minCtlPower); | ||
777 | break; | ||
778 | case CTL_5GHT40: | ||
779 | case CTL_2GHT40: | ||
780 | for (i = 0; | ||
781 | i < ARRAY_SIZE(targetPowerHt40.tPow2x); | ||
782 | i++) { | ||
783 | targetPowerHt40.tPow2x[i] = (u8)min( | ||
784 | (u16)targetPowerHt40.tPow2x[i], | ||
785 | minCtlPower); | ||
786 | } | ||
787 | break; | ||
788 | default: | ||
789 | break; | ||
790 | } | ||
791 | } | ||
792 | |||
793 | ratesArray[rate6mb] = | ||
794 | ratesArray[rate9mb] = | ||
795 | ratesArray[rate12mb] = | ||
796 | ratesArray[rate18mb] = | ||
797 | ratesArray[rate24mb] = | ||
798 | targetPowerOfdm.tPow2x[0]; | ||
799 | |||
800 | ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; | ||
801 | ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; | ||
802 | ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; | ||
803 | ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; | ||
804 | |||
805 | for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) | ||
806 | ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; | ||
807 | |||
808 | if (IS_CHAN_2GHZ(chan)) { | ||
809 | ratesArray[rate1l] = targetPowerCck.tPow2x[0]; | ||
810 | ratesArray[rate2s] = ratesArray[rate2l] = | ||
811 | targetPowerCck.tPow2x[1]; | ||
812 | ratesArray[rate5_5s] = ratesArray[rate5_5l] = | ||
813 | targetPowerCck.tPow2x[2]; | ||
814 | ratesArray[rate11s] = ratesArray[rate11l] = | ||
815 | targetPowerCck.tPow2x[3]; | ||
816 | } | ||
817 | if (IS_CHAN_HT40(chan)) { | ||
818 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) | ||
819 | ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i]; | ||
820 | |||
821 | ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; | ||
822 | ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; | ||
823 | ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; | ||
824 | if (IS_CHAN_2GHZ(chan)) | ||
825 | ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; | ||
826 | } | ||
827 | |||
828 | #undef REDUCE_SCALED_POWER_BY_TWO_CHAIN | ||
829 | #undef REDUCE_SCALED_POWER_BY_THREE_CHAIN | ||
830 | } | ||
831 | |||
832 | static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, | ||
833 | struct ath9k_channel *chan, u16 cfgCtl, | ||
834 | u8 twiceAntennaReduction, | ||
835 | u8 twiceMaxRegulatoryPower, | ||
836 | u8 powerLimit) | ||
837 | { | ||
838 | #define INCREASE_MAXPOW_BY_TWO_CHAIN 6 | ||
839 | #define INCREASE_MAXPOW_BY_THREE_CHAIN 10 | ||
840 | |||
841 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; | ||
842 | struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; | ||
843 | int16_t ratesArray[Ar5416RateSize]; | ||
844 | int16_t txPowerIndexOffset = 0; | ||
845 | u8 ht40PowerIncForPdadc = 2; | ||
846 | int i; | ||
847 | |||
848 | memset(ratesArray, 0, sizeof(ratesArray)); | ||
849 | |||
850 | if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= | ||
851 | AR9287_EEP_MINOR_VER_2) | ||
852 | ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; | ||
853 | |||
854 | ath9k_hw_set_AR9287_power_per_rate_table(ah, chan, | ||
855 | &ratesArray[0], cfgCtl, | ||
856 | twiceAntennaReduction, | ||
857 | twiceMaxRegulatoryPower, | ||
858 | powerLimit); | ||
859 | |||
860 | ath9k_hw_set_AR9287_power_cal_table(ah, chan, &txPowerIndexOffset); | ||
861 | |||
862 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { | ||
863 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); | ||
864 | if (ratesArray[i] > AR9287_MAX_RATE_POWER) | ||
865 | ratesArray[i] = AR9287_MAX_RATE_POWER; | ||
866 | } | ||
867 | |||
868 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
869 | for (i = 0; i < Ar5416RateSize; i++) | ||
870 | ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; | ||
871 | } | ||
872 | |||
873 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, | ||
874 | ATH9K_POW_SM(ratesArray[rate18mb], 24) | ||
875 | | ATH9K_POW_SM(ratesArray[rate12mb], 16) | ||
876 | | ATH9K_POW_SM(ratesArray[rate9mb], 8) | ||
877 | | ATH9K_POW_SM(ratesArray[rate6mb], 0)); | ||
878 | |||
879 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, | ||
880 | ATH9K_POW_SM(ratesArray[rate54mb], 24) | ||
881 | | ATH9K_POW_SM(ratesArray[rate48mb], 16) | ||
882 | | ATH9K_POW_SM(ratesArray[rate36mb], 8) | ||
883 | | ATH9K_POW_SM(ratesArray[rate24mb], 0)); | ||
884 | |||
885 | if (IS_CHAN_2GHZ(chan)) { | ||
886 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, | ||
887 | ATH9K_POW_SM(ratesArray[rate2s], 24) | ||
888 | | ATH9K_POW_SM(ratesArray[rate2l], 16) | ||
889 | | ATH9K_POW_SM(ratesArray[rateXr], 8) | ||
890 | | ATH9K_POW_SM(ratesArray[rate1l], 0)); | ||
891 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, | ||
892 | ATH9K_POW_SM(ratesArray[rate11s], 24) | ||
893 | | ATH9K_POW_SM(ratesArray[rate11l], 16) | ||
894 | | ATH9K_POW_SM(ratesArray[rate5_5s], 8) | ||
895 | | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); | ||
896 | } | ||
897 | |||
898 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, | ||
899 | ATH9K_POW_SM(ratesArray[rateHt20_3], 24) | ||
900 | | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) | ||
901 | | ATH9K_POW_SM(ratesArray[rateHt20_1], 8) | ||
902 | | ATH9K_POW_SM(ratesArray[rateHt20_0], 0)); | ||
903 | |||
904 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, | ||
905 | ATH9K_POW_SM(ratesArray[rateHt20_7], 24) | ||
906 | | ATH9K_POW_SM(ratesArray[rateHt20_6], 16) | ||
907 | | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) | ||
908 | | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); | ||
909 | |||
910 | if (IS_CHAN_HT40(chan)) { | ||
911 | if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | ||
912 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, | ||
913 | ATH9K_POW_SM(ratesArray[rateHt40_3], 24) | ||
914 | | ATH9K_POW_SM(ratesArray[rateHt40_2], 16) | ||
915 | | ATH9K_POW_SM(ratesArray[rateHt40_1], 8) | ||
916 | | ATH9K_POW_SM(ratesArray[rateHt40_0], 0)); | ||
917 | |||
918 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, | ||
919 | ATH9K_POW_SM(ratesArray[rateHt40_7], 24) | ||
920 | | ATH9K_POW_SM(ratesArray[rateHt40_6], 16) | ||
921 | | ATH9K_POW_SM(ratesArray[rateHt40_5], 8) | ||
922 | | ATH9K_POW_SM(ratesArray[rateHt40_4], 0)); | ||
923 | } else { | ||
924 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, | ||
925 | ATH9K_POW_SM(ratesArray[rateHt40_3] + | ||
926 | ht40PowerIncForPdadc, 24) | ||
927 | | ATH9K_POW_SM(ratesArray[rateHt40_2] + | ||
928 | ht40PowerIncForPdadc, 16) | ||
929 | | ATH9K_POW_SM(ratesArray[rateHt40_1] + | ||
930 | ht40PowerIncForPdadc, 8) | ||
931 | | ATH9K_POW_SM(ratesArray[rateHt40_0] + | ||
932 | ht40PowerIncForPdadc, 0)); | ||
933 | |||
934 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, | ||
935 | ATH9K_POW_SM(ratesArray[rateHt40_7] + | ||
936 | ht40PowerIncForPdadc, 24) | ||
937 | | ATH9K_POW_SM(ratesArray[rateHt40_6] + | ||
938 | ht40PowerIncForPdadc, 16) | ||
939 | | ATH9K_POW_SM(ratesArray[rateHt40_5] + | ||
940 | ht40PowerIncForPdadc, 8) | ||
941 | | ATH9K_POW_SM(ratesArray[rateHt40_4] + | ||
942 | ht40PowerIncForPdadc, 0)); | ||
943 | } | ||
944 | |||
945 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, | ||
946 | ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) | ||
947 | | ATH9K_POW_SM(ratesArray[rateExtCck], 16) | ||
948 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | ||
949 | | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); | ||
950 | } | ||
951 | |||
952 | if (IS_CHAN_2GHZ(chan)) | ||
953 | i = rate1l; | ||
954 | else | ||
955 | i = rate6mb; | ||
956 | |||
957 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
958 | ah->regulatory.max_power_level = | ||
959 | ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2; | ||
960 | else | ||
961 | ah->regulatory.max_power_level = ratesArray[i]; | ||
962 | |||
963 | switch (ar5416_get_ntxchains(ah->txchainmask)) { | ||
964 | case 1: | ||
965 | break; | ||
966 | case 2: | ||
967 | ah->regulatory.max_power_level += | ||
968 | INCREASE_MAXPOW_BY_TWO_CHAIN; | ||
969 | break; | ||
970 | case 3: | ||
971 | ah->regulatory.max_power_level += | ||
972 | INCREASE_MAXPOW_BY_THREE_CHAIN; | ||
973 | break; | ||
974 | default: | ||
975 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
976 | "Invalid chainmask configuration\n"); | ||
977 | break; | ||
978 | } | ||
979 | } | ||
980 | |||
981 | static void ath9k_hw_AR9287_set_addac(struct ath_hw *ah, | ||
982 | struct ath9k_channel *chan) | ||
983 | { | ||
984 | } | ||
985 | |||
986 | static void ath9k_hw_AR9287_set_board_values(struct ath_hw *ah, | ||
987 | struct ath9k_channel *chan) | ||
988 | { | ||
989 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | ||
990 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; | ||
991 | u16 antWrites[AR9287_ANT_16S]; | ||
992 | u32 regChainOffset; | ||
993 | u8 txRxAttenLocal; | ||
994 | int i, j, offset_num; | ||
995 | |||
996 | pModal = &eep->modalHeader; | ||
997 | |||
998 | antWrites[0] = (u16)((pModal->antCtrlCommon >> 28) & 0xF); | ||
999 | antWrites[1] = (u16)((pModal->antCtrlCommon >> 24) & 0xF); | ||
1000 | antWrites[2] = (u16)((pModal->antCtrlCommon >> 20) & 0xF); | ||
1001 | antWrites[3] = (u16)((pModal->antCtrlCommon >> 16) & 0xF); | ||
1002 | antWrites[4] = (u16)((pModal->antCtrlCommon >> 12) & 0xF); | ||
1003 | antWrites[5] = (u16)((pModal->antCtrlCommon >> 8) & 0xF); | ||
1004 | antWrites[6] = (u16)((pModal->antCtrlCommon >> 4) & 0xF); | ||
1005 | antWrites[7] = (u16)(pModal->antCtrlCommon & 0xF); | ||
1006 | |||
1007 | offset_num = 8; | ||
1008 | |||
1009 | for (i = 0, j = offset_num; i < AR9287_MAX_CHAINS; i++) { | ||
1010 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 28) & 0xf); | ||
1011 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 10) & 0x3); | ||
1012 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 8) & 0x3); | ||
1013 | antWrites[j++] = 0; | ||
1014 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 6) & 0x3); | ||
1015 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 4) & 0x3); | ||
1016 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 2) & 0x3); | ||
1017 | antWrites[j++] = (u16)(pModal->antCtrlChain[i] & 0x3); | ||
1018 | } | ||
1019 | |||
1020 | REG_WRITE(ah, AR_PHY_SWITCH_COM, | ||
1021 | ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); | ||
1022 | |||
1023 | for (i = 0; i < AR9287_MAX_CHAINS; i++) { | ||
1024 | regChainOffset = i * 0x1000; | ||
1025 | |||
1026 | REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, | ||
1027 | pModal->antCtrlChain[i]); | ||
1028 | |||
1029 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, | ||
1030 | (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) | ||
1031 | & ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | | ||
1032 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | | ||
1033 | SM(pModal->iqCalICh[i], | ||
1034 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | | ||
1035 | SM(pModal->iqCalQCh[i], | ||
1036 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); | ||
1037 | |||
1038 | txRxAttenLocal = pModal->txRxAttenCh[i]; | ||
1039 | |||
1040 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1041 | AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, | ||
1042 | pModal->bswMargin[i]); | ||
1043 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1044 | AR_PHY_GAIN_2GHZ_XATTEN1_DB, | ||
1045 | pModal->bswAtten[i]); | ||
1046 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, | ||
1047 | AR9280_PHY_RXGAIN_TXRX_ATTEN, | ||
1048 | txRxAttenLocal); | ||
1049 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, | ||
1050 | AR9280_PHY_RXGAIN_TXRX_MARGIN, | ||
1051 | pModal->rxTxMarginCh[i]); | ||
1052 | } | ||
1053 | |||
1054 | |||
1055 | if (IS_CHAN_HT40(chan)) | ||
1056 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, | ||
1057 | AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40); | ||
1058 | else | ||
1059 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, | ||
1060 | AR_PHY_SETTLING_SWITCH, pModal->switchSettling); | ||
1061 | |||
1062 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, | ||
1063 | AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize); | ||
1064 | |||
1065 | REG_WRITE(ah, AR_PHY_RF_CTL4, | ||
1066 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) | ||
1067 | | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) | ||
1068 | | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) | ||
1069 | | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); | ||
1070 | |||
1071 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, | ||
1072 | AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn); | ||
1073 | |||
1074 | REG_RMW_FIELD(ah, AR_PHY_CCA, | ||
1075 | AR9280_PHY_CCA_THRESH62, pModal->thresh62); | ||
1076 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, | ||
1077 | AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62); | ||
1078 | |||
1079 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB1, | ||
1080 | AR9287_AN_RF2G3_DB1_S, pModal->db1); | ||
1081 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB2, | ||
1082 | AR9287_AN_RF2G3_DB2_S, pModal->db2); | ||
1083 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, | ||
1084 | AR9287_AN_RF2G3_OB_CCK, | ||
1085 | AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck); | ||
1086 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, | ||
1087 | AR9287_AN_RF2G3_OB_PSK, | ||
1088 | AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk); | ||
1089 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, | ||
1090 | AR9287_AN_RF2G3_OB_QAM, | ||
1091 | AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam); | ||
1092 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, | ||
1093 | AR9287_AN_RF2G3_OB_PAL_OFF, | ||
1094 | AR9287_AN_RF2G3_OB_PAL_OFF_S, | ||
1095 | pModal->ob_pal_off); | ||
1096 | |||
1097 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | ||
1098 | AR9287_AN_RF2G3_DB1, AR9287_AN_RF2G3_DB1_S, | ||
1099 | pModal->db1); | ||
1100 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, AR9287_AN_RF2G3_DB2, | ||
1101 | AR9287_AN_RF2G3_DB2_S, pModal->db2); | ||
1102 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | ||
1103 | AR9287_AN_RF2G3_OB_CCK, | ||
1104 | AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck); | ||
1105 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | ||
1106 | AR9287_AN_RF2G3_OB_PSK, | ||
1107 | AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk); | ||
1108 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | ||
1109 | AR9287_AN_RF2G3_OB_QAM, | ||
1110 | AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam); | ||
1111 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | ||
1112 | AR9287_AN_RF2G3_OB_PAL_OFF, | ||
1113 | AR9287_AN_RF2G3_OB_PAL_OFF_S, | ||
1114 | pModal->ob_pal_off); | ||
1115 | |||
1116 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, | ||
1117 | AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart); | ||
1118 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, | ||
1119 | AR_PHY_TX_END_PA_ON, pModal->txFrameToPaOn); | ||
1120 | |||
1121 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TOP2, | ||
1122 | AR9287_AN_TOP2_XPABIAS_LVL, | ||
1123 | AR9287_AN_TOP2_XPABIAS_LVL_S, | ||
1124 | pModal->xpaBiasLvl); | ||
1125 | } | ||
1126 | |||
1127 | static u8 ath9k_hw_AR9287_get_num_ant_config(struct ath_hw *ah, | ||
1128 | enum ieee80211_band freq_band) | ||
1129 | { | ||
1130 | return 1; | ||
1131 | } | ||
1132 | |||
1133 | static u16 ath9k_hw_AR9287_get_eeprom_antenna_cfg(struct ath_hw *ah, | ||
1134 | struct ath9k_channel *chan) | ||
1135 | { | ||
1136 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | ||
1137 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; | ||
1138 | |||
1139 | return pModal->antCtrlCommon & 0xFFFF; | ||
1140 | } | ||
1141 | |||
1142 | static u16 ath9k_hw_AR9287_get_spur_channel(struct ath_hw *ah, | ||
1143 | u16 i, bool is2GHz) | ||
1144 | { | ||
1145 | #define EEP_MAP9287_SPURCHAN \ | ||
1146 | (ah->eeprom.map9287.modalHeader.spurChans[i].spurChan) | ||
1147 | u16 spur_val = AR_NO_SPUR; | ||
1148 | |||
1149 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
1150 | "Getting spur idx %d is2Ghz. %d val %x\n", | ||
1151 | i, is2GHz, ah->config.spurchans[i][is2GHz]); | ||
1152 | |||
1153 | switch (ah->config.spurmode) { | ||
1154 | case SPUR_DISABLE: | ||
1155 | break; | ||
1156 | case SPUR_ENABLE_IOCTL: | ||
1157 | spur_val = ah->config.spurchans[i][is2GHz]; | ||
1158 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
1159 | "Getting spur val from new loc. %d\n", spur_val); | ||
1160 | break; | ||
1161 | case SPUR_ENABLE_EEPROM: | ||
1162 | spur_val = EEP_MAP9287_SPURCHAN; | ||
1163 | break; | ||
1164 | } | ||
1165 | |||
1166 | return spur_val; | ||
1167 | |||
1168 | #undef EEP_MAP9287_SPURCHAN | ||
1169 | } | ||
1170 | |||
1171 | const struct eeprom_ops eep_AR9287_ops = { | ||
1172 | .check_eeprom = ath9k_hw_AR9287_check_eeprom, | ||
1173 | .get_eeprom = ath9k_hw_AR9287_get_eeprom, | ||
1174 | .fill_eeprom = ath9k_hw_AR9287_fill_eeprom, | ||
1175 | .get_eeprom_ver = ath9k_hw_AR9287_get_eeprom_ver, | ||
1176 | .get_eeprom_rev = ath9k_hw_AR9287_get_eeprom_rev, | ||
1177 | .get_num_ant_config = ath9k_hw_AR9287_get_num_ant_config, | ||
1178 | .get_eeprom_antenna_cfg = ath9k_hw_AR9287_get_eeprom_antenna_cfg, | ||
1179 | .set_board_values = ath9k_hw_AR9287_set_board_values, | ||
1180 | .set_addac = ath9k_hw_AR9287_set_addac, | ||
1181 | .set_txpower = ath9k_hw_AR9287_set_txpower, | ||
1182 | .get_spur_channel = ath9k_hw_AR9287_get_spur_channel | ||
1183 | }; | ||
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c new file mode 100644 index 000000000000..5211ad94c8fb --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
@@ -0,0 +1,1385 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "ath9k.h" | ||
18 | |||
19 | static void ath9k_get_txgain_index(struct ath_hw *ah, | ||
20 | struct ath9k_channel *chan, | ||
21 | struct calDataPerFreqOpLoop *rawDatasetOpLoop, | ||
22 | u8 *calChans, u16 availPiers, u8 *pwr, u8 *pcdacIdx) | ||
23 | { | ||
24 | u8 pcdac, i = 0; | ||
25 | u16 idxL = 0, idxR = 0, numPiers; | ||
26 | bool match; | ||
27 | struct chan_centers centers; | ||
28 | |||
29 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
30 | |||
31 | for (numPiers = 0; numPiers < availPiers; numPiers++) | ||
32 | if (calChans[numPiers] == AR5416_BCHAN_UNUSED) | ||
33 | break; | ||
34 | |||
35 | match = ath9k_hw_get_lower_upper_index( | ||
36 | (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), | ||
37 | calChans, numPiers, &idxL, &idxR); | ||
38 | if (match) { | ||
39 | pcdac = rawDatasetOpLoop[idxL].pcdac[0][0]; | ||
40 | *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0]; | ||
41 | } else { | ||
42 | pcdac = rawDatasetOpLoop[idxR].pcdac[0][0]; | ||
43 | *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] + | ||
44 | rawDatasetOpLoop[idxR].pwrPdg[0][0])/2; | ||
45 | } | ||
46 | |||
47 | while (pcdac > ah->originalGain[i] && | ||
48 | i < (AR9280_TX_GAIN_TABLE_SIZE - 1)) | ||
49 | i++; | ||
50 | |||
51 | *pcdacIdx = i; | ||
52 | return; | ||
53 | } | ||
54 | |||
55 | static void ath9k_olc_get_pdadcs(struct ath_hw *ah, | ||
56 | u32 initTxGain, | ||
57 | int txPower, | ||
58 | u8 *pPDADCValues) | ||
59 | { | ||
60 | u32 i; | ||
61 | u32 offset; | ||
62 | |||
63 | REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0, | ||
64 | AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); | ||
65 | REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1, | ||
66 | AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); | ||
67 | |||
68 | REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7, | ||
69 | AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain); | ||
70 | |||
71 | offset = txPower; | ||
72 | for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++) | ||
73 | if (i < offset) | ||
74 | pPDADCValues[i] = 0x0; | ||
75 | else | ||
76 | pPDADCValues[i] = 0xFF; | ||
77 | } | ||
78 | |||
79 | static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah) | ||
80 | { | ||
81 | return ((ah->eeprom.def.baseEepHeader.version >> 12) & 0xF); | ||
82 | } | ||
83 | |||
84 | static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah) | ||
85 | { | ||
86 | return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF); | ||
87 | } | ||
88 | |||
89 | static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) | ||
90 | { | ||
91 | #define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16)) | ||
92 | u16 *eep_data = (u16 *)&ah->eeprom.def; | ||
93 | int addr, ar5416_eep_start_loc = 0x100; | ||
94 | |||
95 | for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) { | ||
96 | if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc, | ||
97 | eep_data)) { | ||
98 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
99 | "Unable to read eeprom region\n"); | ||
100 | return false; | ||
101 | } | ||
102 | eep_data++; | ||
103 | } | ||
104 | return true; | ||
105 | #undef SIZE_EEPROM_DEF | ||
106 | } | ||
107 | |||
108 | static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | ||
109 | { | ||
110 | struct ar5416_eeprom_def *eep = | ||
111 | (struct ar5416_eeprom_def *) &ah->eeprom.def; | ||
112 | u16 *eepdata, temp, magic, magic2; | ||
113 | u32 sum = 0, el; | ||
114 | bool need_swap = false; | ||
115 | int i, addr, size; | ||
116 | |||
117 | if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { | ||
118 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Reading Magic # failed\n"); | ||
119 | return false; | ||
120 | } | ||
121 | |||
122 | if (!ath9k_hw_use_flash(ah)) { | ||
123 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
124 | "Read Magic = 0x%04X\n", magic); | ||
125 | |||
126 | if (magic != AR5416_EEPROM_MAGIC) { | ||
127 | magic2 = swab16(magic); | ||
128 | |||
129 | if (magic2 == AR5416_EEPROM_MAGIC) { | ||
130 | size = sizeof(struct ar5416_eeprom_def); | ||
131 | need_swap = true; | ||
132 | eepdata = (u16 *) (&ah->eeprom); | ||
133 | |||
134 | for (addr = 0; addr < size / sizeof(u16); addr++) { | ||
135 | temp = swab16(*eepdata); | ||
136 | *eepdata = temp; | ||
137 | eepdata++; | ||
138 | } | ||
139 | } else { | ||
140 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
141 | "Invalid EEPROM Magic. " | ||
142 | "Endianness mismatch.\n"); | ||
143 | return -EINVAL; | ||
144 | } | ||
145 | } | ||
146 | } | ||
147 | |||
148 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", | ||
149 | need_swap ? "True" : "False"); | ||
150 | |||
151 | if (need_swap) | ||
152 | el = swab16(ah->eeprom.def.baseEepHeader.length); | ||
153 | else | ||
154 | el = ah->eeprom.def.baseEepHeader.length; | ||
155 | |||
156 | if (el > sizeof(struct ar5416_eeprom_def)) | ||
157 | el = sizeof(struct ar5416_eeprom_def) / sizeof(u16); | ||
158 | else | ||
159 | el = el / sizeof(u16); | ||
160 | |||
161 | eepdata = (u16 *)(&ah->eeprom); | ||
162 | |||
163 | for (i = 0; i < el; i++) | ||
164 | sum ^= *eepdata++; | ||
165 | |||
166 | if (need_swap) { | ||
167 | u32 integer, j; | ||
168 | u16 word; | ||
169 | |||
170 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
171 | "EEPROM Endianness is not native.. Changing.\n"); | ||
172 | |||
173 | word = swab16(eep->baseEepHeader.length); | ||
174 | eep->baseEepHeader.length = word; | ||
175 | |||
176 | word = swab16(eep->baseEepHeader.checksum); | ||
177 | eep->baseEepHeader.checksum = word; | ||
178 | |||
179 | word = swab16(eep->baseEepHeader.version); | ||
180 | eep->baseEepHeader.version = word; | ||
181 | |||
182 | word = swab16(eep->baseEepHeader.regDmn[0]); | ||
183 | eep->baseEepHeader.regDmn[0] = word; | ||
184 | |||
185 | word = swab16(eep->baseEepHeader.regDmn[1]); | ||
186 | eep->baseEepHeader.regDmn[1] = word; | ||
187 | |||
188 | word = swab16(eep->baseEepHeader.rfSilent); | ||
189 | eep->baseEepHeader.rfSilent = word; | ||
190 | |||
191 | word = swab16(eep->baseEepHeader.blueToothOptions); | ||
192 | eep->baseEepHeader.blueToothOptions = word; | ||
193 | |||
194 | word = swab16(eep->baseEepHeader.deviceCap); | ||
195 | eep->baseEepHeader.deviceCap = word; | ||
196 | |||
197 | for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) { | ||
198 | struct modal_eep_header *pModal = | ||
199 | &eep->modalHeader[j]; | ||
200 | integer = swab32(pModal->antCtrlCommon); | ||
201 | pModal->antCtrlCommon = integer; | ||
202 | |||
203 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
204 | integer = swab32(pModal->antCtrlChain[i]); | ||
205 | pModal->antCtrlChain[i] = integer; | ||
206 | } | ||
207 | |||
208 | for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { | ||
209 | word = swab16(pModal->spurChans[i].spurChan); | ||
210 | pModal->spurChans[i].spurChan = word; | ||
211 | } | ||
212 | } | ||
213 | } | ||
214 | |||
215 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || | ||
216 | ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { | ||
217 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
218 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | ||
219 | sum, ah->eep_ops->get_eeprom_ver(ah)); | ||
220 | return -EINVAL; | ||
221 | } | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, | ||
227 | enum eeprom_param param) | ||
228 | { | ||
229 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; | ||
230 | struct modal_eep_header *pModal = eep->modalHeader; | ||
231 | struct base_eep_header *pBase = &eep->baseEepHeader; | ||
232 | |||
233 | switch (param) { | ||
234 | case EEP_NFTHRESH_5: | ||
235 | return pModal[0].noiseFloorThreshCh[0]; | ||
236 | case EEP_NFTHRESH_2: | ||
237 | return pModal[1].noiseFloorThreshCh[0]; | ||
238 | case AR_EEPROM_MAC(0): | ||
239 | return pBase->macAddr[0] << 8 | pBase->macAddr[1]; | ||
240 | case AR_EEPROM_MAC(1): | ||
241 | return pBase->macAddr[2] << 8 | pBase->macAddr[3]; | ||
242 | case AR_EEPROM_MAC(2): | ||
243 | return pBase->macAddr[4] << 8 | pBase->macAddr[5]; | ||
244 | case EEP_REG_0: | ||
245 | return pBase->regDmn[0]; | ||
246 | case EEP_REG_1: | ||
247 | return pBase->regDmn[1]; | ||
248 | case EEP_OP_CAP: | ||
249 | return pBase->deviceCap; | ||
250 | case EEP_OP_MODE: | ||
251 | return pBase->opCapFlags; | ||
252 | case EEP_RF_SILENT: | ||
253 | return pBase->rfSilent; | ||
254 | case EEP_OB_5: | ||
255 | return pModal[0].ob; | ||
256 | case EEP_DB_5: | ||
257 | return pModal[0].db; | ||
258 | case EEP_OB_2: | ||
259 | return pModal[1].ob; | ||
260 | case EEP_DB_2: | ||
261 | return pModal[1].db; | ||
262 | case EEP_MINOR_REV: | ||
263 | return AR5416_VER_MASK; | ||
264 | case EEP_TX_MASK: | ||
265 | return pBase->txMask; | ||
266 | case EEP_RX_MASK: | ||
267 | return pBase->rxMask; | ||
268 | case EEP_RXGAIN_TYPE: | ||
269 | return pBase->rxGainType; | ||
270 | case EEP_TXGAIN_TYPE: | ||
271 | return pBase->txGainType; | ||
272 | case EEP_OL_PWRCTRL: | ||
273 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) | ||
274 | return pBase->openLoopPwrCntl ? true : false; | ||
275 | else | ||
276 | return false; | ||
277 | case EEP_RC_CHAIN_MASK: | ||
278 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) | ||
279 | return pBase->rcChainMask; | ||
280 | else | ||
281 | return 0; | ||
282 | case EEP_DAC_HPWR_5G: | ||
283 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) | ||
284 | return pBase->dacHiPwrMode_5G; | ||
285 | else | ||
286 | return 0; | ||
287 | case EEP_FRAC_N_5G: | ||
288 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22) | ||
289 | return pBase->frac_n_5g; | ||
290 | else | ||
291 | return 0; | ||
292 | default: | ||
293 | return 0; | ||
294 | } | ||
295 | } | ||
296 | |||
297 | static void ath9k_hw_def_set_gain(struct ath_hw *ah, | ||
298 | struct modal_eep_header *pModal, | ||
299 | struct ar5416_eeprom_def *eep, | ||
300 | u8 txRxAttenLocal, int regChainOffset, int i) | ||
301 | { | ||
302 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { | ||
303 | txRxAttenLocal = pModal->txRxAttenCh[i]; | ||
304 | |||
305 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
306 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
307 | AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, | ||
308 | pModal->bswMargin[i]); | ||
309 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
310 | AR_PHY_GAIN_2GHZ_XATTEN1_DB, | ||
311 | pModal->bswAtten[i]); | ||
312 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
313 | AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, | ||
314 | pModal->xatten2Margin[i]); | ||
315 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
316 | AR_PHY_GAIN_2GHZ_XATTEN2_DB, | ||
317 | pModal->xatten2Db[i]); | ||
318 | } else { | ||
319 | REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
320 | (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & | ||
321 | ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) | ||
322 | | SM(pModal-> bswMargin[i], | ||
323 | AR_PHY_GAIN_2GHZ_BSW_MARGIN)); | ||
324 | REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
325 | (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & | ||
326 | ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) | ||
327 | | SM(pModal->bswAtten[i], | ||
328 | AR_PHY_GAIN_2GHZ_BSW_ATTEN)); | ||
329 | } | ||
330 | } | ||
331 | |||
332 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
333 | REG_RMW_FIELD(ah, | ||
334 | AR_PHY_RXGAIN + regChainOffset, | ||
335 | AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); | ||
336 | REG_RMW_FIELD(ah, | ||
337 | AR_PHY_RXGAIN + regChainOffset, | ||
338 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]); | ||
339 | } else { | ||
340 | REG_WRITE(ah, | ||
341 | AR_PHY_RXGAIN + regChainOffset, | ||
342 | (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) & | ||
343 | ~AR_PHY_RXGAIN_TXRX_ATTEN) | ||
344 | | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN)); | ||
345 | REG_WRITE(ah, | ||
346 | AR_PHY_GAIN_2GHZ + regChainOffset, | ||
347 | (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & | ||
348 | ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) | | ||
349 | SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN)); | ||
350 | } | ||
351 | } | ||
352 | |||
353 | static void ath9k_hw_def_set_board_values(struct ath_hw *ah, | ||
354 | struct ath9k_channel *chan) | ||
355 | { | ||
356 | struct modal_eep_header *pModal; | ||
357 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; | ||
358 | int i, regChainOffset; | ||
359 | u8 txRxAttenLocal; | ||
360 | |||
361 | pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); | ||
362 | txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; | ||
363 | |||
364 | REG_WRITE(ah, AR_PHY_SWITCH_COM, | ||
365 | ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); | ||
366 | |||
367 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
368 | if (AR_SREV_9280(ah)) { | ||
369 | if (i >= 2) | ||
370 | break; | ||
371 | } | ||
372 | |||
373 | if (AR_SREV_5416_20_OR_LATER(ah) && | ||
374 | (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0)) | ||
375 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; | ||
376 | else | ||
377 | regChainOffset = i * 0x1000; | ||
378 | |||
379 | REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, | ||
380 | pModal->antCtrlChain[i]); | ||
381 | |||
382 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, | ||
383 | (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) & | ||
384 | ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | | ||
385 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | | ||
386 | SM(pModal->iqCalICh[i], | ||
387 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | | ||
388 | SM(pModal->iqCalQCh[i], | ||
389 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); | ||
390 | |||
391 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) | ||
392 | ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal, | ||
393 | regChainOffset, i); | ||
394 | } | ||
395 | |||
396 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
397 | if (IS_CHAN_2GHZ(chan)) { | ||
398 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0, | ||
399 | AR_AN_RF2G1_CH0_OB, | ||
400 | AR_AN_RF2G1_CH0_OB_S, | ||
401 | pModal->ob); | ||
402 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0, | ||
403 | AR_AN_RF2G1_CH0_DB, | ||
404 | AR_AN_RF2G1_CH0_DB_S, | ||
405 | pModal->db); | ||
406 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1, | ||
407 | AR_AN_RF2G1_CH1_OB, | ||
408 | AR_AN_RF2G1_CH1_OB_S, | ||
409 | pModal->ob_ch1); | ||
410 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1, | ||
411 | AR_AN_RF2G1_CH1_DB, | ||
412 | AR_AN_RF2G1_CH1_DB_S, | ||
413 | pModal->db_ch1); | ||
414 | } else { | ||
415 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0, | ||
416 | AR_AN_RF5G1_CH0_OB5, | ||
417 | AR_AN_RF5G1_CH0_OB5_S, | ||
418 | pModal->ob); | ||
419 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0, | ||
420 | AR_AN_RF5G1_CH0_DB5, | ||
421 | AR_AN_RF5G1_CH0_DB5_S, | ||
422 | pModal->db); | ||
423 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1, | ||
424 | AR_AN_RF5G1_CH1_OB5, | ||
425 | AR_AN_RF5G1_CH1_OB5_S, | ||
426 | pModal->ob_ch1); | ||
427 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1, | ||
428 | AR_AN_RF5G1_CH1_DB5, | ||
429 | AR_AN_RF5G1_CH1_DB5_S, | ||
430 | pModal->db_ch1); | ||
431 | } | ||
432 | ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2, | ||
433 | AR_AN_TOP2_XPABIAS_LVL, | ||
434 | AR_AN_TOP2_XPABIAS_LVL_S, | ||
435 | pModal->xpaBiasLvl); | ||
436 | ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2, | ||
437 | AR_AN_TOP2_LOCALBIAS, | ||
438 | AR_AN_TOP2_LOCALBIAS_S, | ||
439 | pModal->local_bias); | ||
440 | REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG, | ||
441 | pModal->force_xpaon); | ||
442 | } | ||
443 | |||
444 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, | ||
445 | pModal->switchSettling); | ||
446 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, | ||
447 | pModal->adcDesiredSize); | ||
448 | |||
449 | if (!AR_SREV_9280_10_OR_LATER(ah)) | ||
450 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, | ||
451 | AR_PHY_DESIRED_SZ_PGA, | ||
452 | pModal->pgaDesiredSize); | ||
453 | |||
454 | REG_WRITE(ah, AR_PHY_RF_CTL4, | ||
455 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) | ||
456 | | SM(pModal->txEndToXpaOff, | ||
457 | AR_PHY_RF_CTL4_TX_END_XPAB_OFF) | ||
458 | | SM(pModal->txFrameToXpaOn, | ||
459 | AR_PHY_RF_CTL4_FRAME_XPAA_ON) | ||
460 | | SM(pModal->txFrameToXpaOn, | ||
461 | AR_PHY_RF_CTL4_FRAME_XPAB_ON)); | ||
462 | |||
463 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, | ||
464 | pModal->txEndToRxOn); | ||
465 | |||
466 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
467 | REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, | ||
468 | pModal->thresh62); | ||
469 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, | ||
470 | AR_PHY_EXT_CCA0_THRESH62, | ||
471 | pModal->thresh62); | ||
472 | } else { | ||
473 | REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62, | ||
474 | pModal->thresh62); | ||
475 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, | ||
476 | AR_PHY_EXT_CCA_THRESH62, | ||
477 | pModal->thresh62); | ||
478 | } | ||
479 | |||
480 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) { | ||
481 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, | ||
482 | AR_PHY_TX_END_DATA_START, | ||
483 | pModal->txFrameToDataStart); | ||
484 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON, | ||
485 | pModal->txFrameToPaOn); | ||
486 | } | ||
487 | |||
488 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { | ||
489 | if (IS_CHAN_HT40(chan)) | ||
490 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, | ||
491 | AR_PHY_SETTLING_SWITCH, | ||
492 | pModal->swSettleHt40); | ||
493 | } | ||
494 | |||
495 | if (AR_SREV_9280_20_OR_LATER(ah) && | ||
496 | AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) | ||
497 | REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL, | ||
498 | AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK, | ||
499 | pModal->miscBits); | ||
500 | |||
501 | |||
502 | if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) { | ||
503 | if (IS_CHAN_2GHZ(chan)) | ||
504 | REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, | ||
505 | eep->baseEepHeader.dacLpMode); | ||
506 | else if (eep->baseEepHeader.dacHiPwrMode_5G) | ||
507 | REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0); | ||
508 | else | ||
509 | REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, | ||
510 | eep->baseEepHeader.dacLpMode); | ||
511 | |||
512 | REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, | ||
513 | pModal->miscBits >> 2); | ||
514 | |||
515 | REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9, | ||
516 | AR_PHY_TX_DESIRED_SCALE_CCK, | ||
517 | eep->baseEepHeader.desiredScaleCCK); | ||
518 | } | ||
519 | } | ||
520 | |||
521 | static void ath9k_hw_def_set_addac(struct ath_hw *ah, | ||
522 | struct ath9k_channel *chan) | ||
523 | { | ||
524 | #define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt]) | ||
525 | struct modal_eep_header *pModal; | ||
526 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; | ||
527 | u8 biaslevel; | ||
528 | |||
529 | if (ah->hw_version.macVersion != AR_SREV_VERSION_9160) | ||
530 | return; | ||
531 | |||
532 | if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7) | ||
533 | return; | ||
534 | |||
535 | pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); | ||
536 | |||
537 | if (pModal->xpaBiasLvl != 0xff) { | ||
538 | biaslevel = pModal->xpaBiasLvl; | ||
539 | } else { | ||
540 | u16 resetFreqBin, freqBin, freqCount = 0; | ||
541 | struct chan_centers centers; | ||
542 | |||
543 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
544 | |||
545 | resetFreqBin = FREQ2FBIN(centers.synth_center, | ||
546 | IS_CHAN_2GHZ(chan)); | ||
547 | freqBin = XPA_LVL_FREQ(0) & 0xff; | ||
548 | biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14); | ||
549 | |||
550 | freqCount++; | ||
551 | |||
552 | while (freqCount < 3) { | ||
553 | if (XPA_LVL_FREQ(freqCount) == 0x0) | ||
554 | break; | ||
555 | |||
556 | freqBin = XPA_LVL_FREQ(freqCount) & 0xff; | ||
557 | if (resetFreqBin >= freqBin) | ||
558 | biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14); | ||
559 | else | ||
560 | break; | ||
561 | freqCount++; | ||
562 | } | ||
563 | } | ||
564 | |||
565 | if (IS_CHAN_2GHZ(chan)) { | ||
566 | INI_RA(&ah->iniAddac, 7, 1) = (INI_RA(&ah->iniAddac, | ||
567 | 7, 1) & (~0x18)) | biaslevel << 3; | ||
568 | } else { | ||
569 | INI_RA(&ah->iniAddac, 6, 1) = (INI_RA(&ah->iniAddac, | ||
570 | 6, 1) & (~0xc0)) | biaslevel << 6; | ||
571 | } | ||
572 | #undef XPA_LVL_FREQ | ||
573 | } | ||
574 | |||
575 | static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, | ||
576 | struct ath9k_channel *chan, | ||
577 | struct cal_data_per_freq *pRawDataSet, | ||
578 | u8 *bChans, u16 availPiers, | ||
579 | u16 tPdGainOverlap, int16_t *pMinCalPower, | ||
580 | u16 *pPdGainBoundaries, u8 *pPDADCValues, | ||
581 | u16 numXpdGains) | ||
582 | { | ||
583 | int i, j, k; | ||
584 | int16_t ss; | ||
585 | u16 idxL = 0, idxR = 0, numPiers; | ||
586 | static u8 vpdTableL[AR5416_NUM_PD_GAINS] | ||
587 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
588 | static u8 vpdTableR[AR5416_NUM_PD_GAINS] | ||
589 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
590 | static u8 vpdTableI[AR5416_NUM_PD_GAINS] | ||
591 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
592 | |||
593 | u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; | ||
594 | u8 minPwrT4[AR5416_NUM_PD_GAINS]; | ||
595 | u8 maxPwrT4[AR5416_NUM_PD_GAINS]; | ||
596 | int16_t vpdStep; | ||
597 | int16_t tmpVal; | ||
598 | u16 sizeCurrVpdTable, maxIndex, tgtIndex; | ||
599 | bool match; | ||
600 | int16_t minDelta = 0; | ||
601 | struct chan_centers centers; | ||
602 | |||
603 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
604 | |||
605 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | ||
606 | if (bChans[numPiers] == AR5416_BCHAN_UNUSED) | ||
607 | break; | ||
608 | } | ||
609 | |||
610 | match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center, | ||
611 | IS_CHAN_2GHZ(chan)), | ||
612 | bChans, numPiers, &idxL, &idxR); | ||
613 | |||
614 | if (match) { | ||
615 | for (i = 0; i < numXpdGains; i++) { | ||
616 | minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; | ||
617 | maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; | ||
618 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
619 | pRawDataSet[idxL].pwrPdg[i], | ||
620 | pRawDataSet[idxL].vpdPdg[i], | ||
621 | AR5416_PD_GAIN_ICEPTS, | ||
622 | vpdTableI[i]); | ||
623 | } | ||
624 | } else { | ||
625 | for (i = 0; i < numXpdGains; i++) { | ||
626 | pVpdL = pRawDataSet[idxL].vpdPdg[i]; | ||
627 | pPwrL = pRawDataSet[idxL].pwrPdg[i]; | ||
628 | pVpdR = pRawDataSet[idxR].vpdPdg[i]; | ||
629 | pPwrR = pRawDataSet[idxR].pwrPdg[i]; | ||
630 | |||
631 | minPwrT4[i] = max(pPwrL[0], pPwrR[0]); | ||
632 | |||
633 | maxPwrT4[i] = | ||
634 | min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1], | ||
635 | pPwrR[AR5416_PD_GAIN_ICEPTS - 1]); | ||
636 | |||
637 | |||
638 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
639 | pPwrL, pVpdL, | ||
640 | AR5416_PD_GAIN_ICEPTS, | ||
641 | vpdTableL[i]); | ||
642 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
643 | pPwrR, pVpdR, | ||
644 | AR5416_PD_GAIN_ICEPTS, | ||
645 | vpdTableR[i]); | ||
646 | |||
647 | for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { | ||
648 | vpdTableI[i][j] = | ||
649 | (u8)(ath9k_hw_interpolate((u16) | ||
650 | FREQ2FBIN(centers. | ||
651 | synth_center, | ||
652 | IS_CHAN_2GHZ | ||
653 | (chan)), | ||
654 | bChans[idxL], bChans[idxR], | ||
655 | vpdTableL[i][j], vpdTableR[i][j])); | ||
656 | } | ||
657 | } | ||
658 | } | ||
659 | |||
660 | *pMinCalPower = (int16_t)(minPwrT4[0] / 2); | ||
661 | |||
662 | k = 0; | ||
663 | |||
664 | for (i = 0; i < numXpdGains; i++) { | ||
665 | if (i == (numXpdGains - 1)) | ||
666 | pPdGainBoundaries[i] = | ||
667 | (u16)(maxPwrT4[i] / 2); | ||
668 | else | ||
669 | pPdGainBoundaries[i] = | ||
670 | (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4); | ||
671 | |||
672 | pPdGainBoundaries[i] = | ||
673 | min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); | ||
674 | |||
675 | if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { | ||
676 | minDelta = pPdGainBoundaries[0] - 23; | ||
677 | pPdGainBoundaries[0] = 23; | ||
678 | } else { | ||
679 | minDelta = 0; | ||
680 | } | ||
681 | |||
682 | if (i == 0) { | ||
683 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
684 | ss = (int16_t)(0 - (minPwrT4[i] / 2)); | ||
685 | else | ||
686 | ss = 0; | ||
687 | } else { | ||
688 | ss = (int16_t)((pPdGainBoundaries[i - 1] - | ||
689 | (minPwrT4[i] / 2)) - | ||
690 | tPdGainOverlap + 1 + minDelta); | ||
691 | } | ||
692 | vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); | ||
693 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
694 | |||
695 | while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
696 | tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); | ||
697 | pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); | ||
698 | ss++; | ||
699 | } | ||
700 | |||
701 | sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); | ||
702 | tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap - | ||
703 | (minPwrT4[i] / 2)); | ||
704 | maxIndex = (tgtIndex < sizeCurrVpdTable) ? | ||
705 | tgtIndex : sizeCurrVpdTable; | ||
706 | |||
707 | while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
708 | pPDADCValues[k++] = vpdTableI[i][ss++]; | ||
709 | } | ||
710 | |||
711 | vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - | ||
712 | vpdTableI[i][sizeCurrVpdTable - 2]); | ||
713 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
714 | |||
715 | if (tgtIndex > maxIndex) { | ||
716 | while ((ss <= tgtIndex) && | ||
717 | (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
718 | tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] + | ||
719 | (ss - maxIndex + 1) * vpdStep)); | ||
720 | pPDADCValues[k++] = (u8)((tmpVal > 255) ? | ||
721 | 255 : tmpVal); | ||
722 | ss++; | ||
723 | } | ||
724 | } | ||
725 | } | ||
726 | |||
727 | while (i < AR5416_PD_GAINS_IN_MASK) { | ||
728 | pPdGainBoundaries[i] = pPdGainBoundaries[i - 1]; | ||
729 | i++; | ||
730 | } | ||
731 | |||
732 | while (k < AR5416_NUM_PDADC_VALUES) { | ||
733 | pPDADCValues[k] = pPDADCValues[k - 1]; | ||
734 | k++; | ||
735 | } | ||
736 | |||
737 | return; | ||
738 | } | ||
739 | |||
740 | static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | ||
741 | struct ath9k_channel *chan, | ||
742 | int16_t *pTxPowerIndexOffset) | ||
743 | { | ||
744 | #define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x) | ||
745 | #define SM_PDGAIN_B(x, y) \ | ||
746 | SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y) | ||
747 | |||
748 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; | ||
749 | struct cal_data_per_freq *pRawDataset; | ||
750 | u8 *pCalBChans = NULL; | ||
751 | u16 pdGainOverlap_t2; | ||
752 | static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; | ||
753 | u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; | ||
754 | u16 numPiers, i, j; | ||
755 | int16_t tMinCalPower; | ||
756 | u16 numXpdGain, xpdMask; | ||
757 | u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 }; | ||
758 | u32 reg32, regOffset, regChainOffset; | ||
759 | int16_t modalIdx; | ||
760 | |||
761 | modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; | ||
762 | xpdMask = pEepData->modalHeader[modalIdx].xpdGain; | ||
763 | |||
764 | if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
765 | AR5416_EEP_MINOR_VER_2) { | ||
766 | pdGainOverlap_t2 = | ||
767 | pEepData->modalHeader[modalIdx].pdGainOverlap; | ||
768 | } else { | ||
769 | pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), | ||
770 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); | ||
771 | } | ||
772 | |||
773 | if (IS_CHAN_2GHZ(chan)) { | ||
774 | pCalBChans = pEepData->calFreqPier2G; | ||
775 | numPiers = AR5416_NUM_2G_CAL_PIERS; | ||
776 | } else { | ||
777 | pCalBChans = pEepData->calFreqPier5G; | ||
778 | numPiers = AR5416_NUM_5G_CAL_PIERS; | ||
779 | } | ||
780 | |||
781 | if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) { | ||
782 | pRawDataset = pEepData->calPierData2G[0]; | ||
783 | ah->initPDADC = ((struct calDataPerFreqOpLoop *) | ||
784 | pRawDataset)->vpdPdg[0][0]; | ||
785 | } | ||
786 | |||
787 | numXpdGain = 0; | ||
788 | |||
789 | for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { | ||
790 | if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { | ||
791 | if (numXpdGain >= AR5416_NUM_PD_GAINS) | ||
792 | break; | ||
793 | xpdGainValues[numXpdGain] = | ||
794 | (u16)(AR5416_PD_GAINS_IN_MASK - i); | ||
795 | numXpdGain++; | ||
796 | } | ||
797 | } | ||
798 | |||
799 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, | ||
800 | (numXpdGain - 1) & 0x3); | ||
801 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, | ||
802 | xpdGainValues[0]); | ||
803 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, | ||
804 | xpdGainValues[1]); | ||
805 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, | ||
806 | xpdGainValues[2]); | ||
807 | |||
808 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
809 | if (AR_SREV_5416_20_OR_LATER(ah) && | ||
810 | (ah->rxchainmask == 5 || ah->txchainmask == 5) && | ||
811 | (i != 0)) { | ||
812 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; | ||
813 | } else | ||
814 | regChainOffset = i * 0x1000; | ||
815 | |||
816 | if (pEepData->baseEepHeader.txMask & (1 << i)) { | ||
817 | if (IS_CHAN_2GHZ(chan)) | ||
818 | pRawDataset = pEepData->calPierData2G[i]; | ||
819 | else | ||
820 | pRawDataset = pEepData->calPierData5G[i]; | ||
821 | |||
822 | |||
823 | if (OLC_FOR_AR9280_20_LATER) { | ||
824 | u8 pcdacIdx; | ||
825 | u8 txPower; | ||
826 | |||
827 | ath9k_get_txgain_index(ah, chan, | ||
828 | (struct calDataPerFreqOpLoop *)pRawDataset, | ||
829 | pCalBChans, numPiers, &txPower, &pcdacIdx); | ||
830 | ath9k_olc_get_pdadcs(ah, pcdacIdx, | ||
831 | txPower/2, pdadcValues); | ||
832 | } else { | ||
833 | ath9k_hw_get_def_gain_boundaries_pdadcs(ah, | ||
834 | chan, pRawDataset, | ||
835 | pCalBChans, numPiers, | ||
836 | pdGainOverlap_t2, | ||
837 | &tMinCalPower, | ||
838 | gainBoundaries, | ||
839 | pdadcValues, | ||
840 | numXpdGain); | ||
841 | } | ||
842 | |||
843 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { | ||
844 | if (OLC_FOR_AR9280_20_LATER) { | ||
845 | REG_WRITE(ah, | ||
846 | AR_PHY_TPCRG5 + regChainOffset, | ||
847 | SM(0x6, | ||
848 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | | ||
849 | SM_PD_GAIN(1) | SM_PD_GAIN(2) | | ||
850 | SM_PD_GAIN(3) | SM_PD_GAIN(4)); | ||
851 | } else { | ||
852 | REG_WRITE(ah, | ||
853 | AR_PHY_TPCRG5 + regChainOffset, | ||
854 | SM(pdGainOverlap_t2, | ||
855 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP)| | ||
856 | SM_PDGAIN_B(0, 1) | | ||
857 | SM_PDGAIN_B(1, 2) | | ||
858 | SM_PDGAIN_B(2, 3) | | ||
859 | SM_PDGAIN_B(3, 4)); | ||
860 | } | ||
861 | } | ||
862 | |||
863 | regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; | ||
864 | for (j = 0; j < 32; j++) { | ||
865 | reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) | | ||
866 | ((pdadcValues[4 * j + 1] & 0xFF) << 8) | | ||
867 | ((pdadcValues[4 * j + 2] & 0xFF) << 16)| | ||
868 | ((pdadcValues[4 * j + 3] & 0xFF) << 24); | ||
869 | REG_WRITE(ah, regOffset, reg32); | ||
870 | |||
871 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
872 | "PDADC (%d,%4x): %4.4x %8.8x\n", | ||
873 | i, regChainOffset, regOffset, | ||
874 | reg32); | ||
875 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
876 | "PDADC: Chain %d | PDADC %3d " | ||
877 | "Value %3d | PDADC %3d Value %3d | " | ||
878 | "PDADC %3d Value %3d | PDADC %3d " | ||
879 | "Value %3d |\n", | ||
880 | i, 4 * j, pdadcValues[4 * j], | ||
881 | 4 * j + 1, pdadcValues[4 * j + 1], | ||
882 | 4 * j + 2, pdadcValues[4 * j + 2], | ||
883 | 4 * j + 3, | ||
884 | pdadcValues[4 * j + 3]); | ||
885 | |||
886 | regOffset += 4; | ||
887 | } | ||
888 | } | ||
889 | } | ||
890 | |||
891 | *pTxPowerIndexOffset = 0; | ||
892 | #undef SM_PD_GAIN | ||
893 | #undef SM_PDGAIN_B | ||
894 | } | ||
895 | |||
896 | static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, | ||
897 | struct ath9k_channel *chan, | ||
898 | int16_t *ratesArray, | ||
899 | u16 cfgCtl, | ||
900 | u16 AntennaReduction, | ||
901 | u16 twiceMaxRegulatoryPower, | ||
902 | u16 powerLimit) | ||
903 | { | ||
904 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ | ||
905 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */ | ||
906 | |||
907 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; | ||
908 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
909 | static const u16 tpScaleReductionTable[5] = | ||
910 | { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; | ||
911 | |||
912 | int i; | ||
913 | int16_t twiceLargestAntenna; | ||
914 | struct cal_ctl_data *rep; | ||
915 | struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { | ||
916 | 0, { 0, 0, 0, 0} | ||
917 | }; | ||
918 | struct cal_target_power_leg targetPowerOfdmExt = { | ||
919 | 0, { 0, 0, 0, 0} }, targetPowerCckExt = { | ||
920 | 0, { 0, 0, 0, 0 } | ||
921 | }; | ||
922 | struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { | ||
923 | 0, {0, 0, 0, 0} | ||
924 | }; | ||
925 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; | ||
926 | u16 ctlModesFor11a[] = | ||
927 | { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 }; | ||
928 | u16 ctlModesFor11g[] = | ||
929 | { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, | ||
930 | CTL_2GHT40 | ||
931 | }; | ||
932 | u16 numCtlModes, *pCtlMode, ctlMode, freq; | ||
933 | struct chan_centers centers; | ||
934 | int tx_chainmask; | ||
935 | u16 twiceMinEdgePower; | ||
936 | |||
937 | tx_chainmask = ah->txchainmask; | ||
938 | |||
939 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
940 | |||
941 | twiceLargestAntenna = max( | ||
942 | pEepData->modalHeader | ||
943 | [IS_CHAN_2GHZ(chan)].antennaGainCh[0], | ||
944 | pEepData->modalHeader | ||
945 | [IS_CHAN_2GHZ(chan)].antennaGainCh[1]); | ||
946 | |||
947 | twiceLargestAntenna = max((u8)twiceLargestAntenna, | ||
948 | pEepData->modalHeader | ||
949 | [IS_CHAN_2GHZ(chan)].antennaGainCh[2]); | ||
950 | |||
951 | twiceLargestAntenna = (int16_t)min(AntennaReduction - | ||
952 | twiceLargestAntenna, 0); | ||
953 | |||
954 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; | ||
955 | |||
956 | if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) { | ||
957 | maxRegAllowedPower -= | ||
958 | (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); | ||
959 | } | ||
960 | |||
961 | scaledPower = min(powerLimit, maxRegAllowedPower); | ||
962 | |||
963 | switch (ar5416_get_ntxchains(tx_chainmask)) { | ||
964 | case 1: | ||
965 | break; | ||
966 | case 2: | ||
967 | scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; | ||
968 | break; | ||
969 | case 3: | ||
970 | scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; | ||
971 | break; | ||
972 | } | ||
973 | |||
974 | scaledPower = max((u16)0, scaledPower); | ||
975 | |||
976 | if (IS_CHAN_2GHZ(chan)) { | ||
977 | numCtlModes = ARRAY_SIZE(ctlModesFor11g) - | ||
978 | SUB_NUM_CTL_MODES_AT_2G_40; | ||
979 | pCtlMode = ctlModesFor11g; | ||
980 | |||
981 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
982 | pEepData->calTargetPowerCck, | ||
983 | AR5416_NUM_2G_CCK_TARGET_POWERS, | ||
984 | &targetPowerCck, 4, false); | ||
985 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
986 | pEepData->calTargetPower2G, | ||
987 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
988 | &targetPowerOfdm, 4, false); | ||
989 | ath9k_hw_get_target_powers(ah, chan, | ||
990 | pEepData->calTargetPower2GHT20, | ||
991 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
992 | &targetPowerHt20, 8, false); | ||
993 | |||
994 | if (IS_CHAN_HT40(chan)) { | ||
995 | numCtlModes = ARRAY_SIZE(ctlModesFor11g); | ||
996 | ath9k_hw_get_target_powers(ah, chan, | ||
997 | pEepData->calTargetPower2GHT40, | ||
998 | AR5416_NUM_2G_40_TARGET_POWERS, | ||
999 | &targetPowerHt40, 8, true); | ||
1000 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
1001 | pEepData->calTargetPowerCck, | ||
1002 | AR5416_NUM_2G_CCK_TARGET_POWERS, | ||
1003 | &targetPowerCckExt, 4, true); | ||
1004 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
1005 | pEepData->calTargetPower2G, | ||
1006 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
1007 | &targetPowerOfdmExt, 4, true); | ||
1008 | } | ||
1009 | } else { | ||
1010 | numCtlModes = ARRAY_SIZE(ctlModesFor11a) - | ||
1011 | SUB_NUM_CTL_MODES_AT_5G_40; | ||
1012 | pCtlMode = ctlModesFor11a; | ||
1013 | |||
1014 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
1015 | pEepData->calTargetPower5G, | ||
1016 | AR5416_NUM_5G_20_TARGET_POWERS, | ||
1017 | &targetPowerOfdm, 4, false); | ||
1018 | ath9k_hw_get_target_powers(ah, chan, | ||
1019 | pEepData->calTargetPower5GHT20, | ||
1020 | AR5416_NUM_5G_20_TARGET_POWERS, | ||
1021 | &targetPowerHt20, 8, false); | ||
1022 | |||
1023 | if (IS_CHAN_HT40(chan)) { | ||
1024 | numCtlModes = ARRAY_SIZE(ctlModesFor11a); | ||
1025 | ath9k_hw_get_target_powers(ah, chan, | ||
1026 | pEepData->calTargetPower5GHT40, | ||
1027 | AR5416_NUM_5G_40_TARGET_POWERS, | ||
1028 | &targetPowerHt40, 8, true); | ||
1029 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
1030 | pEepData->calTargetPower5G, | ||
1031 | AR5416_NUM_5G_20_TARGET_POWERS, | ||
1032 | &targetPowerOfdmExt, 4, true); | ||
1033 | } | ||
1034 | } | ||
1035 | |||
1036 | for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { | ||
1037 | bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || | ||
1038 | (pCtlMode[ctlMode] == CTL_2GHT40); | ||
1039 | if (isHt40CtlMode) | ||
1040 | freq = centers.synth_center; | ||
1041 | else if (pCtlMode[ctlMode] & EXT_ADDITIVE) | ||
1042 | freq = centers.ext_center; | ||
1043 | else | ||
1044 | freq = centers.ctl_center; | ||
1045 | |||
1046 | if (ah->eep_ops->get_eeprom_ver(ah) == 14 && | ||
1047 | ah->eep_ops->get_eeprom_rev(ah) <= 2) | ||
1048 | twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
1049 | |||
1050 | for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { | ||
1051 | if ((((cfgCtl & ~CTL_MODE_M) | | ||
1052 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
1053 | pEepData->ctlIndex[i]) || | ||
1054 | (((cfgCtl & ~CTL_MODE_M) | | ||
1055 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
1056 | ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) { | ||
1057 | rep = &(pEepData->ctlData[i]); | ||
1058 | |||
1059 | twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq, | ||
1060 | rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1], | ||
1061 | IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES); | ||
1062 | |||
1063 | if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { | ||
1064 | twiceMaxEdgePower = min(twiceMaxEdgePower, | ||
1065 | twiceMinEdgePower); | ||
1066 | } else { | ||
1067 | twiceMaxEdgePower = twiceMinEdgePower; | ||
1068 | break; | ||
1069 | } | ||
1070 | } | ||
1071 | } | ||
1072 | |||
1073 | minCtlPower = min(twiceMaxEdgePower, scaledPower); | ||
1074 | |||
1075 | switch (pCtlMode[ctlMode]) { | ||
1076 | case CTL_11B: | ||
1077 | for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) { | ||
1078 | targetPowerCck.tPow2x[i] = | ||
1079 | min((u16)targetPowerCck.tPow2x[i], | ||
1080 | minCtlPower); | ||
1081 | } | ||
1082 | break; | ||
1083 | case CTL_11A: | ||
1084 | case CTL_11G: | ||
1085 | for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) { | ||
1086 | targetPowerOfdm.tPow2x[i] = | ||
1087 | min((u16)targetPowerOfdm.tPow2x[i], | ||
1088 | minCtlPower); | ||
1089 | } | ||
1090 | break; | ||
1091 | case CTL_5GHT20: | ||
1092 | case CTL_2GHT20: | ||
1093 | for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) { | ||
1094 | targetPowerHt20.tPow2x[i] = | ||
1095 | min((u16)targetPowerHt20.tPow2x[i], | ||
1096 | minCtlPower); | ||
1097 | } | ||
1098 | break; | ||
1099 | case CTL_11B_EXT: | ||
1100 | targetPowerCckExt.tPow2x[0] = min((u16) | ||
1101 | targetPowerCckExt.tPow2x[0], | ||
1102 | minCtlPower); | ||
1103 | break; | ||
1104 | case CTL_11A_EXT: | ||
1105 | case CTL_11G_EXT: | ||
1106 | targetPowerOfdmExt.tPow2x[0] = min((u16) | ||
1107 | targetPowerOfdmExt.tPow2x[0], | ||
1108 | minCtlPower); | ||
1109 | break; | ||
1110 | case CTL_5GHT40: | ||
1111 | case CTL_2GHT40: | ||
1112 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { | ||
1113 | targetPowerHt40.tPow2x[i] = | ||
1114 | min((u16)targetPowerHt40.tPow2x[i], | ||
1115 | minCtlPower); | ||
1116 | } | ||
1117 | break; | ||
1118 | default: | ||
1119 | break; | ||
1120 | } | ||
1121 | } | ||
1122 | |||
1123 | ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = | ||
1124 | ratesArray[rate18mb] = ratesArray[rate24mb] = | ||
1125 | targetPowerOfdm.tPow2x[0]; | ||
1126 | ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; | ||
1127 | ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; | ||
1128 | ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; | ||
1129 | ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; | ||
1130 | |||
1131 | for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) | ||
1132 | ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; | ||
1133 | |||
1134 | if (IS_CHAN_2GHZ(chan)) { | ||
1135 | ratesArray[rate1l] = targetPowerCck.tPow2x[0]; | ||
1136 | ratesArray[rate2s] = ratesArray[rate2l] = | ||
1137 | targetPowerCck.tPow2x[1]; | ||
1138 | ratesArray[rate5_5s] = ratesArray[rate5_5l] = | ||
1139 | targetPowerCck.tPow2x[2]; | ||
1140 | ratesArray[rate11s] = ratesArray[rate11l] = | ||
1141 | targetPowerCck.tPow2x[3]; | ||
1142 | } | ||
1143 | if (IS_CHAN_HT40(chan)) { | ||
1144 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { | ||
1145 | ratesArray[rateHt40_0 + i] = | ||
1146 | targetPowerHt40.tPow2x[i]; | ||
1147 | } | ||
1148 | ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; | ||
1149 | ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; | ||
1150 | ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; | ||
1151 | if (IS_CHAN_2GHZ(chan)) { | ||
1152 | ratesArray[rateExtCck] = | ||
1153 | targetPowerCckExt.tPow2x[0]; | ||
1154 | } | ||
1155 | } | ||
1156 | } | ||
1157 | |||
1158 | static void ath9k_hw_def_set_txpower(struct ath_hw *ah, | ||
1159 | struct ath9k_channel *chan, | ||
1160 | u16 cfgCtl, | ||
1161 | u8 twiceAntennaReduction, | ||
1162 | u8 twiceMaxRegulatoryPower, | ||
1163 | u8 powerLimit) | ||
1164 | { | ||
1165 | #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) | ||
1166 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; | ||
1167 | struct modal_eep_header *pModal = | ||
1168 | &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]); | ||
1169 | int16_t ratesArray[Ar5416RateSize]; | ||
1170 | int16_t txPowerIndexOffset = 0; | ||
1171 | u8 ht40PowerIncForPdadc = 2; | ||
1172 | int i, cck_ofdm_delta = 0; | ||
1173 | |||
1174 | memset(ratesArray, 0, sizeof(ratesArray)); | ||
1175 | |||
1176 | if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
1177 | AR5416_EEP_MINOR_VER_2) { | ||
1178 | ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; | ||
1179 | } | ||
1180 | |||
1181 | ath9k_hw_set_def_power_per_rate_table(ah, chan, | ||
1182 | &ratesArray[0], cfgCtl, | ||
1183 | twiceAntennaReduction, | ||
1184 | twiceMaxRegulatoryPower, | ||
1185 | powerLimit); | ||
1186 | |||
1187 | ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset); | ||
1188 | |||
1189 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { | ||
1190 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); | ||
1191 | if (ratesArray[i] > AR5416_MAX_RATE_POWER) | ||
1192 | ratesArray[i] = AR5416_MAX_RATE_POWER; | ||
1193 | } | ||
1194 | |||
1195 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
1196 | for (i = 0; i < Ar5416RateSize; i++) | ||
1197 | ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2; | ||
1198 | } | ||
1199 | |||
1200 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, | ||
1201 | ATH9K_POW_SM(ratesArray[rate18mb], 24) | ||
1202 | | ATH9K_POW_SM(ratesArray[rate12mb], 16) | ||
1203 | | ATH9K_POW_SM(ratesArray[rate9mb], 8) | ||
1204 | | ATH9K_POW_SM(ratesArray[rate6mb], 0)); | ||
1205 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, | ||
1206 | ATH9K_POW_SM(ratesArray[rate54mb], 24) | ||
1207 | | ATH9K_POW_SM(ratesArray[rate48mb], 16) | ||
1208 | | ATH9K_POW_SM(ratesArray[rate36mb], 8) | ||
1209 | | ATH9K_POW_SM(ratesArray[rate24mb], 0)); | ||
1210 | |||
1211 | if (IS_CHAN_2GHZ(chan)) { | ||
1212 | if (OLC_FOR_AR9280_20_LATER) { | ||
1213 | cck_ofdm_delta = 2; | ||
1214 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, | ||
1215 | ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24) | ||
1216 | | ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16) | ||
1217 | | ATH9K_POW_SM(ratesArray[rateXr], 8) | ||
1218 | | ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0)); | ||
1219 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, | ||
1220 | ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24) | ||
1221 | | ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16) | ||
1222 | | ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8) | ||
1223 | | ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0)); | ||
1224 | } else { | ||
1225 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, | ||
1226 | ATH9K_POW_SM(ratesArray[rate2s], 24) | ||
1227 | | ATH9K_POW_SM(ratesArray[rate2l], 16) | ||
1228 | | ATH9K_POW_SM(ratesArray[rateXr], 8) | ||
1229 | | ATH9K_POW_SM(ratesArray[rate1l], 0)); | ||
1230 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, | ||
1231 | ATH9K_POW_SM(ratesArray[rate11s], 24) | ||
1232 | | ATH9K_POW_SM(ratesArray[rate11l], 16) | ||
1233 | | ATH9K_POW_SM(ratesArray[rate5_5s], 8) | ||
1234 | | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); | ||
1235 | } | ||
1236 | } | ||
1237 | |||
1238 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, | ||
1239 | ATH9K_POW_SM(ratesArray[rateHt20_3], 24) | ||
1240 | | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) | ||
1241 | | ATH9K_POW_SM(ratesArray[rateHt20_1], 8) | ||
1242 | | ATH9K_POW_SM(ratesArray[rateHt20_0], 0)); | ||
1243 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, | ||
1244 | ATH9K_POW_SM(ratesArray[rateHt20_7], 24) | ||
1245 | | ATH9K_POW_SM(ratesArray[rateHt20_6], 16) | ||
1246 | | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) | ||
1247 | | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); | ||
1248 | |||
1249 | if (IS_CHAN_HT40(chan)) { | ||
1250 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, | ||
1251 | ATH9K_POW_SM(ratesArray[rateHt40_3] + | ||
1252 | ht40PowerIncForPdadc, 24) | ||
1253 | | ATH9K_POW_SM(ratesArray[rateHt40_2] + | ||
1254 | ht40PowerIncForPdadc, 16) | ||
1255 | | ATH9K_POW_SM(ratesArray[rateHt40_1] + | ||
1256 | ht40PowerIncForPdadc, 8) | ||
1257 | | ATH9K_POW_SM(ratesArray[rateHt40_0] + | ||
1258 | ht40PowerIncForPdadc, 0)); | ||
1259 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, | ||
1260 | ATH9K_POW_SM(ratesArray[rateHt40_7] + | ||
1261 | ht40PowerIncForPdadc, 24) | ||
1262 | | ATH9K_POW_SM(ratesArray[rateHt40_6] + | ||
1263 | ht40PowerIncForPdadc, 16) | ||
1264 | | ATH9K_POW_SM(ratesArray[rateHt40_5] + | ||
1265 | ht40PowerIncForPdadc, 8) | ||
1266 | | ATH9K_POW_SM(ratesArray[rateHt40_4] + | ||
1267 | ht40PowerIncForPdadc, 0)); | ||
1268 | if (OLC_FOR_AR9280_20_LATER) { | ||
1269 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, | ||
1270 | ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) | ||
1271 | | ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16) | ||
1272 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | ||
1273 | | ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0)); | ||
1274 | } else { | ||
1275 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, | ||
1276 | ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) | ||
1277 | | ATH9K_POW_SM(ratesArray[rateExtCck], 16) | ||
1278 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | ||
1279 | | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); | ||
1280 | } | ||
1281 | } | ||
1282 | |||
1283 | REG_WRITE(ah, AR_PHY_POWER_TX_SUB, | ||
1284 | ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) | ||
1285 | | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)); | ||
1286 | |||
1287 | i = rate6mb; | ||
1288 | |||
1289 | if (IS_CHAN_HT40(chan)) | ||
1290 | i = rateHt40_0; | ||
1291 | else if (IS_CHAN_HT20(chan)) | ||
1292 | i = rateHt20_0; | ||
1293 | |||
1294 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
1295 | ah->regulatory.max_power_level = | ||
1296 | ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2; | ||
1297 | else | ||
1298 | ah->regulatory.max_power_level = ratesArray[i]; | ||
1299 | |||
1300 | switch(ar5416_get_ntxchains(ah->txchainmask)) { | ||
1301 | case 1: | ||
1302 | break; | ||
1303 | case 2: | ||
1304 | ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; | ||
1305 | break; | ||
1306 | case 3: | ||
1307 | ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; | ||
1308 | break; | ||
1309 | default: | ||
1310 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
1311 | "Invalid chainmask configuration\n"); | ||
1312 | break; | ||
1313 | } | ||
1314 | } | ||
1315 | |||
1316 | static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah, | ||
1317 | enum ieee80211_band freq_band) | ||
1318 | { | ||
1319 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; | ||
1320 | struct modal_eep_header *pModal = | ||
1321 | &(eep->modalHeader[ATH9K_HAL_FREQ_BAND_2GHZ == freq_band]); | ||
1322 | struct base_eep_header *pBase = &eep->baseEepHeader; | ||
1323 | u8 num_ant_config; | ||
1324 | |||
1325 | num_ant_config = 1; | ||
1326 | |||
1327 | if (pBase->version >= 0x0E0D) | ||
1328 | if (pModal->useAnt1) | ||
1329 | num_ant_config += 1; | ||
1330 | |||
1331 | return num_ant_config; | ||
1332 | } | ||
1333 | |||
1334 | static u16 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah, | ||
1335 | struct ath9k_channel *chan) | ||
1336 | { | ||
1337 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; | ||
1338 | struct modal_eep_header *pModal = | ||
1339 | &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); | ||
1340 | |||
1341 | return pModal->antCtrlCommon & 0xFFFF; | ||
1342 | } | ||
1343 | |||
1344 | static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) | ||
1345 | { | ||
1346 | #define EEP_DEF_SPURCHAN \ | ||
1347 | (ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan) | ||
1348 | |||
1349 | u16 spur_val = AR_NO_SPUR; | ||
1350 | |||
1351 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
1352 | "Getting spur idx %d is2Ghz. %d val %x\n", | ||
1353 | i, is2GHz, ah->config.spurchans[i][is2GHz]); | ||
1354 | |||
1355 | switch (ah->config.spurmode) { | ||
1356 | case SPUR_DISABLE: | ||
1357 | break; | ||
1358 | case SPUR_ENABLE_IOCTL: | ||
1359 | spur_val = ah->config.spurchans[i][is2GHz]; | ||
1360 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
1361 | "Getting spur val from new loc. %d\n", spur_val); | ||
1362 | break; | ||
1363 | case SPUR_ENABLE_EEPROM: | ||
1364 | spur_val = EEP_DEF_SPURCHAN; | ||
1365 | break; | ||
1366 | } | ||
1367 | |||
1368 | return spur_val; | ||
1369 | |||
1370 | #undef EEP_DEF_SPURCHAN | ||
1371 | } | ||
1372 | |||
1373 | const struct eeprom_ops eep_def_ops = { | ||
1374 | .check_eeprom = ath9k_hw_def_check_eeprom, | ||
1375 | .get_eeprom = ath9k_hw_def_get_eeprom, | ||
1376 | .fill_eeprom = ath9k_hw_def_fill_eeprom, | ||
1377 | .get_eeprom_ver = ath9k_hw_def_get_eeprom_ver, | ||
1378 | .get_eeprom_rev = ath9k_hw_def_get_eeprom_rev, | ||
1379 | .get_num_ant_config = ath9k_hw_def_get_num_ant_config, | ||
1380 | .get_eeprom_antenna_cfg = ath9k_hw_def_get_eeprom_antenna_cfg, | ||
1381 | .set_board_values = ath9k_hw_def_set_board_values, | ||
1382 | .set_addac = ath9k_hw_def_set_addac, | ||
1383 | .set_txpower = ath9k_hw_def_set_txpower, | ||
1384 | .get_spur_channel = ath9k_hw_def_get_spur_channel | ||
1385 | }; | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 71a3bcc450a2..9f1b34d9861a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -407,7 +407,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah) | |||
407 | ah->config.cck_trig_high = 200; | 407 | ah->config.cck_trig_high = 200; |
408 | ah->config.cck_trig_low = 100; | 408 | ah->config.cck_trig_low = 100; |
409 | ah->config.enable_ani = 1; | 409 | ah->config.enable_ani = 1; |
410 | ah->config.diversity_control = 0; | 410 | ah->config.diversity_control = ATH9K_ANT_VARIABLE; |
411 | ah->config.antenna_switch_swap = 0; | 411 | ah->config.antenna_switch_swap = 0; |
412 | 412 | ||
413 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { | 413 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { |
@@ -452,9 +452,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) | |||
452 | ah->regulatory.power_limit = MAX_RATE_POWER; | 452 | ah->regulatory.power_limit = MAX_RATE_POWER; |
453 | ah->regulatory.tp_scale = ATH9K_TP_SCALE_MAX; | 453 | ah->regulatory.tp_scale = ATH9K_TP_SCALE_MAX; |
454 | ah->atim_window = 0; | 454 | ah->atim_window = 0; |
455 | ah->diversity_control = ah->config.diversity_control; | ||
456 | ah->antenna_switch_swap = | ||
457 | ah->config.antenna_switch_swap; | ||
458 | ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE; | 455 | ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE; |
459 | ah->beacon_interval = 100; | 456 | ah->beacon_interval = 100; |
460 | ah->enable_32kHz_clock = DONT_USE_32KHZ; | 457 | ah->enable_32kHz_clock = DONT_USE_32KHZ; |
@@ -3891,7 +3888,7 @@ bool ath9k_hw_setantennaswitch(struct ath_hw *ah, | |||
3891 | break; | 3888 | break; |
3892 | } | 3889 | } |
3893 | } else { | 3890 | } else { |
3894 | ah->diversity_control = settings; | 3891 | ah->config.diversity_control = settings; |
3895 | } | 3892 | } |
3896 | 3893 | ||
3897 | return true; | 3894 | return true; |
@@ -4019,14 +4016,12 @@ void ath9k_hw_reset_tsf(struct ath_hw *ah) | |||
4019 | ath9k_ps_restore(ah->ah_sc); | 4016 | ath9k_ps_restore(ah->ah_sc); |
4020 | } | 4017 | } |
4021 | 4018 | ||
4022 | bool ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting) | 4019 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting) |
4023 | { | 4020 | { |
4024 | if (setting) | 4021 | if (setting) |
4025 | ah->misc_mode |= AR_PCU_TX_ADD_TSF; | 4022 | ah->misc_mode |= AR_PCU_TX_ADD_TSF; |
4026 | else | 4023 | else |
4027 | ah->misc_mode &= ~AR_PCU_TX_ADD_TSF; | 4024 | ah->misc_mode &= ~AR_PCU_TX_ADD_TSF; |
4028 | |||
4029 | return true; | ||
4030 | } | 4025 | } |
4031 | 4026 | ||
4032 | bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us) | 4027 | bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us) |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index d4aaf4f8db29..0336981a70ec 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -127,6 +127,12 @@ enum wireless_mode { | |||
127 | ATH9K_MODE_MAX, | 127 | ATH9K_MODE_MAX, |
128 | }; | 128 | }; |
129 | 129 | ||
130 | enum ath9k_ant_setting { | ||
131 | ATH9K_ANT_VARIABLE = 0, | ||
132 | ATH9K_ANT_FIXED_A, | ||
133 | ATH9K_ANT_FIXED_B | ||
134 | }; | ||
135 | |||
130 | enum ath9k_hw_caps { | 136 | enum ath9k_hw_caps { |
131 | ATH9K_HW_CAP_MIC_AESCCM = BIT(0), | 137 | ATH9K_HW_CAP_MIC_AESCCM = BIT(0), |
132 | ATH9K_HW_CAP_MIC_CKIP = BIT(1), | 138 | ATH9K_HW_CAP_MIC_CKIP = BIT(1), |
@@ -191,7 +197,7 @@ struct ath9k_ops_config { | |||
191 | u32 cck_trig_high; | 197 | u32 cck_trig_high; |
192 | u32 cck_trig_low; | 198 | u32 cck_trig_low; |
193 | u32 enable_ani; | 199 | u32 enable_ani; |
194 | u16 diversity_control; | 200 | enum ath9k_ant_setting diversity_control; |
195 | u16 antenna_switch_swap; | 201 | u16 antenna_switch_swap; |
196 | int serialize_regmode; | 202 | int serialize_regmode; |
197 | bool intr_mitigation; | 203 | bool intr_mitigation; |
@@ -330,12 +336,6 @@ enum ath9k_power_mode { | |||
330 | ATH9K_PM_UNDEFINED | 336 | ATH9K_PM_UNDEFINED |
331 | }; | 337 | }; |
332 | 338 | ||
333 | enum ath9k_ant_setting { | ||
334 | ATH9K_ANT_VARIABLE = 0, | ||
335 | ATH9K_ANT_FIXED_A, | ||
336 | ATH9K_ANT_FIXED_B | ||
337 | }; | ||
338 | |||
339 | enum ath9k_tp_scale { | 339 | enum ath9k_tp_scale { |
340 | ATH9K_TP_SCALE_MAX = 0, | 340 | ATH9K_TP_SCALE_MAX = 0, |
341 | ATH9K_TP_SCALE_50, | 341 | ATH9K_TP_SCALE_50, |
@@ -437,8 +437,6 @@ struct ath_hw { | |||
437 | u32 txurn_interrupt_mask; | 437 | u32 txurn_interrupt_mask; |
438 | bool chip_fullsleep; | 438 | bool chip_fullsleep; |
439 | u32 atim_window; | 439 | u32 atim_window; |
440 | u16 antenna_switch_swap; | ||
441 | enum ath9k_ant_setting diversity_control; | ||
442 | 440 | ||
443 | /* Calibration */ | 441 | /* Calibration */ |
444 | enum ath9k_cal_types supp_cals; | 442 | enum ath9k_cal_types supp_cals; |
@@ -507,7 +505,6 @@ struct ath_hw { | |||
507 | 505 | ||
508 | /* ANI */ | 506 | /* ANI */ |
509 | u32 proc_phyerr; | 507 | u32 proc_phyerr; |
510 | bool has_hw_phycounters; | ||
511 | u32 aniperiod; | 508 | u32 aniperiod; |
512 | struct ar5416AniState *curani; | 509 | struct ar5416AniState *curani; |
513 | struct ar5416AniState ani[255]; | 510 | struct ar5416AniState ani[255]; |
@@ -601,7 +598,7 @@ void ath9k_hw_write_associd(struct ath_softc *sc); | |||
601 | u64 ath9k_hw_gettsf64(struct ath_hw *ah); | 598 | u64 ath9k_hw_gettsf64(struct ath_hw *ah); |
602 | void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); | 599 | void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); |
603 | void ath9k_hw_reset_tsf(struct ath_hw *ah); | 600 | void ath9k_hw_reset_tsf(struct ath_hw *ah); |
604 | bool ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); | 601 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); |
605 | bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us); | 602 | bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us); |
606 | void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode); | 603 | void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode); |
607 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); | 604 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 6f923e318727..800bfab94635 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -40,20 +40,15 @@ u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) | |||
40 | return REG_READ(ah, AR_QTXDP(q)); | 40 | return REG_READ(ah, AR_QTXDP(q)); |
41 | } | 41 | } |
42 | 42 | ||
43 | bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp) | 43 | void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp) |
44 | { | 44 | { |
45 | REG_WRITE(ah, AR_QTXDP(q), txdp); | 45 | REG_WRITE(ah, AR_QTXDP(q), txdp); |
46 | |||
47 | return true; | ||
48 | } | 46 | } |
49 | 47 | ||
50 | bool ath9k_hw_txstart(struct ath_hw *ah, u32 q) | 48 | void ath9k_hw_txstart(struct ath_hw *ah, u32 q) |
51 | { | 49 | { |
52 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Enable TXE on queue: %u\n", q); | 50 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Enable TXE on queue: %u\n", q); |
53 | |||
54 | REG_WRITE(ah, AR_Q_TXE, 1 << q); | 51 | REG_WRITE(ah, AR_Q_TXE, 1 << q); |
55 | |||
56 | return true; | ||
57 | } | 52 | } |
58 | 53 | ||
59 | u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q) | 54 | u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q) |
@@ -178,7 +173,7 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) | |||
178 | #undef ATH9K_TIME_QUANTUM | 173 | #undef ATH9K_TIME_QUANTUM |
179 | } | 174 | } |
180 | 175 | ||
181 | bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, | 176 | void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, |
182 | u32 segLen, bool firstSeg, | 177 | u32 segLen, bool firstSeg, |
183 | bool lastSeg, const struct ath_desc *ds0) | 178 | bool lastSeg, const struct ath_desc *ds0) |
184 | { | 179 | { |
@@ -202,8 +197,6 @@ bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
202 | ads->ds_txstatus4 = ads->ds_txstatus5 = 0; | 197 | ads->ds_txstatus4 = ads->ds_txstatus5 = 0; |
203 | ads->ds_txstatus6 = ads->ds_txstatus7 = 0; | 198 | ads->ds_txstatus6 = ads->ds_txstatus7 = 0; |
204 | ads->ds_txstatus8 = ads->ds_txstatus9 = 0; | 199 | ads->ds_txstatus8 = ads->ds_txstatus9 = 0; |
205 | |||
206 | return true; | ||
207 | } | 200 | } |
208 | 201 | ||
209 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) | 202 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) |
@@ -888,7 +881,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
888 | return 0; | 881 | return 0; |
889 | } | 882 | } |
890 | 883 | ||
891 | bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, | 884 | void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, |
892 | u32 size, u32 flags) | 885 | u32 size, u32 flags) |
893 | { | 886 | { |
894 | struct ar5416_desc *ads = AR5416DESC(ds); | 887 | struct ar5416_desc *ads = AR5416DESC(ds); |
@@ -901,8 +894,6 @@ bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
901 | ads->ds_rxstatus8 &= ~AR_RxDone; | 894 | ads->ds_rxstatus8 &= ~AR_RxDone; |
902 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) | 895 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) |
903 | memset(&(ads->u), 0, sizeof(ads->u)); | 896 | memset(&(ads->u), 0, sizeof(ads->u)); |
904 | |||
905 | return true; | ||
906 | } | 897 | } |
907 | 898 | ||
908 | bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) | 899 | bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 1176bce8b76c..7b3982295a43 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -628,12 +628,12 @@ struct ath9k_channel; | |||
628 | struct ath_rate_table; | 628 | struct ath_rate_table; |
629 | 629 | ||
630 | u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); | 630 | u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); |
631 | bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); | 631 | void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); |
632 | bool ath9k_hw_txstart(struct ath_hw *ah, u32 q); | 632 | void ath9k_hw_txstart(struct ath_hw *ah, u32 q); |
633 | u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q); | 633 | u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q); |
634 | bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); | 634 | bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); |
635 | bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q); | 635 | bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q); |
636 | bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, | 636 | void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, |
637 | u32 segLen, bool firstSeg, | 637 | u32 segLen, bool firstSeg, |
638 | bool lastSeg, const struct ath_desc *ds0); | 638 | bool lastSeg, const struct ath_desc *ds0); |
639 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds); | 639 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds); |
@@ -668,7 +668,7 @@ bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q); | |||
668 | bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q); | 668 | bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q); |
669 | int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | 669 | int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, |
670 | u32 pa, struct ath_desc *nds, u64 tsf); | 670 | u32 pa, struct ath_desc *nds, u64 tsf); |
671 | bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, | 671 | void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, |
672 | u32 size, u32 flags); | 672 | u32 size, u32 flags); |
673 | bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); | 673 | bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); |
674 | void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); | 674 | void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index a9e43f7a23f6..fa4c6e74f977 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -1327,7 +1327,7 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc) | |||
1327 | */ | 1327 | */ |
1328 | ath_read_cachesize(sc, &csz); | 1328 | ath_read_cachesize(sc, &csz); |
1329 | /* XXX assert csz is non-zero */ | 1329 | /* XXX assert csz is non-zero */ |
1330 | sc->cachelsz = csz << 2; /* convert to bytes */ | 1330 | sc->common.cachelsz = csz << 2; /* convert to bytes */ |
1331 | 1331 | ||
1332 | ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); | 1332 | ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); |
1333 | if (!ah) { | 1333 | if (!ah) { |
@@ -2140,6 +2140,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
2140 | /* disable HAL and put h/w to sleep */ | 2140 | /* disable HAL and put h/w to sleep */ |
2141 | ath9k_hw_disable(sc->sc_ah); | 2141 | ath9k_hw_disable(sc->sc_ah); |
2142 | ath9k_hw_configpcipowersave(sc->sc_ah, 1); | 2142 | ath9k_hw_configpcipowersave(sc->sc_ah, 1); |
2143 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); | ||
2143 | 2144 | ||
2144 | sc->sc_flags |= SC_OP_INVALID; | 2145 | sc->sc_flags |= SC_OP_INVALID; |
2145 | 2146 | ||
@@ -2214,8 +2215,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
2214 | if ((conf->type == NL80211_IFTYPE_STATION) || | 2215 | if ((conf->type == NL80211_IFTYPE_STATION) || |
2215 | (conf->type == NL80211_IFTYPE_ADHOC) || | 2216 | (conf->type == NL80211_IFTYPE_ADHOC) || |
2216 | (conf->type == NL80211_IFTYPE_MESH_POINT)) { | 2217 | (conf->type == NL80211_IFTYPE_MESH_POINT)) { |
2217 | if (ath9k_hw_phycounters(sc->sc_ah)) | 2218 | sc->imask |= ATH9K_INT_MIB; |
2218 | sc->imask |= ATH9K_INT_MIB; | ||
2219 | sc->imask |= ATH9K_INT_TSFOOR; | 2219 | sc->imask |= ATH9K_INT_TSFOOR; |
2220 | } | 2220 | } |
2221 | 2221 | ||
@@ -2380,6 +2380,7 @@ skip_chan_change: | |||
2380 | (FIF_PROMISC_IN_BSS | \ | 2380 | (FIF_PROMISC_IN_BSS | \ |
2381 | FIF_ALLMULTI | \ | 2381 | FIF_ALLMULTI | \ |
2382 | FIF_CONTROL | \ | 2382 | FIF_CONTROL | \ |
2383 | FIF_PSPOLL | \ | ||
2383 | FIF_OTHER_BSS | \ | 2384 | FIF_OTHER_BSS | \ |
2384 | FIF_BCN_PRBRESP_PROMISC | \ | 2385 | FIF_BCN_PRBRESP_PROMISC | \ |
2385 | FIF_FCSFAIL) | 2386 | FIF_FCSFAIL) |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 3546504a83c4..616bdff2b6a1 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -253,10 +253,12 @@ static int ath_pci_resume(struct pci_dev *pdev) | |||
253 | u32 val; | 253 | u32 val; |
254 | int err; | 254 | int err; |
255 | 255 | ||
256 | pci_restore_state(pdev); | ||
257 | |||
256 | err = pci_enable_device(pdev); | 258 | err = pci_enable_device(pdev); |
257 | if (err) | 259 | if (err) |
258 | return err; | 260 | return err; |
259 | pci_restore_state(pdev); | 261 | |
260 | /* | 262 | /* |
261 | * Suspend/Resume resets the PCI configuration space, so we have to | 263 | * Suspend/Resume resets the PCI configuration space, so we have to |
262 | * re-disable the RETRY_TIMEOUT register (0x41) to keep | 264 | * re-disable the RETRY_TIMEOUT register (0x41) to keep |
diff --git a/drivers/net/wireless/ath/ath9k/phy.c b/drivers/net/wireless/ath/ath9k/phy.c index 59bb3ce1e646..63bf9a307c6a 100644 --- a/drivers/net/wireless/ath/ath9k/phy.c +++ b/drivers/net/wireless/ath/ath9k/phy.c | |||
@@ -353,18 +353,16 @@ ath9k_hw_decrease_chain_power(struct ath_hw *ah, struct ath9k_channel *chan) | |||
353 | u32 bank6SelMask; | 353 | u32 bank6SelMask; |
354 | u32 *bank6Temp = ah->bank6Temp; | 354 | u32 *bank6Temp = ah->bank6Temp; |
355 | 355 | ||
356 | switch (ah->diversity_control) { | 356 | switch (ah->config.diversity_control) { |
357 | case ATH9K_ANT_FIXED_A: | 357 | case ATH9K_ANT_FIXED_A: |
358 | bank6SelMask = | 358 | bank6SelMask = |
359 | (ah-> | 359 | (ah->config.antenna_switch_swap & ANTSWAP_AB) ? |
360 | antenna_switch_swap & ANTSWAP_AB) ? REDUCE_CHAIN_0 : | 360 | REDUCE_CHAIN_0 : REDUCE_CHAIN_1; |
361 | REDUCE_CHAIN_1; | ||
362 | break; | 361 | break; |
363 | case ATH9K_ANT_FIXED_B: | 362 | case ATH9K_ANT_FIXED_B: |
364 | bank6SelMask = | 363 | bank6SelMask = |
365 | (ah-> | 364 | (ah->config.antenna_switch_swap & ANTSWAP_AB) ? |
366 | antenna_switch_swap & ANTSWAP_AB) ? REDUCE_CHAIN_1 : | 365 | REDUCE_CHAIN_1 : REDUCE_CHAIN_0; |
367 | REDUCE_CHAIN_0; | ||
368 | break; | 366 | break; |
369 | case ATH9K_ANT_VARIABLE: | 367 | case ATH9K_ANT_VARIABLE: |
370 | return; | 368 | return; |
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index 27bd93c6e74d..e83cd4ab87f0 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h | |||
@@ -312,7 +312,25 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, | |||
312 | #define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12)) | 312 | #define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12)) |
313 | #define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000 | 313 | #define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000 |
314 | #define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 | 314 | #define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 |
315 | #define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac | 315 | |
316 | #define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac | ||
317 | #define AR_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000 | ||
318 | #define AR_PHY_9285_ANT_DIV_CTL 0x01000000 | ||
319 | #define AR_PHY_9285_ANT_DIV_CTL_S 24 | ||
320 | #define AR_PHY_9285_ANT_DIV_ALT_LNACONF 0x06000000 | ||
321 | #define AR_PHY_9285_ANT_DIV_ALT_LNACONF_S 25 | ||
322 | #define AR_PHY_9285_ANT_DIV_MAIN_LNACONF 0x18000000 | ||
323 | #define AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S 27 | ||
324 | #define AR_PHY_9285_ANT_DIV_ALT_GAINTB 0x20000000 | ||
325 | #define AR_PHY_9285_ANT_DIV_ALT_GAINTB_S 29 | ||
326 | #define AR_PHY_9285_ANT_DIV_MAIN_GAINTB 0x40000000 | ||
327 | #define AR_PHY_9285_ANT_DIV_MAIN_GAINTB_S 30 | ||
328 | #define AR_PHY_9285_ANT_DIV_LNA1 2 | ||
329 | #define AR_PHY_9285_ANT_DIV_LNA2 1 | ||
330 | #define AR_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2 3 | ||
331 | #define AR_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0 | ||
332 | #define AR_PHY_9285_ANT_DIV_GAINTB_0 0 | ||
333 | #define AR_PHY_9285_ANT_DIV_GAINTB_1 1 | ||
316 | 334 | ||
317 | #define AR_PHY_EXT_CCA0 0x99b8 | 335 | #define AR_PHY_EXT_CCA0 0x99b8 |
318 | #define AR_PHY_EXT_CCA0_THRESH62 0x000000FF | 336 | #define AR_PHY_EXT_CCA0_THRESH62 0x000000FF |
@@ -401,6 +419,7 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, | |||
401 | #define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0 | 419 | #define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0 |
402 | #define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6 | 420 | #define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6 |
403 | #define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000 | 421 | #define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000 |
422 | #define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13 | ||
404 | 423 | ||
405 | #define AR_PHY_GAIN_2GHZ 0xA20C | 424 | #define AR_PHY_GAIN_2GHZ 0xA20C |
406 | #define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000 | 425 | #define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000 |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 61edfab20ffc..61dbdd227444 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -100,38 +100,6 @@ static u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp) | |||
100 | return (tsf & ~0x7fff) | rstamp; | 100 | return (tsf & ~0x7fff) | rstamp; |
101 | } | 101 | } |
102 | 102 | ||
103 | static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len, gfp_t gfp_mask) | ||
104 | { | ||
105 | struct sk_buff *skb; | ||
106 | u32 off; | ||
107 | |||
108 | /* | ||
109 | * Cache-line-align. This is important (for the | ||
110 | * 5210 at least) as not doing so causes bogus data | ||
111 | * in rx'd frames. | ||
112 | */ | ||
113 | |||
114 | /* Note: the kernel can allocate a value greater than | ||
115 | * what we ask it to give us. We really only need 4 KB as that | ||
116 | * is this hardware supports and in fact we need at least 3849 | ||
117 | * as that is the MAX AMSDU size this hardware supports. | ||
118 | * Unfortunately this means we may get 8 KB here from the | ||
119 | * kernel... and that is actually what is observed on some | ||
120 | * systems :( */ | ||
121 | skb = __dev_alloc_skb(len + sc->cachelsz - 1, gfp_mask); | ||
122 | if (skb != NULL) { | ||
123 | off = ((unsigned long) skb->data) % sc->cachelsz; | ||
124 | if (off != 0) | ||
125 | skb_reserve(skb, sc->cachelsz - off); | ||
126 | } else { | ||
127 | DPRINTF(sc, ATH_DBG_FATAL, | ||
128 | "skbuff alloc of size %u failed\n", len); | ||
129 | return NULL; | ||
130 | } | ||
131 | |||
132 | return skb; | ||
133 | } | ||
134 | |||
135 | /* | 103 | /* |
136 | * For Decrypt or Demic errors, we only mark packet status here and always push | 104 | * For Decrypt or Demic errors, we only mark packet status here and always push |
137 | * up the frame up to let mac80211 handle the actual error case, be it no | 105 | * up the frame up to let mac80211 handle the actual error case, be it no |
@@ -252,6 +220,10 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, | |||
252 | else if (ds->ds_rxstat.rs_rssi > 127) | 220 | else if (ds->ds_rxstat.rs_rssi > 127) |
253 | ds->ds_rxstat.rs_rssi = 127; | 221 | ds->ds_rxstat.rs_rssi = 127; |
254 | 222 | ||
223 | /* Update Beacon RSSI, this is used by ANI. */ | ||
224 | if (ieee80211_is_beacon(fc)) | ||
225 | sc->nodestats.ns_avgbrssi = ds->ds_rxstat.rs_rssi; | ||
226 | |||
255 | rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); | 227 | rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); |
256 | rx_status->band = hw->conf.channel->band; | 228 | rx_status->band = hw->conf.channel->band; |
257 | rx_status->freq = hw->conf.channel->center_freq; | 229 | rx_status->freq = hw->conf.channel->center_freq; |
@@ -332,10 +304,10 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
332 | spin_lock_init(&sc->rx.rxbuflock); | 304 | spin_lock_init(&sc->rx.rxbuflock); |
333 | 305 | ||
334 | sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN, | 306 | sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN, |
335 | min(sc->cachelsz, (u16)64)); | 307 | min(sc->common.cachelsz, (u16)64)); |
336 | 308 | ||
337 | DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", | 309 | DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", |
338 | sc->cachelsz, sc->rx.bufsize); | 310 | sc->common.cachelsz, sc->rx.bufsize); |
339 | 311 | ||
340 | /* Initialize rx descriptors */ | 312 | /* Initialize rx descriptors */ |
341 | 313 | ||
@@ -348,7 +320,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
348 | } | 320 | } |
349 | 321 | ||
350 | list_for_each_entry(bf, &sc->rx.rxbuf, list) { | 322 | list_for_each_entry(bf, &sc->rx.rxbuf, list) { |
351 | skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL); | 323 | skb = ath_rxbuf_alloc(&sc->common, sc->rx.bufsize, GFP_KERNEL); |
352 | if (skb == NULL) { | 324 | if (skb == NULL) { |
353 | error = -ENOMEM; | 325 | error = -ENOMEM; |
354 | goto err; | 326 | goto err; |
@@ -448,8 +420,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
448 | else | 420 | else |
449 | rfilt |= ATH9K_RX_FILTER_BEACON; | 421 | rfilt |= ATH9K_RX_FILTER_BEACON; |
450 | 422 | ||
451 | /* If in HOSTAP mode, want to enable reception of PSPOLL frames */ | 423 | if (sc->rx.rxfilter & FIF_PSPOLL) |
452 | if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) | ||
453 | rfilt |= ATH9K_RX_FILTER_PSPOLL; | 424 | rfilt |= ATH9K_RX_FILTER_PSPOLL; |
454 | 425 | ||
455 | if (sc->sec_wiphy) { | 426 | if (sc->sec_wiphy) { |
@@ -774,7 +745,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
774 | 745 | ||
775 | /* Ensure we always have an skb to requeue once we are done | 746 | /* Ensure we always have an skb to requeue once we are done |
776 | * processing the current buffer's skb */ | 747 | * processing the current buffer's skb */ |
777 | requeue_skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_ATOMIC); | 748 | requeue_skb = ath_rxbuf_alloc(&sc->common, sc->rx.bufsize, GFP_ATOMIC); |
778 | 749 | ||
779 | /* If there is no memory we ignore the current RX'd frame, | 750 | /* If there is no memory we ignore the current RX'd frame, |
780 | * tell hardware it can give us a new frame using the old | 751 | * tell hardware it can give us a new frame using the old |
@@ -789,7 +760,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
789 | DMA_FROM_DEVICE); | 760 | DMA_FROM_DEVICE); |
790 | 761 | ||
791 | skb_put(skb, ds->ds_rxstat.rs_datalen); | 762 | skb_put(skb, ds->ds_rxstat.rs_datalen); |
792 | skb->protocol = cpu_to_be16(ETH_P_CONTROL); | ||
793 | 763 | ||
794 | /* see if any padding is done by the hw and remove it */ | 764 | /* see if any padding is done by the hw and remove it */ |
795 | hdr = (struct ieee80211_hdr *)skb->data; | 765 | hdr = (struct ieee80211_hdr *)skb->data; |