diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285.h b/sys/dev/ath/ath_hal/ar9002/ar9285.h index 7e296a69d2e3..3f6b48143c43 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9285.h +++ b/sys/dev/ath/ath_hal/ar9002/ar9285.h @@ -21,10 +21,10 @@ #include "ar5416/ar5416.h" enum ar9285_ant_div_comb_lna_conf { - ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2, - ATH_ANT_DIV_COMB_LNA2, - ATH_ANT_DIV_COMB_LNA1, - ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2, + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2 = 0, + ATH_ANT_DIV_COMB_LNA2 = 1, + ATH_ANT_DIV_COMB_LNA1 = 2, + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2 = 3, }; struct ar9285_ant_comb { diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c index 7aebc960a35b..653b586e77fb 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c @@ -407,15 +407,6 @@ ar9285FillCapabilityInfo(struct ath_hal *ah) return AH_TRUE; } -/* - * Antenna selection is not (currently) done this way. - */ -HAL_BOOL -ar9285SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) -{ - return AH_TRUE; -} - static const char* ar9285Probe(uint16_t vendorid, uint16_t devid) { diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_diversity.c b/sys/dev/ath/ath_hal/ar9002/ar9285_diversity.c index d19e3def1900..a1c2bd26f0fe 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9285_diversity.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9285_diversity.c @@ -374,11 +374,19 @@ ar9285_ant_comb_scan(struct ath_hal *ah, struct ath_rx_status *rs, if (! ar9285_check_div_comb(ah)) return; + if (AH5212(ah)->ah_diversity == AH_FALSE) + return; + rx_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_CURRENT_SHIFT) & ATH_ANT_RX_MASK; main_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_MAIN_SHIFT) & ATH_ANT_RX_MASK; +#if 0 + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: main: %d, alt: %d, rx_ant_conf: %x, main_ant_conf: %x\n", + __func__, main_rssi, alt_rssi, rx_ant_conf, main_ant_conf); +#endif + /* Record packet only when alt_rssi is positive */ if (alt_rssi > 0) { antcomb->total_pkt_count++; @@ -587,6 +595,24 @@ div_comb_done: ar9285_antdiv_comb_conf_set(ah, &div_ant_conf); + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: total_pkt_count=%d\n", + __func__, antcomb->total_pkt_count); + + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: main_total_rssi=%d\n", + __func__, antcomb->main_total_rssi); + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: alt_total_rssi=%d\n", + __func__, antcomb->alt_total_rssi); + + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: main_rssi_avg=%d\n", + __func__, main_rssi_avg); + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: alt_alt_rssi_avg=%d\n", + __func__, alt_rssi_avg); + + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: main_recv_cnt=%d\n", + __func__, antcomb->main_recv_cnt); + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: alt_recv_cnt=%d\n", + __func__, antcomb->alt_recv_cnt); + if (curr_alt_set != div_ant_conf.alt_lna_conf) HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: lna_conf: %x -> %x\n", __func__, curr_alt_set, div_ant_conf.alt_lna_conf); @@ -604,3 +630,117 @@ div_comb_done: antcomb->main_recv_cnt = 0; antcomb->alt_recv_cnt = 0; } + +/* + * Set the antenna switch to control RX antenna diversity. + * + * If a fixed configuration is used, the LNA and div bias + * settings are fixed and the antenna diversity scanning routine + * is disabled. + * + * If a variable configuration is used, a default is programmed + * in and sampling commences per RXed packet. + * + * Since this is called from ar9285SetBoardValues() to setup + * diversity, it means that after a reset or scan, any current + * software diversity combining settings will be lost and won't + * re-appear until after the first successful sample run. + * Please keep this in mind if you're seeing weird performance + * that happens to relate to scan/diversity timing. + */ +HAL_BOOL +ar9285SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) +{ + int regVal; + const HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; + const MODAL_EEP4K_HEADER *pModal = &ee->ee_base.modalHeader; + uint8_t ant_div_control1, ant_div_control2; + + if (pModal->version < 3) { + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: not supported\n", + __func__); + return AH_FALSE; /* Can't do diversity */ + } + + /* Store settings */ + AH5212(ah)->ah_antControl = settings; + AH5212(ah)->ah_diversity = (settings == HAL_ANT_VARIABLE); + + /* XXX don't fiddle if the PHY is in sleep mode or ! chan */ + + /* Begin setting the relevant registers */ + + ant_div_control1 = pModal->antdiv_ctl1; + ant_div_control2 = pModal->antdiv_ctl2; + + regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); + regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL)); + + /* enable antenna diversity only if diversityControl == HAL_ANT_VARIABLE */ + if (settings == HAL_ANT_VARIABLE) + regVal |= SM(ant_div_control1, AR_PHY_9285_ANT_DIV_CTL); + + if (settings == HAL_ANT_VARIABLE) { + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: HAL_ANT_VARIABLE\n", + __func__); + regVal |= SM(ant_div_control2, AR_PHY_9285_ANT_DIV_ALT_LNACONF); + regVal |= SM((ant_div_control2 >> 2), AR_PHY_9285_ANT_DIV_MAIN_LNACONF); + regVal |= SM((ant_div_control1 >> 1), AR_PHY_9285_ANT_DIV_ALT_GAINTB); + regVal |= SM((ant_div_control1 >> 2), AR_PHY_9285_ANT_DIV_MAIN_GAINTB); + } else { + if (settings == HAL_ANT_FIXED_A) { + /* Diversity disabled, RX = LNA1 */ + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: HAL_ANT_FIXED_A\n", + __func__); + regVal |= SM(ATH_ANT_DIV_COMB_LNA2, AR_PHY_9285_ANT_DIV_ALT_LNACONF); + regVal |= SM(ATH_ANT_DIV_COMB_LNA1, AR_PHY_9285_ANT_DIV_MAIN_LNACONF); + regVal |= SM(AR_PHY_9285_ANT_DIV_GAINTB_0, AR_PHY_9285_ANT_DIV_ALT_GAINTB); + regVal |= SM(AR_PHY_9285_ANT_DIV_GAINTB_1, AR_PHY_9285_ANT_DIV_MAIN_GAINTB); + } + else if (settings == HAL_ANT_FIXED_B) { + /* Diversity disabled, RX = LNA2 */ + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, "%s: HAL_ANT_FIXED_B\n", + __func__); + regVal |= SM(ATH_ANT_DIV_COMB_LNA1, AR_PHY_9285_ANT_DIV_ALT_LNACONF); + regVal |= SM(ATH_ANT_DIV_COMB_LNA2, AR_PHY_9285_ANT_DIV_MAIN_LNACONF); + regVal |= SM(AR_PHY_9285_ANT_DIV_GAINTB_1, AR_PHY_9285_ANT_DIV_ALT_GAINTB); + regVal |= SM(AR_PHY_9285_ANT_DIV_GAINTB_0, AR_PHY_9285_ANT_DIV_MAIN_GAINTB); + } + } + + OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal); + regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); + regVal = OS_REG_READ(ah, AR_PHY_CCK_DETECT); + regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); + if (settings == HAL_ANT_VARIABLE) + regVal |= SM((ant_div_control1 >> 3), AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); + + OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal); + regVal = OS_REG_READ(ah, AR_PHY_CCK_DETECT); + + /* + * If Diversity combining is available and the diversity setting + * is to allow variable diversity, enable it by default. + * + * This will be eventually overridden by the software antenna + * diversity logic. + * + * Note that yes, this following section overrides the above + * settings for the LNA configuration and fast-bias. + */ + if (ar9285_check_div_comb(ah) && AH5212(ah)->ah_diversity == AH_TRUE) { + // If support DivComb, set MAIN to LNA1 and ALT to LNA2 at the first beginning + HALDEBUG(ah, HAL_DEBUG_DIVERSITY, + "%s: Enable initial settings for combined diversity\n", + __func__); + regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); + regVal &= (~(AR_PHY_9285_ANT_DIV_MAIN_LNACONF | AR_PHY_9285_ANT_DIV_ALT_LNACONF)); + regVal |= (ATH_ANT_DIV_COMB_LNA1 << AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S); + regVal |= (ATH_ANT_DIV_COMB_LNA2 << AR_PHY_9285_ANT_DIV_ALT_LNACONF_S); + regVal &= (~(AR_PHY_9285_FAST_DIV_BIAS)); + regVal |= (0 << AR_PHY_9285_FAST_DIV_BIAS_S); + OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal); + } + + return AH_TRUE; +} diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c b/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c index 68c8ceaeaec3..bf0347bd1572 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c @@ -237,8 +237,6 @@ ar9285SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan) const MODAL_EEP4K_HEADER *pModal; uint8_t txRxAttenLocal; uint8_t ob[5], db1[5], db2[5]; - uint8_t ant_div_control1, ant_div_control2; - uint32_t regVal; pModal = &eep->modalHeader; txRxAttenLocal = 23; @@ -248,36 +246,10 @@ ar9285SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan) /* Single chain for 4K EEPROM*/ ar9285SetBoardGain(ah, pModal, eep, txRxAttenLocal); - /* Initialize Ant Diversity settings from EEPROM */ - if (pModal->version >= 3) { - ant_div_control1 = pModal->antdiv_ctl1; - ant_div_control2 = pModal->antdiv_ctl2; - - regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); - regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL)); - - regVal |= SM(ant_div_control1, - AR_PHY_9285_ANT_DIV_CTL); - regVal |= SM(ant_div_control2, - AR_PHY_9285_ANT_DIV_ALT_LNACONF); - regVal |= SM((ant_div_control2 >> 2), - AR_PHY_9285_ANT_DIV_MAIN_LNACONF); - regVal |= SM((ant_div_control1 >> 1), - AR_PHY_9285_ANT_DIV_ALT_GAINTB); - regVal |= SM((ant_div_control1 >> 2), - AR_PHY_9285_ANT_DIV_MAIN_GAINTB); - - OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal); - regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); - regVal = OS_REG_READ(ah, AR_PHY_CCK_DETECT); - regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); - regVal |= SM((ant_div_control1 >> 3), - AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); - - OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal); - regVal = OS_REG_READ(ah, AR_PHY_CCK_DETECT); - } + /* Initialize Ant Diversity settings if supported */ + (void) ar9285SetAntennaSwitch(ah, AH5212(ah)->ah_antControl); + /* Configure TX power calibration */ if (pModal->version >= 2) { ob[0] = pModal->ob_0; ob[1] = pModal->ob_1; @@ -379,6 +351,7 @@ ar9285SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan) if (AR_SREV_9271(ah) || AR_SREV_KITE(ah)) { uint8_t bb_desired_scale = (pModal->bb_scale_smrt_antenna & EEP_4K_BB_DESIRED_SCALE_MASK); if ((eep->baseEepHeader.txGainType == 0) && (bb_desired_scale != 0)) { + ath_hal_printf(ah, "[ath]: adjusting cck tx gain factor\n"); uint32_t pwrctrl, mask, clr; mask = (1<<0) | (1<<5) | (1<<10) | (1<<15) | (1<<20) | (1<<25);