summaryrefslogtreecommitdiffstats
path: root/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c')
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c186
1 files changed, 184 insertions, 2 deletions
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c
index ba7777e..9028ab7 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c
@@ -1200,6 +1200,44 @@ ar9300_noise_floor_cal_or_power_get(struct ath_hal *ah, int32_t frequency,
return nf_use;
}
+/*
+ * Return the Rx NF offset for specific channel.
+ * The values saved in EEPROM/OTP/Flash is converted through the following way:
+ * ((_p) - NOISE_PWR_DATA_OFFSET) << 2
+ * So we need to convert back to the original values.
+ */
+int ar9300_get_rx_nf_offset(struct ath_hal *ah, struct ieee80211_channel *chan, int8_t *nf_pwr, int8_t *nf_cal) {
+ HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
+ int8_t rx_nf_pwr, rx_nf_cal;
+ int i;
+ //HALASSERT(ichan);
+
+ /* Fill 0 if valid internal channel is not found */
+ if (ichan == AH_NULL) {
+ OS_MEMZERO(nf_pwr, sizeof(nf_pwr[0])*OSPREY_MAX_CHAINS);
+ OS_MEMZERO(nf_cal, sizeof(nf_cal[0])*OSPREY_MAX_CHAINS);
+ return -1;
+ }
+
+ for (i = 0; i < OSPREY_MAX_CHAINS; i++) {
+ if ((rx_nf_pwr = ar9300_noise_floor_cal_or_power_get(ah, ichan->channel, i, 0)) == 1) {
+ nf_pwr[i] = 0;
+ } else {
+ //printk("%s: raw nf_pwr[%d] = %d\n", __func__, i, rx_nf_pwr);
+ nf_pwr[i] = NOISE_PWR_DBM_2_INT(rx_nf_pwr);
+ }
+
+ if ((rx_nf_cal = ar9300_noise_floor_cal_or_power_get(ah, ichan->channel, i, 1)) == 1) {
+ nf_cal[i] = 0;
+ } else {
+ //printk("%s: raw nf_cal[%d] = %d\n", __func__, i, rx_nf_cal);
+ nf_cal[i] = NOISE_PWR_DBM_2_INT(rx_nf_cal);
+ }
+ }
+
+ return 0;
+}
+
int32_t ar9300_rx_gain_index_get(struct ath_hal *ah)
{
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
@@ -1530,6 +1568,61 @@ u_int16_t ar9300_ant_ctrl_chain_get(struct ath_hal *ah, int chain,
return 0;
}
+/*
+ * Select the usage of antenna via the RF switch.
+ * Default values are loaded from eeprom.
+ */
+HAL_BOOL ar9300_ant_swcom_sel(struct ath_hal *ah, u_int8_t ops,
+ u_int32_t *common_tbl1, u_int32_t *common_tbl2)
+{
+ ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
+ struct ath_hal_private *ap = AH_PRIVATE(ah);
+ const struct ieee80211_channel *curchan = ap->ah_curchan;
+ enum {
+ ANT_SELECT_OPS_GET,
+ ANT_SELECT_OPS_SET,
+ };
+
+ if (AR_SREV_JUPITER(ah) || AR_SREV_SCORPION(ah))
+ return AH_FALSE;
+
+ if (!curchan)
+ return AH_FALSE;
+
+#define AR_SWITCH_TABLE_COM_ALL (0xffff)
+#define AR_SWITCH_TABLE_COM_ALL_S (0)
+#define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
+#define AR_SWITCH_TABLE_COM2_ALL_S (0)
+ switch (ops) {
+ case ANT_SELECT_OPS_GET:
+ *common_tbl1 = OS_REG_READ_FIELD(ah, AR_PHY_SWITCH_COM,
+ AR_SWITCH_TABLE_COM_ALL);
+ *common_tbl2 = OS_REG_READ_FIELD(ah, AR_PHY_SWITCH_COM_2,
+ AR_SWITCH_TABLE_COM2_ALL);
+ break;
+ case ANT_SELECT_OPS_SET:
+ OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
+ AR_SWITCH_TABLE_COM_ALL, *common_tbl1);
+ OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2,
+ AR_SWITCH_TABLE_COM2_ALL, *common_tbl2);
+
+ /* write back to eeprom */
+ if (IEEE80211_IS_CHAN_2GHZ(curchan)) {
+ eep->modal_header_2g.ant_ctrl_common = *common_tbl1;
+ eep->modal_header_2g.ant_ctrl_common2 = *common_tbl2;
+ } else {
+ eep->modal_header_5g.ant_ctrl_common = *common_tbl1;
+ eep->modal_header_5g.ant_ctrl_common2 = *common_tbl2;
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ return AH_TRUE;
+}
+
HAL_BOOL ar9300_ant_ctrl_apply(struct ath_hal *ah, HAL_BOOL is_2ghz)
{
u_int32_t value;
@@ -1606,6 +1699,7 @@ HAL_BOOL ar9300_ant_ctrl_apply(struct ath_hal *ah, HAL_BOOL is_2ghz)
if ( AR_SREV_POSEIDON(ah) && (ahp->ah_lna_div_use_bt_ant_enable == TRUE) ) {
value &= ~AR_SWITCH_TABLE_COM2_ALL;
value |= ah->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable;
+ HALDEBUG(ah, HAL_DEBUG_RESET, "%s: com2=0x%08x\n", __func__, value)
}
#endif /* ATH_ANT_DIV_COMB */
OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
@@ -1711,6 +1805,8 @@ HAL_BOOL ar9300_ant_ctrl_apply(struct ath_hal *ah, HAL_BOOL is_2ghz)
/* For WB225, need to swith ANT2 from BT to Wifi
* This will not affect HB125 LNA diversity feature.
*/
+ HALDEBUG(ah, HAL_DEBUG_RESET, "%s: com2=0x%08x\n", __func__,
+ ah->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable)
OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL,
ah->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable);
break;
@@ -1776,6 +1872,7 @@ ar9300_attenuation_margin_chain_get(struct ath_hal *ah, int chain,
return 0;
}
+#if 0
HAL_BOOL ar9300_attenuation_apply(struct ath_hal *ah, u_int16_t channel)
{
u_int32_t value;
@@ -1814,6 +1911,75 @@ HAL_BOOL ar9300_attenuation_apply(struct ath_hal *ah, u_int16_t channel)
}
return 0;
}
+#endif
+HAL_BOOL
+ar9300_attenuation_apply(struct ath_hal *ah, u_int16_t channel)
+{
+ int i;
+ uint32_t value;
+ uint32_t ext_atten_reg[3] = {
+ AR_PHY_EXT_ATTEN_CTL_0,
+ AR_PHY_EXT_ATTEN_CTL_1,
+ AR_PHY_EXT_ATTEN_CTL_2
+ };
+
+ /*
+ * If it's an AR9462 and we're receiving on the second
+ * chain only, set the chain 0 details from chain 1
+ * calibration.
+ *
+ * This is from ath9k.
+ */
+ if (AR_SREV_JUPITER(ah) && (AH9300(ah)->ah_rx_chainmask == 0x2)) {
+ value = ar9300_attenuation_chain_get(ah, 1, channel);
+ OS_REG_RMW_FIELD(ah, ext_atten_reg[0],
+ AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value);
+ value = ar9300_attenuation_margin_chain_get(ah, 1, channel);
+ OS_REG_RMW_FIELD(ah, ext_atten_reg[0],
+ AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value);
+ }
+
+ /*
+ * Now, loop over the configured transmit chains and
+ * load in the attenuation/margin settings as appropriate.
+ */
+ for (i = 0; i < 3; i++) {
+ if ((AH9300(ah)->ah_tx_chainmask & (1 << i)) == 0)
+ continue;
+
+ value = ar9300_attenuation_chain_get(ah, i, channel);
+ OS_REG_RMW_FIELD(ah, ext_atten_reg[i],
+ AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB,
+ value);
+
+ if (AR_SREV_POSEIDON(ah) &&
+ (ar9300_rx_gain_index_get(ah) == 0) &&
+ ah->ah_config.ath_hal_ext_atten_margin_cfg) {
+ value = 5;
+ } else {
+ value = ar9300_attenuation_margin_chain_get(ah, 0,
+ channel);
+ }
+
+ /*
+ * I'm not sure why it's loading in this setting into
+ * the chain 0 margin regardless of the current chain.
+ */
+ if (ah->ah_config.ath_hal_min_gainidx)
+ OS_REG_RMW_FIELD(ah,
+ AR_PHY_EXT_ATTEN_CTL_0,
+ AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN,
+ value);
+
+ OS_REG_RMW_FIELD(ah,
+ ext_atten_reg[i],
+ AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN,
+ value);
+ }
+
+ return (0);
+}
+
static u_int16_t ar9300_quick_drop_get(struct ath_hal *ah,
int chain, u_int16_t channel)
@@ -2339,16 +2505,31 @@ ar9300_eeprom_set_power_per_rate_table(
HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
#endif
- tx_chainmask = chainmask ? chainmask : ahp->ah_tx_chainmask;
+ if (chainmask)
+ tx_chainmask = chainmask;
+ else
+ tx_chainmask = ahp->ah_tx_chainmaskopt ?
+ ahp->ah_tx_chainmaskopt :ahp->ah_tx_chainmask;
ar9300_get_channel_centers(ah, chan, &centers);
+#if 1
if (IEEE80211_IS_CHAN_2GHZ(chan)) {
ahp->twice_antenna_gain = p_eep_data->modal_header_2g.antenna_gain;
} else {
ahp->twice_antenna_gain = p_eep_data->modal_header_5g.antenna_gain;
}
+#else
+ if (IEEE80211_IS_CHAN_2GHZ(chan)) {
+ ahp->twice_antenna_gain = AH_MAX(p_eep_data->modal_header_2g.antenna_gain,
+ AH_PRIVATE(ah)->ah_antenna_gain_2g);
+ } else {
+ ahp->twice_antenna_gain = AH_MAX(p_eep_data->modal_header_5g.antenna_gain,
+ AH_PRIVATE(ah)->ah_antenna_gain_5g);
+ }
+#endif
+
/* Save max allowed antenna gain to ease future lookups */
ahp->twice_antenna_reduction = twice_antenna_reduction;
@@ -2885,7 +3066,8 @@ ar9300_eeprom_set_transmit_power(struct ath_hal *ah,
}
max_power_level = target_power_val_t2[i];
/* Adjusting the ah_max_power_level based on chains and antennaGain*/
- switch (ar9300_get_ntxchains(ahp->ah_tx_chainmask))
+ switch (ar9300_get_ntxchains(((ahp->ah_tx_chainmaskopt > 0) ?
+ ahp->ah_tx_chainmaskopt : ahp->ah_tx_chainmask)))
{
case 1:
break;
OpenPOWER on IntegriCloud