aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/hw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/hw.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c323
1 files changed, 110 insertions, 213 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 87db1ee1c298..6c69e4e8b1cb 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -23,6 +23,7 @@
#include "hw-ops.h"
#include "rc.h"
#include "ar9003_mac.h"
+#include "ar9003_mci.h"
static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type);
@@ -448,6 +449,7 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
ah->slottime = ATH9K_SLOT_TIME_9;
ah->globaltxtimeout = (u32) -1;
ah->power_mode = ATH9K_PM_UNDEFINED;
+ ah->htc_reset_init = true;
}
static int ath9k_hw_init_macaddr(struct ath_hw *ah)
@@ -554,7 +556,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
return -EIO;
}
- if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
+ if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
((AR_SREV_9160(ah) || AR_SREV_9280(ah)) &&
!ah->is_pciexpress)) {
@@ -618,9 +620,6 @@ static int __ath9k_hw_init(struct ath_hw *ah)
if (!ah->is_pciexpress)
ath9k_hw_disablepcie(ah);
- if (!AR_SREV_9300_20_OR_LATER(ah))
- ar9002_hw_cck_chan14_spread(ah);
-
r = ath9k_hw_post_init(ah);
if (r)
return r;
@@ -1385,10 +1384,16 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
static bool ath9k_hw_chip_reset(struct ath_hw *ah,
struct ath9k_channel *chan)
{
- if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) {
- if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON))
- return false;
- } else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
+ int reset_type = ATH9K_RESET_WARM;
+
+ if (AR_SREV_9280(ah)) {
+ if (ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
+ reset_type = ATH9K_RESET_POWER_ON;
+ else
+ reset_type = ATH9K_RESET_COLD;
+ }
+
+ if (!ath9k_hw_set_reset_reg(ah, reset_type))
return false;
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
@@ -1514,70 +1519,95 @@ bool ath9k_hw_check_alive(struct ath_hw *ah)
}
EXPORT_SYMBOL(ath9k_hw_check_alive);
-int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
- struct ath9k_hw_cal_data *caldata, bool bChannelChange)
+/*
+ * Fast channel change:
+ * (Change synthesizer based on channel freq without resetting chip)
+ *
+ * Don't do FCC when
+ * - Flag is not set
+ * - Chip is just coming out of full sleep
+ * - Channel to be set is same as current channel
+ * - Channel flags are different, (eg.,moving from 2GHz to 5GHz channel)
+ */
+static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
- struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
- u32 saveLedState;
- struct ath9k_channel *curchan = ah->curchan;
- u32 saveDefAntenna;
- u32 macStaId1;
- u64 tsf = 0;
- int i, r;
- bool allow_fbs = false;
- bool mci = !!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI);
- bool save_fullsleep = ah->chip_fullsleep;
+ int ret;
- if (mci) {
+ if (AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI)
+ goto fail;
- ar9003_mci_2g5g_changed(ah, IS_CHAN_2GHZ(chan));
+ if (ah->chip_fullsleep)
+ goto fail;
- if (mci_hw->bt_state == MCI_BT_CAL_START) {
- u32 payload[4] = {0, 0, 0, 0};
+ if (!ah->curchan)
+ goto fail;
- ath_dbg(common, MCI, "MCI stop rx for BT CAL\n");
+ if (chan->channel == ah->curchan->channel)
+ goto fail;
- mci_hw->bt_state = MCI_BT_CAL;
+ if ((chan->channelFlags & CHANNEL_ALL) !=
+ (ah->curchan->channelFlags & CHANNEL_ALL))
+ goto fail;
- /*
- * MCI FIX: disable mci interrupt here. This is to avoid
- * SW_MSG_DONE or RX_MSG bits to trigger MCI_INT and
- * lead to mci_intr reentry.
- */
+ if (!ath9k_hw_check_alive(ah))
+ goto fail;
- ar9003_mci_disable_interrupt(ah);
+ /*
+ * For AR9462, make sure that calibration data for
+ * re-using are present.
+ */
+ if (AR_SREV_9462(ah) && (!ah->caldata ||
+ !ah->caldata->done_txiqcal_once ||
+ !ah->caldata->done_txclcal_once ||
+ !ah->caldata->rtt_hist.num_readings))
+ goto fail;
- ath_dbg(common, MCI, "send WLAN_CAL_GRANT\n");
- MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_GRANT);
- ar9003_mci_send_message(ah, MCI_GPM, 0, payload,
- 16, true, false);
+ ath_dbg(common, RESET, "FastChannelChange for %d -> %d\n",
+ ah->curchan->channel, chan->channel);
- ath_dbg(common, MCI, "\nMCI BT is calibrating\n");
+ ret = ath9k_hw_channel_change(ah, chan);
+ if (!ret)
+ goto fail;
- /* Wait BT calibration to be completed for 25ms */
+ ath9k_hw_loadnf(ah, ah->curchan);
+ ath9k_hw_start_nfcal(ah, true);
- if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_DONE,
- 0, 25000))
- ath_dbg(common, MCI,
- "MCI got BT_CAL_DONE\n");
- else
- ath_dbg(common, MCI,
- "MCI ### BT cal takes to long, force bt_state to be bt_awake\n");
- mci_hw->bt_state = MCI_BT_AWAKE;
- /* MCI FIX: enable mci interrupt here */
- ar9003_mci_enable_interrupt(ah);
+ if ((ah->caps.hw_caps & ATH9K_HW_CAP_MCI) && ar9003_mci_is_ready(ah))
+ ar9003_mci_2g5g_switch(ah, true);
- return true;
- }
- }
+ if (AR_SREV_9271(ah))
+ ar9002_hw_load_ani_reg(ah, chan);
+
+ return 0;
+fail:
+ return -EINVAL;
+}
+
+int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
+ struct ath9k_hw_cal_data *caldata, bool fastcc)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ u32 saveLedState;
+ u32 saveDefAntenna;
+ u32 macStaId1;
+ u64 tsf = 0;
+ int i, r;
+ bool start_mci_reset = false;
+ bool mci = !!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI);
+ bool save_fullsleep = ah->chip_fullsleep;
+ if (mci) {
+ start_mci_reset = ar9003_mci_start_reset(ah, chan);
+ if (start_mci_reset)
+ return 0;
+ }
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
return -EIO;
- if (curchan && !ah->chip_fullsleep)
- ath9k_hw_getnf(ah, curchan);
+ if (ah->curchan && !ah->chip_fullsleep)
+ ath9k_hw_getnf(ah, ah->curchan);
ah->caldata = caldata;
if (caldata &&
@@ -1590,47 +1620,14 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
}
ah->noise = ath9k_hw_getchan_noise(ah, chan);
- if (AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI)
- bChannelChange = false;
-
- if (caldata &&
- caldata->done_txiqcal_once &&
- caldata->done_txclcal_once &&
- caldata->rtt_hist.num_readings)
- allow_fbs = true;
-
- if (bChannelChange &&
- (ah->chip_fullsleep != true) &&
- (ah->curchan != NULL) &&
- (chan->channel != ah->curchan->channel) &&
- (allow_fbs ||
- ((chan->channelFlags & CHANNEL_ALL) ==
- (ah->curchan->channelFlags & CHANNEL_ALL)))) {
- if (ath9k_hw_channel_change(ah, chan)) {
- ath9k_hw_loadnf(ah, ah->curchan);
- ath9k_hw_start_nfcal(ah, true);
- if (mci && mci_hw->ready)
- ar9003_mci_2g5g_switch(ah, true);
-
- if (AR_SREV_9271(ah))
- ar9002_hw_load_ani_reg(ah, chan);
- return 0;
- }
- }
-
- if (mci) {
- ar9003_mci_disable_interrupt(ah);
-
- if (mci_hw->ready && !save_fullsleep) {
- ar9003_mci_mute_bt(ah);
- udelay(20);
- REG_WRITE(ah, AR_BTCOEX_CTRL, 0);
- }
-
- mci_hw->bt_state = MCI_BT_SLEEP;
- mci_hw->ready = false;
+ if (fastcc) {
+ r = ath9k_hw_do_fastcc(ah, chan);
+ if (!r)
+ return r;
}
+ if (mci)
+ ar9003_mci_stop_bt(ah, save_fullsleep);
saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA);
if (saveDefAntenna == 0)
@@ -1807,53 +1804,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_loadnf(ah, chan);
ath9k_hw_start_nfcal(ah, true);
- if (mci && mci_hw->ready) {
-
- if (IS_CHAN_2GHZ(chan) &&
- (mci_hw->bt_state == MCI_BT_SLEEP)) {
-
- if (ar9003_mci_check_int(ah,
- AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET) ||
- ar9003_mci_check_int(ah,
- AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)) {
-
- /*
- * BT is sleeping. Check if BT wakes up during
- * WLAN calibration. If BT wakes up during
- * WLAN calibration, need to go through all
- * message exchanges again and recal.
- */
-
- ath_dbg(common, MCI,
- "MCI BT wakes up during WLAN calibration\n");
-
- REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
- AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET |
- AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE);
- ath_dbg(common, MCI, "MCI send REMOTE_RESET\n");
- ar9003_mci_remote_reset(ah, true);
- ar9003_mci_send_sys_waking(ah, true);
- udelay(1);
- if (IS_CHAN_2GHZ(chan))
- ar9003_mci_send_lna_transfer(ah, true);
-
- mci_hw->bt_state = MCI_BT_AWAKE;
-
- ath_dbg(common, MCI, "MCI re-cal\n");
-
- if (caldata) {
- caldata->done_txiqcal_once = false;
- caldata->done_txclcal_once = false;
- caldata->rtt_hist.num_readings = 0;
- }
-
- if (!ath9k_hw_init_cal(ah, chan))
- return -EIO;
-
- }
- }
- ar9003_mci_enable_interrupt(ah);
- }
+ if (mci && ar9003_mci_end_reset(ah, chan, caldata))
+ return -EIO;
ENABLE_REGWRITE_BUFFER(ah);
@@ -1894,24 +1846,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
#endif
}
- if (ah->btcoex_hw.enabled &&
- ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE)
+ if (ath9k_hw_btcoex_is_enabled(ah))
ath9k_hw_btcoex_enable(ah);
- if (mci && mci_hw->ready) {
- /*
- * check BT state again to make
- * sure it's not changed.
- */
-
- ar9003_mci_sync_bt_state(ah);
- ar9003_mci_2g5g_switch(ah, true);
-
- if ((mci_hw->bt_state == MCI_BT_AWAKE) &&
- (mci_hw->query_bt == true)) {
- mci_hw->need_flush_btinfo = true;
- }
- }
+ if (mci)
+ ar9003_mci_check_bt(ah);
if (AR_SREV_9300_20_OR_LATER(ah)) {
ar9003_hw_bb_watchdog_config(ah);
@@ -1962,8 +1901,7 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
/* Shutdown chip. Active low */
- if (!AR_SREV_5416(ah) &&
- !AR_SREV_9271(ah) && !AR_SREV_9462_10(ah)) {
+ if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah)) {
REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN);
udelay(2);
}
@@ -2038,8 +1976,7 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)
if (setChip) {
if ((REG_READ(ah, AR_RTC_STATUS) &
AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) {
- if (ath9k_hw_set_reset_reg(ah,
- ATH9K_RESET_POWER_ON) != true) {
+ if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
return false;
}
if (!AR_SREV_9300_20_OR_LATER(ah))
@@ -2077,7 +2014,6 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)
bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
{
struct ath_common *common = ath9k_hw_common(ah);
- struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
int status = true, setChip = true;
static const char *modes[] = {
"AWAKE",
@@ -2101,20 +2037,8 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
break;
case ATH9K_PM_FULL_SLEEP:
-
- if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) {
- if (ar9003_mci_state(ah, MCI_STATE_ENABLE, NULL) &&
- (mci->bt_state != MCI_BT_SLEEP) &&
- !mci->halted_bt_gpm) {
- ath_dbg(common, MCI,
- "MCI halt BT GPM (full_sleep)\n");
- ar9003_mci_send_coex_halt_bt_gpm(ah,
- true, true);
- }
-
- mci->ready = false;
- REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2);
- }
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI)
+ ar9003_mci_set_full_sleep(ah);
ath9k_set_power_sleep(ah, setChip);
ah->chip_fullsleep = true;
@@ -2304,7 +2228,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
struct ath9k_hw_capabilities *pCap = &ah->caps;
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath_common *common = ath9k_hw_common(ah);
- struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
unsigned int chip_chainmask;
u16 eeval;
@@ -2423,30 +2346,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
else
pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS;
- if (common->btcoex_enabled) {
- if (AR_SREV_9462(ah))
- btcoex_hw->scheme = ATH_BTCOEX_CFG_MCI;
- else if (AR_SREV_9300_20_OR_LATER(ah)) {
- btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE;
- btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9300;
- btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9300;
- btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO_9300;
- } else if (AR_SREV_9280_20_OR_LATER(ah)) {
- btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9280;
- btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9280;
-
- if (AR_SREV_9285(ah)) {
- btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE;
- btcoex_hw->btpriority_gpio =
- ATH_BTPRIORITY_GPIO_9285;
- } else {
- btcoex_hw->scheme = ATH_BTCOEX_CFG_2WIRE;
- }
- }
- } else {
- btcoex_hw->scheme = ATH_BTCOEX_CFG_NONE;
- }
-
if (AR_SREV_9300_20_OR_LATER(ah)) {
pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_FASTCLOCK;
if (!AR_SREV_9330(ah) && !AR_SREV_9485(ah))
@@ -2530,8 +2429,17 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
if (AR_SREV_9485_OR_LATER(ah))
ah->enabled_cals |= TX_IQ_ON_AGC_CAL;
}
- if (AR_SREV_9462(ah))
- pCap->hw_caps |= ATH9K_HW_CAP_RTT | ATH9K_HW_CAP_MCI;
+
+ if (AR_SREV_9462(ah)) {
+
+ if (!(ah->ent_mode & AR_ENT_OTP_49GHZ_DISABLE))
+ pCap->hw_caps |= ATH9K_HW_CAP_MCI;
+
+ if (AR_SREV_9462_20(ah))
+ pCap->hw_caps |= ATH9K_HW_CAP_RTT;
+
+ }
+
return 0;
}
@@ -2657,12 +2565,6 @@ void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val)
}
EXPORT_SYMBOL(ath9k_hw_set_gpio);
-u32 ath9k_hw_getdefantenna(struct ath_hw *ah)
-{
- return REG_READ(ah, AR_DEF_ANTENNA) & 0x7;
-}
-EXPORT_SYMBOL(ath9k_hw_getdefantenna);
-
void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna)
{
REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
@@ -2720,6 +2622,7 @@ bool ath9k_hw_phy_disable(struct ath_hw *ah)
return false;
ath9k_hw_init_pll(ah, NULL);
+ ah->htc_reset_init = true;
return true;
}
EXPORT_SYMBOL(ath9k_hw_phy_disable);
@@ -3080,12 +2983,6 @@ EXPORT_SYMBOL(ath_gen_timer_isr);
/* HTC */
/********/
-void ath9k_hw_htc_resetinit(struct ath_hw *ah)
-{
- ah->htc_reset_init = true;
-}
-EXPORT_SYMBOL(ath9k_hw_htc_resetinit);
-
static struct {
u32 version;
const char * name;