diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/hw.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 1974 |
1 files changed, 1257 insertions, 717 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 9f01e50d5cd..2a8ed8375ec 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Atheros Communications Inc. + * Copyright (c) 2008-2011 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,12 +16,17 @@ #include <linux/io.h> #include <linux/slab.h> +#include <linux/module.h> +#include <linux/time.h> +#include <linux/bitops.h> #include <asm/unaligned.h> #include "hw.h" #include "hw-ops.h" -#include "rc.h" #include "ar9003_mac.h" +#include "ar9003_mci.h" +#include "ar9003_phy.h" +#include "ath9k.h" static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); @@ -30,74 +35,32 @@ MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards"); MODULE_LICENSE("Dual BSD/GPL"); -static int __init ath9k_init(void) -{ - return 0; -} -module_init(ath9k_init); - -static void __exit ath9k_exit(void) -{ - return; -} -module_exit(ath9k_exit); - -/* Private hardware callbacks */ - -static void ath9k_hw_init_cal_settings(struct ath_hw *ah) -{ - ath9k_hw_private_ops(ah)->init_cal_settings(ah); -} - -static void ath9k_hw_init_mode_regs(struct ath_hw *ah) -{ - ath9k_hw_private_ops(ah)->init_mode_regs(ah); -} - -static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - return ath9k_hw_private_ops(ah)->compute_pll_control(ah, chan); -} - -static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) -{ - if (!ath9k_hw_private_ops(ah)->init_mode_gain_regs) - return; - - ath9k_hw_private_ops(ah)->init_mode_gain_regs(ah); -} - -static void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah) -{ - /* You will not have this callback if using the old ANI */ - if (!ath9k_hw_private_ops(ah)->ani_cache_ini_regs) - return; - - ath9k_hw_private_ops(ah)->ani_cache_ini_regs(ah); -} - -/********************/ -/* Helper Functions */ -/********************/ - static void ath9k_hw_set_clockrate(struct ath_hw *ah) { - struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_channel *chan = ah->curchan; unsigned int clockrate; - if (!ah->curchan) /* should really check for CCK instead */ + /* AR9287 v1.3+ uses async FIFO and runs the MAC at 117 MHz */ + if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) + clockrate = 117; + else if (!chan) /* should really check for CCK instead */ clockrate = ATH9K_CLOCK_RATE_CCK; - else if (conf->channel->band == IEEE80211_BAND_2GHZ) + else if (IS_CHAN_2GHZ(chan)) clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM; else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK) clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM; else clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM; - if (conf_is_ht40(conf)) - clockrate *= 2; + if (chan) { + if (IS_CHAN_HT40(chan)) + clockrate *= 2; + if (IS_CHAN_HALF_RATE(chan)) + clockrate /= 2; + if (IS_CHAN_QUARTER_RATE(chan)) + clockrate /= 4; + } common->clockrate = clockrate; } @@ -122,7 +85,7 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) udelay(AH_TIME_QUANTUM); } - ath_dbg(ath9k_hw_common(ah), ATH_DBG_ANY, + ath_dbg(ath9k_hw_common(ah), ANY, "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", timeout, reg, REG_READ(ah, reg), mask, val); @@ -130,6 +93,33 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) } EXPORT_SYMBOL(ath9k_hw_wait); +void ath9k_hw_synth_delay(struct ath_hw *ah, struct ath9k_channel *chan, + int hw_delay) +{ + hw_delay /= 10; + + if (IS_CHAN_HALF_RATE(chan)) + hw_delay *= 2; + else if (IS_CHAN_QUARTER_RATE(chan)) + hw_delay *= 4; + + udelay(hw_delay + BASE_ACTIVATE_DELAY); +} + +void ath9k_hw_write_array(struct ath_hw *ah, const struct ar5416IniArray *array, + int column, unsigned int *writecnt) +{ + int r; + + ENABLE_REGWRITE_BUFFER(ah); + for (r = 0; r < array->ia_rows; r++) { + REG_WRITE(ah, INI_RA(array, r, 0), + INI_RA(array, r, column)); + DO_DELAY(*writecnt); + } + REGWRITE_BUFFER_FLUSH(ah); +} + u32 ath9k_hw_reverse_bits(u32 val, u32 n) { u32 retval; @@ -142,25 +132,6 @@ u32 ath9k_hw_reverse_bits(u32 val, u32 n) return retval; } -bool ath9k_get_channel_edges(struct ath_hw *ah, - u16 flags, u16 *low, - u16 *high) -{ - struct ath9k_hw_capabilities *pCap = &ah->caps; - - if (flags & CHANNEL_5GHZ) { - *low = pCap->low_5ghz_chan; - *high = pCap->high_5ghz_chan; - return true; - } - if ((flags & CHANNEL_2GHZ)) { - *low = pCap->low_2ghz_chan; - *high = pCap->high_2ghz_chan; - return true; - } - return false; -} - u16 ath9k_hw_computetxtime(struct ath_hw *ah, u8 phy, int kbps, u32 frameLen, u16 rateix, @@ -226,8 +197,7 @@ void ath9k_hw_get_channel_centers(struct ath_hw *ah, return; } - if ((chan->chanmode == CHANNEL_A_HT40PLUS) || - (chan->chanmode == CHANNEL_G_HT40PLUS)) { + if (IS_CHAN_HT40PLUS(chan)) { centers->synth_center = chan->channel + HT40_CHANNEL_CENTER_SHIFT; extoff = 1; @@ -252,6 +222,34 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah) { u32 val; + switch (ah->hw_version.devid) { + case AR5416_AR9100_DEVID: + ah->hw_version.macVersion = AR_SREV_VERSION_9100; + break; + case AR9300_DEVID_AR9330: + ah->hw_version.macVersion = AR_SREV_VERSION_9330; + if (ah->get_mac_revision) { + ah->hw_version.macRev = ah->get_mac_revision(); + } else { + val = REG_READ(ah, AR_SREV); + ah->hw_version.macRev = MS(val, AR_SREV_REVISION2); + } + return; + case AR9300_DEVID_AR9340: + ah->hw_version.macVersion = AR_SREV_VERSION_9340; + val = REG_READ(ah, AR_SREV); + ah->hw_version.macRev = MS(val, AR_SREV_REVISION2); + return; + case AR9300_DEVID_QCA955X: + ah->hw_version.macVersion = AR_SREV_VERSION_9550; + return; + case AR9300_DEVID_AR953X: + ah->hw_version.macVersion = AR_SREV_VERSION_9531; + if (ah->get_mac_revision) + ah->hw_version.macRev = ah->get_mac_revision(); + return; + } + val = REG_READ(ah, AR_SREV) & AR_SREV_ID; if (val == 0xFF) { @@ -259,7 +257,12 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah) ah->hw_version.macVersion = (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S; ah->hw_version.macRev = MS(val, AR_SREV_REVISION2); - ah->is_pciexpress = (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1; + + if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) + ah->is_pciexpress = true; + else + ah->is_pciexpress = (val & + AR_SREV_TYPE2_HOST_MODE) ? 0 : 1; } else { if (!AR_SREV_9100(ah)) ah->hw_version.macVersion = MS(val, AR_SREV_VERSION); @@ -346,34 +349,22 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) static void ath9k_hw_init_config(struct ath_hw *ah) { - int i; + struct ath_common *common = ath9k_hw_common(ah); - ah->config.dma_beacon_response_time = 2; - ah->config.sw_beacon_response_time = 10; - ah->config.additional_swba_backoff = 0; - ah->config.ack_6mb = 0x0; + ah->config.dma_beacon_response_time = 1; + ah->config.sw_beacon_response_time = 6; ah->config.cwm_ignore_extcca = 0; - ah->config.pcie_powersave_enable = 0; - ah->config.pcie_clock_req = 0; - ah->config.pcie_waen = 0; ah->config.analog_shiftreg = 1; - ah->config.enable_ani = true; - - for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { - ah->config.spurchans[i][0] = AR_NO_SPUR; - ah->config.spurchans[i][1] = AR_NO_SPUR; - } - - if (ah->hw_version.devid != AR2427_DEVID_PCIE) - ah->config.ht_enable = 1; - else - ah->config.ht_enable = 0; - - /* PAPRD needs some more work to be enabled */ - ah->config.paprd_disable = 1; ah->config.rx_intr_mitigation = true; - ah->config.pcieSerDesWrite = true; + + if (AR_SREV_9300_20_OR_LATER(ah)) { + ah->config.rimt_last = 500; + ah->config.rimt_first = 2000; + } else { + ah->config.rimt_last = 250; + ah->config.rimt_first = 700; + } /* * We need this for PCI devices only (Cardbus, PCI, miniPCI) @@ -393,6 +384,24 @@ static void ath9k_hw_init_config(struct ath_hw *ah) */ if (num_possible_cpus() > 1) 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) || AR_SREV_9287(ah)) && + !ah->is_pciexpress)) { + ah->config.serialize_regmode = SER_REG_MODE_ON; + } else { + ah->config.serialize_regmode = SER_REG_MODE_OFF; + } + } + + ath_dbg(common, RESET, "serialize_regmode is %d\n", + ah->config.serialize_regmode); + + if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) + ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD >> 1; + else + ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD; } static void ath9k_hw_init_defaults(struct ath_hw *ah) @@ -401,19 +410,28 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) regulatory->country_code = CTRY_DEFAULT; regulatory->power_limit = MAX_RATE_POWER; - regulatory->tp_scale = ATH9K_TP_SCALE_MAX; ah->hw_version.magic = AR5416_MAGIC; ah->hw_version.subvendorid = 0; - ah->atim_window = 0; - ah->sta_id1_defaults = - AR_STA_ID1_CRPT_MIC_ENABLE | - AR_STA_ID1_MCAST_KSRCH; - ah->enable_32kHz_clock = DONT_USE_32KHZ; - ah->slottime = 20; + ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE | + AR_STA_ID1_MCAST_KSRCH; + if (AR_SREV_9100(ah)) + ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX; + + ah->slottime = ATH9K_SLOT_TIME_9; ah->globaltxtimeout = (u32) -1; ah->power_mode = ATH9K_PM_UNDEFINED; + ah->htc_reset_init = true; + + ah->ani_function = ATH9K_ANI_ALL; + if (!AR_SREV_9300_20_OR_LATER(ah)) + ah->ani_function &= ~ATH9K_ANI_MRC_CCK; + + if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) + ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S); + else + ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); } static int ath9k_hw_init_macaddr(struct ath_hw *ah) @@ -457,33 +475,34 @@ static int ath9k_hw_post_init(struct ath_hw *ah) if (ecode != 0) return ecode; - ath_dbg(ath9k_hw_common(ah), ATH_DBG_CONFIG, - "Eeprom VER: %d, REV: %d\n", + ath_dbg(ath9k_hw_common(ah), CONFIG, "Eeprom VER: %d, REV: %d\n", ah->eep_ops->get_eeprom_ver(ah), ah->eep_ops->get_eeprom_rev(ah)); - ecode = ath9k_hw_rf_alloc_ext_banks(ah); - if (ecode) { - ath_err(ath9k_hw_common(ah), - "Failed allocating banks for external radio\n"); - ath9k_hw_rf_free_ext_banks(ah); - return ecode; - } + ath9k_hw_ani_init(ah); - if (!AR_SREV_9100(ah)) { - ath9k_hw_ani_setup(ah); - ath9k_hw_ani_init(ah); + /* + * EEPROM needs to be initialized before we do this. + * This is required for regulatory compliance. + */ + if (AR_SREV_9300_20_OR_LATER(ah)) { + u16 regdmn = ah->eep_ops->get_eeprom(ah, EEP_REG_0); + if ((regdmn & 0xF0) == CTL_FCC) { + ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_2GHZ; + ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_5GHZ; + } } return 0; } -static void ath9k_hw_attach_ops(struct ath_hw *ah) +static int ath9k_hw_attach_ops(struct ath_hw *ah) { - if (AR_SREV_9300_20_OR_LATER(ah)) - ar9003_hw_attach_ops(ah); - else - ar9002_hw_attach_ops(ah); + if (!AR_SREV_9300_20_OR_LATER(ah)) + return ar9002_hw_attach_ops(ah); + + ar9003_hw_attach_ops(ah); + return 0; } /* Called for all hardware families */ @@ -492,43 +511,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); int r = 0; - if (ah->hw_version.devid == AR5416_AR9100_DEVID) - ah->hw_version.macVersion = AR_SREV_VERSION_9100; - - if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { - ath_err(common, "Couldn't reset chip\n"); - return -EIO; - } - - ath9k_hw_init_defaults(ah); - ath9k_hw_init_config(ah); - - ath9k_hw_attach_ops(ah); - - if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { - ath_err(common, "Couldn't wakeup chip\n"); - return -EIO; - } - - if (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)) { - ah->config.serialize_regmode = - SER_REG_MODE_ON; - } else { - ah->config.serialize_regmode = - SER_REG_MODE_OFF; - } - } - - ath_dbg(common, ATH_DBG_RESET, "serialize_regmode is %d\n", - ah->config.serialize_regmode); - - if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) - ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD >> 1; - else - ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD; + ath9k_hw_read_revisions(ah); switch (ah->hw_version.macVersion) { case AR_SREV_VERSION_5416_PCI: @@ -540,7 +523,13 @@ static int __ath9k_hw_init(struct ath_hw *ah) case AR_SREV_VERSION_9287: case AR_SREV_VERSION_9271: case AR_SREV_VERSION_9300: + case AR_SREV_VERSION_9330: case AR_SREV_VERSION_9485: + case AR_SREV_VERSION_9340: + case AR_SREV_VERSION_9462: + case AR_SREV_VERSION_9550: + case AR_SREV_VERSION_9565: + case AR_SREV_VERSION_9531: break; default: ath_err(common, @@ -549,36 +538,48 @@ static int __ath9k_hw_init(struct ath_hw *ah) return -EOPNOTSUPP; } - if (AR_SREV_9271(ah) || AR_SREV_9100(ah)) - ah->is_pciexpress = false; - - ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); - ath9k_hw_init_cal_settings(ah); - - ah->ani_function = ATH9K_ANI_ALL; - if (AR_SREV_9280_20_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah)) - ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; - if (!AR_SREV_9300_20_OR_LATER(ah)) - ah->ani_function &= ~ATH9K_ANI_MRC_CCK; - - ath9k_hw_init_mode_regs(ah); - /* * Read back AR_WA into a permanent copy and set bits 14 and 17. * We need to do this to avoid RMW of this register. We cannot * read the reg when chip is asleep. */ - ah->WARegVal = REG_READ(ah, AR_WA); - ah->WARegVal |= (AR_WA_D3_L1_DISABLE | - AR_WA_ASPM_TIMER_BASED_DISABLE); + if (AR_SREV_9300_20_OR_LATER(ah)) { + ah->WARegVal = REG_READ(ah, AR_WA); + ah->WARegVal |= (AR_WA_D3_L1_DISABLE | + AR_WA_ASPM_TIMER_BASED_DISABLE); + } - if (ah->is_pciexpress) - ath9k_hw_configpcipowersave(ah, 0, 0); - else - ath9k_hw_disablepcie(ah); + if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { + ath_err(common, "Couldn't reset chip\n"); + return -EIO; + } - if (!AR_SREV_9300_20_OR_LATER(ah)) - ar9002_hw_cck_chan14_spread(ah); + if (AR_SREV_9565(ah)) { + ah->WARegVal |= AR_WA_BIT22; + REG_WRITE(ah, AR_WA, ah->WARegVal); + } + + ath9k_hw_init_defaults(ah); + ath9k_hw_init_config(ah); + + r = ath9k_hw_attach_ops(ah); + if (r) + return r; + + if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { + ath_err(common, "Couldn't wakeup chip\n"); + return -EIO; + } + + if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah) || + AR_SREV_9330(ah) || AR_SREV_9550(ah)) + ah->is_pciexpress = false; + + ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); + ath9k_hw_init_cal_settings(ah); + + if (!ah->is_pciexpress) + ath9k_hw_disablepcie(ah); r = ath9k_hw_post_init(ah); if (r) @@ -595,12 +596,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) return r; } - if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) - ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S); - else - ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); - - ah->bb_watchdog_timeout_ms = 25; + ath9k_hw_init_hang_checks(ah); common->state = ATH_HW_INITIALIZED; @@ -612,7 +608,7 @@ int ath9k_hw_init(struct ath_hw *ah) int ret; struct ath_common *common = ath9k_hw_common(ah); - /* These are all the AR5008/AR9001/AR9002 hardware family of chipsets */ + /* These are all the AR5008/AR9001/AR9002/AR9003 hardware family of chipsets */ switch (ah->hw_version.devid) { case AR5416_DEVID_PCI: case AR5416_DEVID_PCIE: @@ -626,6 +622,14 @@ int ath9k_hw_init(struct ath_hw *ah) case AR2427_DEVID_PCIE: case AR9300_DEVID_PCIE: case AR9300_DEVID_AR9485_PCIE: + case AR9300_DEVID_AR9330: + case AR9300_DEVID_AR9340: + case AR9300_DEVID_QCA955X: + case AR9300_DEVID_AR9580: + case AR9300_DEVID_AR9462: + case AR9485_DEVID_AR1111: + case AR9300_DEVID_AR9565: + case AR9300_DEVID_AR953X: break; default: if (common->bus_ops->ath_bus_type == ATH_USB) @@ -668,18 +672,183 @@ static void ath9k_hw_init_qos(struct ath_hw *ah) REGWRITE_BUFFER_FLUSH(ah); } +u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + int i = 0; + + REG_CLR_BIT(ah, PLL3, PLL3_DO_MEAS_MASK); + udelay(100); + REG_SET_BIT(ah, PLL3, PLL3_DO_MEAS_MASK); + + while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) { + + udelay(100); + + if (WARN_ON_ONCE(i >= 100)) { + ath_err(common, "PLL4 meaurement not done\n"); + break; + } + + i++; + } + + return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3; +} +EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc); + static void ath9k_hw_init_pll(struct ath_hw *ah, struct ath9k_channel *chan) { u32 pll; - if (AR_SREV_9485(ah)) - REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666); + if (AR_SREV_9485(ah) || AR_SREV_9565(ah)) { + /* program BB PLL ki and kd value, ki=0x4, kd=0x40 */ + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, + AR_CH0_BB_DPLL2_PLL_PWD, 0x1); + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, + AR_CH0_DPLL2_KD, 0x40); + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, + AR_CH0_DPLL2_KI, 0x4); + + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, + AR_CH0_BB_DPLL1_REFDIV, 0x5); + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, + AR_CH0_BB_DPLL1_NINI, 0x58); + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, + AR_CH0_BB_DPLL1_NFRAC, 0x0); + + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, + AR_CH0_BB_DPLL2_OUTDIV, 0x1); + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, + AR_CH0_BB_DPLL2_LOCAL_PLL, 0x1); + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, + AR_CH0_BB_DPLL2_EN_NEGTRIG, 0x1); + + /* program BB PLL phase_shift to 0x6 */ + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, + AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x6); + + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, + AR_CH0_BB_DPLL2_PLL_PWD, 0x0); + udelay(1000); + } else if (AR_SREV_9330(ah)) { + u32 ddr_dpll2, pll_control2, kd; + + if (ah->is_clk_25mhz) { + ddr_dpll2 = 0x18e82f01; + pll_control2 = 0xe04a3d; + kd = 0x1d; + } else { + ddr_dpll2 = 0x19e82f01; + pll_control2 = 0x886666; + kd = 0x3d; + } + + /* program DDR PLL ki and kd value */ + REG_WRITE(ah, AR_CH0_DDR_DPLL2, ddr_dpll2); - pll = ath9k_hw_compute_pll_control(ah, chan); + /* program DDR PLL phase_shift */ + REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3, + AR_CH0_DPLL3_PHASE_SHIFT, 0x1); + + REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); + udelay(1000); + + /* program refdiv, nint, frac to RTC register */ + REG_WRITE(ah, AR_RTC_PLL_CONTROL2, pll_control2); + + /* program BB PLL kd and ki value */ + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KD, kd); + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KI, 0x06); + + /* program BB PLL phase_shift */ + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, + AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x1); + } else if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) { + u32 regval, pll2_divint, pll2_divfrac, refdiv; + + REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); + udelay(1000); + + REG_SET_BIT(ah, AR_PHY_PLL_MODE, 0x1 << 16); + udelay(100); + + if (ah->is_clk_25mhz) { + if (AR_SREV_9531(ah)) { + pll2_divint = 0x1c; + pll2_divfrac = 0xa3d2; + refdiv = 1; + } else { + pll2_divint = 0x54; + pll2_divfrac = 0x1eb85; + refdiv = 3; + } + } else { + if (AR_SREV_9340(ah)) { + pll2_divint = 88; + pll2_divfrac = 0; + refdiv = 5; + } else { + pll2_divint = 0x11; + pll2_divfrac = 0x26666; + refdiv = 1; + } + } + + regval = REG_READ(ah, AR_PHY_PLL_MODE); + if (AR_SREV_9531(ah)) + regval |= (0x1 << 22); + else + regval |= (0x1 << 16); + REG_WRITE(ah, AR_PHY_PLL_MODE, regval); + udelay(100); + + REG_WRITE(ah, AR_PHY_PLL_CONTROL, (refdiv << 27) | + (pll2_divint << 18) | pll2_divfrac); + udelay(100); + + regval = REG_READ(ah, AR_PHY_PLL_MODE); + if (AR_SREV_9340(ah)) + regval = (regval & 0x80071fff) | + (0x1 << 30) | + (0x1 << 13) | + (0x4 << 26) | + (0x18 << 19); + else if (AR_SREV_9531(ah)) + regval = (regval & 0x01c00fff) | + (0x1 << 31) | + (0x2 << 29) | + (0xa << 25) | + (0x1 << 19) | + (0x6 << 12); + else + regval = (regval & 0x80071fff) | + (0x3 << 30) | + (0x1 << 13) | + (0x4 << 26) | + (0x60 << 19); + REG_WRITE(ah, AR_PHY_PLL_MODE, regval); + + if (AR_SREV_9531(ah)) + REG_WRITE(ah, AR_PHY_PLL_MODE, + REG_READ(ah, AR_PHY_PLL_MODE) & 0xffbfffff); + else + REG_WRITE(ah, AR_PHY_PLL_MODE, + REG_READ(ah, AR_PHY_PLL_MODE) & 0xfffeffff); + + udelay(1000); + } + pll = ath9k_hw_compute_pll_control(ah, chan); + if (AR_SREV_9565(ah)) + pll |= 0x40000; REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); + if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) || + AR_SREV_9550(ah)) + udelay(1000); + /* Switch the core clock for ar9271 to 117Mhz */ if (AR_SREV_9271(ah)) { udelay(500); @@ -689,17 +858,34 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, udelay(RTC_PLL_SETTLE_DELAY); REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); + + if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) { + if (ah->is_clk_25mhz) { + REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1); + REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7); + REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae); + } else { + REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1); + REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400); + REG_WRITE(ah, AR_SLP32_INC, 0x0001e800); + } + udelay(100); + } } static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, enum nl80211_iftype opmode) { + u32 sync_default = AR_INTR_SYNC_DEFAULT; u32 imr_reg = AR_IMR_TXERR | AR_IMR_TXURN | AR_IMR_RXERR | AR_IMR_RXORN | AR_IMR_BCNMISC; + if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) + sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; + if (AR_SREV_9300_20_OR_LATER(ah)) { imr_reg |= AR_IMR_RXOK_HP; if (ah->config.rx_intr_mitigation) @@ -719,9 +905,6 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, else imr_reg |= AR_IMR_TXOK; - if (opmode == NL80211_IFTYPE_AP) - imr_reg |= AR_IMR_MIB; - ENABLE_REGWRITE_BUFFER(ah); REG_WRITE(ah, AR_IMR, imr_reg); @@ -730,7 +913,7 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, if (!AR_SREV_9100(ah)) { REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF); - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT); + REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default); REG_WRITE(ah, AR_INTR_SYNC_MASK, 0); } @@ -744,6 +927,13 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, } } +static void ath9k_hw_set_sifs_time(struct ath_hw *ah, u32 us) +{ + u32 val = ath9k_hw_mac_to_clks(ah, us - 2); + val = min(val, (u32) 0xFFFF); + REG_WRITE(ah, AR_D_GBL_IFS_SIFS, val); +} + static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us) { u32 val = ath9k_hw_mac_to_clks(ah, us); @@ -768,8 +958,8 @@ static void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) { if (tu > 0xFFFF) { - ath_dbg(ath9k_hw_common(ah), ATH_DBG_XMIT, - "bad global tx timeout %u\n", tu); + ath_dbg(ath9k_hw_common(ah), XMIT, "bad global tx timeout %u\n", + tu); ah->globaltxtimeout = (u32) -1; return false; } else { @@ -781,42 +971,101 @@ static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) void ath9k_hw_init_global_settings(struct ath_hw *ah) { - struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; - int acktimeout; + struct ath_common *common = ath9k_hw_common(ah); + const struct ath9k_channel *chan = ah->curchan; + int acktimeout, ctstimeout, ack_offset = 0; int slottime; int sifstime; + int rx_lat = 0, tx_lat = 0, eifs = 0; + u32 reg; - ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n", + ath_dbg(ath9k_hw_common(ah), RESET, "ah->misc_mode 0x%x\n", ah->misc_mode); + if (!chan) + return; + if (ah->misc_mode != 0) - REG_WRITE(ah, AR_PCU_MISC, - REG_READ(ah, AR_PCU_MISC) | ah->misc_mode); + REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode); + + if (IS_CHAN_A_FAST_CLOCK(ah, chan)) + rx_lat = 41; + else + rx_lat = 37; + tx_lat = 54; - if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ) + if (IS_CHAN_5GHZ(chan)) sifstime = 16; else sifstime = 10; + if (IS_CHAN_HALF_RATE(chan)) { + eifs = 175; + rx_lat *= 2; + tx_lat *= 2; + if (IS_CHAN_A_FAST_CLOCK(ah, chan)) + tx_lat += 11; + + sifstime = 32; + ack_offset = 16; + slottime = 13; + } else if (IS_CHAN_QUARTER_RATE(chan)) { + eifs = 340; + rx_lat = (rx_lat * 4) - 1; + tx_lat *= 4; + if (IS_CHAN_A_FAST_CLOCK(ah, chan)) + tx_lat += 22; + + sifstime = 64; + ack_offset = 32; + slottime = 21; + } else { + if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) { + eifs = AR_D_GBL_IFS_EIFS_ASYNC_FIFO; + reg = AR_USEC_ASYNC_FIFO; + } else { + eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/ + common->clockrate; + reg = REG_READ(ah, AR_USEC); + } + rx_lat = MS(reg, AR_USEC_RX_LAT); + tx_lat = MS(reg, AR_USEC_TX_LAT); + + slottime = ah->slottime; + } + /* As defined by IEEE 802.11-2007 17.3.8.6 */ - slottime = ah->slottime + 3 * ah->coverage_class; - acktimeout = slottime + sifstime; + slottime += 3 * ah->coverage_class; + acktimeout = slottime + sifstime + ack_offset; + ctstimeout = acktimeout; /* * Workaround for early ACK timeouts, add an offset to match the - * initval's 64us ack timeout value. + * initval's 64us ack timeout value. Use 48us for the CTS timeout. * This was initially only meant to work around an issue with delayed * BA frames in some implementations, but it has been found to fix ACK * timeout issues in other cases as well. */ - if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ) + if (IS_CHAN_2GHZ(chan) && + !IS_CHAN_HALF_RATE(chan) && !IS_CHAN_QUARTER_RATE(chan)) { acktimeout += 64 - sifstime - ah->slottime; + ctstimeout += 48 - sifstime - ah->slottime; + } - ath9k_hw_setslottime(ah, ah->slottime); + ath9k_hw_set_sifs_time(ah, sifstime); + ath9k_hw_setslottime(ah, slottime); ath9k_hw_set_ack_timeout(ah, acktimeout); - ath9k_hw_set_cts_timeout(ah, acktimeout); + ath9k_hw_set_cts_timeout(ah, ctstimeout); if (ah->globaltxtimeout != (u32) -1) ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout); + + REG_WRITE(ah, AR_D_GBL_IFS_EIFS, ath9k_hw_mac_to_clks(ah, eifs)); + REG_RMW(ah, AR_USEC, + (common->clockrate - 1) | + SM(rx_lat, AR_USEC_RX_LAT) | + SM(tx_lat, AR_USEC_TX_LAT), + AR_USEC_TX_LAT | AR_USEC_RX_LAT | AR_USEC_USEC); + } EXPORT_SYMBOL(ath9k_hw_init_global_settings); @@ -825,12 +1074,9 @@ void ath9k_hw_deinit(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); if (common->state < ATH_HW_INITIALIZED) - goto free_hw; + return; ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); - -free_hw: - ath9k_hw_rf_free_ext_banks(ah); } EXPORT_SYMBOL(ath9k_hw_deinit); @@ -842,9 +1088,7 @@ u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan) { u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band); - if (IS_CHAN_B(chan)) - ctl |= CTL_11B; - else if (IS_CHAN_G(chan)) + if (IS_CHAN_2GHZ(chan)) ctl |= CTL_11G; else ctl |= CTL_11A; @@ -859,23 +1103,20 @@ u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan) static inline void ath9k_hw_set_dma(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); - u32 regval; + int txbuf_size; ENABLE_REGWRITE_BUFFER(ah); /* * set AHB_MODE not to do cacheline prefetches */ - if (!AR_SREV_9300_20_OR_LATER(ah)) { - regval = REG_READ(ah, AR_AHB_MODE); - REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN); - } + if (!AR_SREV_9300_20_OR_LATER(ah)) + REG_SET_BIT(ah, AR_AHB_MODE, AR_AHB_PREFETCH_RD_EN); /* * let mac dma reads be in 128 byte chunks */ - regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK; - REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B); + REG_RMW(ah, AR_TXCFG, AR_TXCFG_DMASZ_128B, AR_TXCFG_DMASZ_MASK); REGWRITE_BUFFER_FLUSH(ah); @@ -892,8 +1133,7 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) /* * let mac dma writes be in 128 byte chunks */ - regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK; - REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B); + REG_RMW(ah, AR_RXCFG, AR_RXCFG_DMASZ_128B, AR_RXCFG_DMASZ_MASK); /* * Setup receive FIFO threshold to hold off TX activities @@ -917,13 +1157,17 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) * So set the usable tx buf size also to half to * avoid data/delimiter underruns */ - REG_WRITE(ah, AR_PCU_TXBUF_CTRL, - AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE); - } else if (!AR_SREV_9271(ah)) { - REG_WRITE(ah, AR_PCU_TXBUF_CTRL, - AR_PCU_TXBUF_CTRL_USABLE_SIZE); + txbuf_size = AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE; + } else if (AR_SREV_9340_13_OR_LATER(ah)) { + /* Uses fewer entries for AR934x v1.3+ to prevent rx overruns */ + txbuf_size = AR_9340_PCU_TXBUF_CTRL_USABLE_SIZE; + } else { + txbuf_size = AR_PCU_TXBUF_CTRL_USABLE_SIZE; } + if (!AR_SREV_9271(ah)) + REG_WRITE(ah, AR_PCU_TXBUF_CTRL, txbuf_size); + REGWRITE_BUFFER_FLUSH(ah); if (AR_SREV_9300_20_OR_LATER(ah)) @@ -932,30 +1176,27 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) { - u32 val; + u32 mask = AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC; + u32 set = AR_STA_ID1_KSRCH_MODE; - val = REG_READ(ah, AR_STA_ID1); - val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC); switch (opmode) { - case NL80211_IFTYPE_AP: - REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP - | AR_STA_ID1_KSRCH_MODE); - REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); - break; case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC - | AR_STA_ID1_KSRCH_MODE); + set |= AR_STA_ID1_ADHOC; REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); break; + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + set |= AR_STA_ID1_STA_AP; + /* fall through */ case NL80211_IFTYPE_STATION: - REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE); + REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); break; default: - if (ah->is_monitoring) - REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE); + if (!ah->is_monitoring) + set = 0; break; } + REG_RMW(ah, AR_STA_ID1, set, mask); } void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, @@ -975,16 +1216,50 @@ void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, *coef_exponent = coef_exp - 16; } +/* AR9330 WAR: + * call external reset function to reset WMAC if: + * - doing a cold reset + * - we have pending frames in the TX queues. + */ +static bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type) +{ + int i, npend = 0; + + for (i = 0; i < AR_NUM_QCU; i++) { + npend = ath9k_hw_numtxpending(ah, i); + if (npend) + break; + } + + if (ah->external_reset && + (npend || type == ATH9K_RESET_COLD)) { + int reset_err = 0; + + ath_dbg(ath9k_hw_common(ah), RESET, + "reset MAC via external reset\n"); + + reset_err = ah->external_reset(); + if (reset_err) { + ath_err(ath9k_hw_common(ah), + "External reset failed, err=%d\n", + reset_err); + return false; + } + + REG_WRITE(ah, AR_RTC_RESET, 1); + } + + return true; +} + static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) { u32 rst_flags; u32 tmpReg; if (AR_SREV_9100(ah)) { - u32 val = REG_READ(ah, AR_RTC_DERIVED_CLK); - val &= ~AR_RTC_DERIVED_CLK_PERIOD; - val |= SM(1, AR_RTC_DERIVED_CLK_PERIOD); - REG_WRITE(ah, AR_RTC_DERIVED_CLK, val); + REG_RMW_FIELD(ah, AR_RTC_DERIVED_CLK, + AR_RTC_DERIVED_CLK_PERIOD, 1); (void)REG_READ(ah, AR_RTC_DERIVED_CLK); } @@ -1003,9 +1278,13 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET; } else { tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE); - if (tmpReg & - (AR_INTR_SYNC_LOCAL_TIMEOUT | - AR_INTR_SYNC_RADM_CPL_TIMEOUT)) { + if (AR_SREV_9340(ah)) + tmpReg &= AR9340_INTR_SYNC_LOCAL_TIMEOUT; + else + tmpReg &= AR_INTR_SYNC_LOCAL_TIMEOUT | + AR_INTR_SYNC_RADM_CPL_TIMEOUT; + + if (tmpReg) { u32 val; REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); @@ -1022,16 +1301,28 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) rst_flags |= AR_RTC_RC_MAC_COLD; } + if (AR_SREV_9330(ah)) { + if (!ath9k_hw_ar9330_reset_war(ah, type)) + return false; + } + + if (ath9k_hw_mci_is_enabled(ah)) + ar9003_mci_check_gpm_offset(ah); + REG_WRITE(ah, AR_RTC_RC, rst_flags); REGWRITE_BUFFER_FLUSH(ah); - udelay(50); + if (AR_SREV_9300_20_OR_LATER(ah)) + udelay(50); + else if (AR_SREV_9100(ah)) + mdelay(10); + else + udelay(100); REG_WRITE(ah, AR_RTC_RC, 0); if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) { - ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, - "RTC stuck in MAC reset\n"); + ath_dbg(ath9k_hw_common(ah), RESET, "RTC stuck in MAC reset\n"); return false; } @@ -1060,12 +1351,10 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) REG_WRITE(ah, AR_RC, AR_RC_AHB); REG_WRITE(ah, AR_RTC_RESET, 0); - udelay(2); REGWRITE_BUFFER_FLUSH(ah); - if (!AR_SREV_9300_20_OR_LATER(ah)) - udelay(2); + udelay(2); if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah)) REG_WRITE(ah, AR_RC, 0); @@ -1077,18 +1366,17 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) AR_RTC_STATUS_M, AR_RTC_STATUS_ON, AH_WAIT_TIMEOUT)) { - ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, - "RTC not waking up\n"); + ath_dbg(ath9k_hw_common(ah), RESET, "RTC not waking up\n"); return false; } - ath9k_hw_read_revisions(ah); - return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM); } static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) { + bool ret = false; + if (AR_SREV_9300_20_OR_LATER(ah)) { REG_WRITE(ah, AR_WA, ah->WARegVal); udelay(10); @@ -1097,32 +1385,51 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); + if (!ah->reset_power_on) + type = ATH9K_RESET_POWER_ON; + switch (type) { case ATH9K_RESET_POWER_ON: - return ath9k_hw_set_reset_power_on(ah); + ret = ath9k_hw_set_reset_power_on(ah); + if (ret) + ah->reset_power_on = true; + break; case ATH9K_RESET_WARM: case ATH9K_RESET_COLD: - return ath9k_hw_set_reset(ah, type); + ret = ath9k_hw_set_reset(ah, type); + break; default: - return false; + break; } + + return ret; } 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; + } else if (ah->chip_fullsleep || REG_READ(ah, AR_Q_TXE) || + (REG_READ(ah, AR_CR) & AR_CR_RXE)) + reset_type = ATH9K_RESET_COLD; + + if (!ath9k_hw_set_reset_reg(ah, reset_type)) return false; if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) return false; ah->chip_fullsleep = false; + + if (AR_SREV_9330(ah)) + ar9003_hw_internal_regulator_apply(ah); ath9k_hw_init_pll(ah, chan); - ath9k_hw_set_rfmode(ah, chan); return true; } @@ -1130,15 +1437,22 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah, static bool ath9k_hw_channel_change(struct ath_hw *ah, struct ath9k_channel *chan) { - struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ath_common *common = ath9k_hw_common(ah); - struct ieee80211_channel *channel = chan->chan; + struct ath9k_hw_capabilities *pCap = &ah->caps; + bool band_switch = false, mode_diff = false; + u8 ini_reloaded = 0; u32 qnum; int r; + if (pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) { + u32 flags_diff = chan->channelFlags ^ ah->curchan->channelFlags; + band_switch = !!(flags_diff & CHANNEL_5GHZ); + mode_diff = !!(flags_diff & ~CHANNEL_HT); + } + for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { if (ath9k_hw_numtxpending(ah, qnum)) { - ath_dbg(common, ATH_DBG_QUEUE, + ath_dbg(common, QUEUE, "Transmit frames pending on queue %d\n", qnum); return false; } @@ -1149,6 +1463,19 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, return false; } + if (band_switch || mode_diff) { + ath9k_hw_mark_phy_inactive(ah); + udelay(5); + + if (band_switch) + ath9k_hw_init_pll(ah, chan); + + if (ath9k_hw_fast_chan_change(ah, chan, &ini_reloaded)) { + ath_err(common, "Failed to do fast channel change\n"); + return false; + } + } + ath9k_hw_set_channel_regs(ah, chan); r = ath9k_hw_rf_set_freq(ah, chan); @@ -1157,35 +1484,72 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, return false; } ath9k_hw_set_clockrate(ah); + ath9k_hw_apply_txpower(ah, chan, false); - ah->eep_ops->set_txpower(ah, chan, - ath9k_regd_get_ctl(regulatory, chan), - channel->max_antenna_gain * 2, - channel->max_power * 2, - min((u32) MAX_RATE_POWER, - (u32) regulatory->power_limit), false); + ath9k_hw_set_delta_slope(ah, chan); + ath9k_hw_spur_mitigate_freq(ah, chan); - ath9k_hw_rfbus_done(ah); + if (band_switch || ini_reloaded) + ah->eep_ops->set_board_values(ah, chan); - if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) - ath9k_hw_set_delta_slope(ah, chan); + ath9k_hw_init_bb(ah, chan); + ath9k_hw_rfbus_done(ah); - ath9k_hw_spur_mitigate_freq(ah, chan); + if (band_switch || ini_reloaded) { + ah->ah_flags |= AH_FASTCC; + ath9k_hw_init_cal(ah, chan); + ah->ah_flags &= ~AH_FASTCC; + } return true; } +static void ath9k_hw_apply_gpio_override(struct ath_hw *ah) +{ + u32 gpio_mask = ah->gpio_mask; + int i; + + for (i = 0; gpio_mask; i++, gpio_mask >>= 1) { + if (!(gpio_mask & 1)) + continue; + + ath9k_hw_cfg_output(ah, i, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + ath9k_hw_set_gpio(ah, i, !!(ah->gpio_val & BIT(i))); + } +} + +void ath9k_hw_check_nav(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + u32 val; + + val = REG_READ(ah, AR_NAV); + if (val != 0xdeadbeef && val > 0x7fff) { + ath_dbg(common, BSTUCK, "Abnormal NAV: 0x%x\n", val); + REG_WRITE(ah, AR_NAV, 0); + } +} +EXPORT_SYMBOL(ath9k_hw_check_nav); + bool ath9k_hw_check_alive(struct ath_hw *ah) { int count = 50; - u32 reg; + u32 reg, last_val; + + if (AR_SREV_9300(ah)) + return !ath9k_hw_detect_mac_hang(ah); if (AR_SREV_9285_12_OR_LATER(ah)) return true; + last_val = REG_READ(ah, AR_OBS_BUS_1); do { reg = REG_READ(ah, AR_OBS_BUS_1); + if (reg != last_val) + return true; + udelay(1); + last_val = reg; if ((reg & 0x7E7FFFEF) == 0x00702400) continue; @@ -1203,72 +1567,225 @@ bool ath9k_hw_check_alive(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_check_alive); +static void ath9k_hw_init_mfp(struct ath_hw *ah) +{ + /* Setup MFP options for CCMP */ + if (AR_SREV_9280_20_OR_LATER(ah)) { + /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt + * frames when constructing CCMP AAD. */ + REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, + 0xc7ff); + ah->sw_mgmt_crypto = false; + } else if (AR_SREV_9160_10_OR_LATER(ah)) { + /* Disable hardware crypto for management frames */ + REG_CLR_BIT(ah, AR_PCU_MISC_MODE2, + AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); + REG_SET_BIT(ah, AR_PCU_MISC_MODE2, + AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); + ah->sw_mgmt_crypto = true; + } else { + ah->sw_mgmt_crypto = true; + } +} + +static void ath9k_hw_reset_opmode(struct ath_hw *ah, + u32 macStaId1, u32 saveDefAntenna) +{ + struct ath_common *common = ath9k_hw_common(ah); + + ENABLE_REGWRITE_BUFFER(ah); + + REG_RMW(ah, AR_STA_ID1, macStaId1 + | AR_STA_ID1_RTS_USE_DEF + | ah->sta_id1_defaults, + ~AR_STA_ID1_SADH_MASK); + ath_hw_setbssidmask(common); + REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); + ath9k_hw_write_associd(ah); + REG_WRITE(ah, AR_ISR, ~0); + REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); + + REGWRITE_BUFFER_FLUSH(ah); + + ath9k_hw_set_operating_mode(ah, ah->opmode); +} + +static void ath9k_hw_init_queues(struct ath_hw *ah) +{ + int i; + + ENABLE_REGWRITE_BUFFER(ah); + + for (i = 0; i < AR_NUM_DCU; i++) + REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); + + REGWRITE_BUFFER_FLUSH(ah); + + ah->intr_txqs = 0; + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) + ath9k_hw_resettxqueue(ah, i); +} + +/* + * For big endian systems turn on swapping for descriptors + */ +static void ath9k_hw_init_desc(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + + if (AR_SREV_9100(ah)) { + u32 mask; + mask = REG_READ(ah, AR_CFG); + if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { + ath_dbg(common, RESET, "CFG Byte Swap Set 0x%x\n", + mask); + } else { + mask = INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; + REG_WRITE(ah, AR_CFG, mask); + ath_dbg(common, RESET, "Setting CFG 0x%x\n", + REG_READ(ah, AR_CFG)); + } + } else { + if (common->bus_ops->ath_bus_type == ATH_USB) { + /* Configure AR9271 target WLAN */ + if (AR_SREV_9271(ah)) + REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB); + else + REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); + } +#ifdef __BIG_ENDIAN + else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) || + AR_SREV_9550(ah) || AR_SREV_9531(ah)) + REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); + else + REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); +#endif + } +} + +/* + * Fast channel change: + * (Change synthesizer based on channel freq without resetting chip) + */ +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_capabilities *pCap = &ah->caps; + int ret; + + if (AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI) + goto fail; + + if (ah->chip_fullsleep) + goto fail; + + if (!ah->curchan) + goto fail; + + if (chan->channel == ah->curchan->channel) + goto fail; + + if ((ah->curchan->channelFlags | chan->channelFlags) & + (CHANNEL_HALF | CHANNEL_QUARTER)) + goto fail; + + /* + * If cross-band fcc is not supoprted, bail out if channelFlags differ. + */ + if (!(pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) && + ((chan->channelFlags ^ ah->curchan->channelFlags) & ~CHANNEL_HT)) + goto fail; + + if (!ath9k_hw_check_alive(ah)) + goto fail; + + /* + * For AR9462, make sure that calibration data for + * re-using are present. + */ + if (AR_SREV_9462(ah) && (ah->caldata && + (!test_bit(TXIQCAL_DONE, &ah->caldata->cal_flags) || + !test_bit(TXCLCAL_DONE, &ah->caldata->cal_flags) || + !test_bit(RTT_DONE, &ah->caldata->cal_flags)))) + goto fail; + + ath_dbg(common, RESET, "FastChannelChange for %d -> %d\n", + ah->curchan->channel, chan->channel); + + ret = ath9k_hw_channel_change(ah, chan); + if (!ret) + goto fail; + + if (ath9k_hw_mci_is_enabled(ah)) + ar9003_mci_2g5g_switch(ah, false); + + ath9k_hw_loadnf(ah, ah->curchan); + ath9k_hw_start_nfcal(ah, 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 bChannelChange) + struct ath9k_hw_cal_data *caldata, bool fastcc) { struct ath_common *common = ath9k_hw_common(ah); + struct timespec ts; u32 saveLedState; - struct ath9k_channel *curchan = ah->curchan; u32 saveDefAntenna; u32 macStaId1; u64 tsf = 0; - int i, r; - - ah->txchainmask = common->tx_chainmask; - ah->rxchainmask = common->rx_chainmask; + s64 usec = 0; + int r; + bool start_mci_reset = false; + bool save_fullsleep = ah->chip_fullsleep; - if ((common->bus_ops->ath_bus_type != ATH_USB) && !ah->chip_fullsleep) { - ath9k_hw_abortpcurecv(ah); - if (!ath9k_hw_stopdmarecv(ah)) { - ath_dbg(common, ATH_DBG_XMIT, - "Failed to stop receive dma\n"); - bChannelChange = false; - } + if (ath9k_hw_mci_is_enabled(ah)) { + 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 && - (chan->channel != caldata->channel || - (chan->channelFlags & ~CHANNEL_CW_INT) != - (caldata->channelFlags & ~CHANNEL_CW_INT))) { + if (caldata && (chan->channel != caldata->channel || + chan->channelFlags != caldata->channelFlags)) { /* Operating channel changed, reset channel calibration data */ memset(caldata, 0, sizeof(*caldata)); ath9k_init_nfcal_hist_buffer(ah, chan); + } else if (caldata) { + clear_bit(PAPRD_PACKET_SENT, &caldata->cal_flags); } + ah->noise = ath9k_hw_getchan_noise(ah, chan, chan->noisefloor); - if (bChannelChange && - (ah->chip_fullsleep != true) && - (ah->curchan != NULL) && - (chan->channel != ah->curchan->channel) && - ((chan->channelFlags & CHANNEL_ALL) == - (ah->curchan->channelFlags & CHANNEL_ALL)) && - (!AR_SREV_9280(ah) || AR_DEVID_7010(ah))) { - - if (ath9k_hw_channel_change(ah, chan)) { - ath9k_hw_loadnf(ah, ah->curchan); - ath9k_hw_start_nfcal(ah, true); - if (AR_SREV_9271(ah)) - ar9002_hw_load_ani_reg(ah, chan); - return 0; - } + if (fastcc) { + r = ath9k_hw_do_fastcc(ah, chan); + if (!r) + return r; } + if (ath9k_hw_mci_is_enabled(ah)) + ar9003_mci_stop_bt(ah, save_fullsleep); + saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA); if (saveDefAntenna == 0) saveDefAntenna = 1; macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; - /* For chips on which RTC reset is done, save TSF before it gets cleared */ - if (AR_SREV_9100(ah) || - (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))) - tsf = ath9k_hw_gettsf64(ah); + /* Save TSF before chip reset, a cold reset clears it */ + tsf = ath9k_hw_gettsf64(ah); + getrawmonotonic(&ts); + usec = ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000; saveLedState = REG_READ(ah, AR_CFG_LED) & (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | @@ -1301,8 +1818,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, } /* Restore TSF */ - if (tsf) - ath9k_hw_settsf64(ah, tsf); + getrawmonotonic(&ts); + usec = ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000 - usec; + ath9k_hw_settsf64(ah, tsf + usec); if (AR_SREV_9280_20_OR_LATER(ah)) REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); @@ -1314,6 +1832,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (r) return r; + ath9k_hw_set_rfmode(ah, chan); + + if (ath9k_hw_mci_is_enabled(ah)) + ar9003_mci_reset(ah, false, IS_CHAN_2GHZ(chan), save_fullsleep); + /* * Some AR91xx SoC devices frequently fail to accept TSF writes * right after the chip reset. When that happens, write a new @@ -1325,47 +1848,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_settsf64(ah, tsf); } - /* Setup MFP options for CCMP */ - if (AR_SREV_9280_20_OR_LATER(ah)) { - /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt - * frames when constructing CCMP AAD. */ - REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, - 0xc7ff); - ah->sw_mgmt_crypto = false; - } else if (AR_SREV_9160_10_OR_LATER(ah)) { - /* Disable hardware crypto for management frames */ - REG_CLR_BIT(ah, AR_PCU_MISC_MODE2, - AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); - REG_SET_BIT(ah, AR_PCU_MISC_MODE2, - AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); - ah->sw_mgmt_crypto = true; - } else - ah->sw_mgmt_crypto = true; - - if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) - ath9k_hw_set_delta_slope(ah, chan); + ath9k_hw_init_mfp(ah); + ath9k_hw_set_delta_slope(ah, chan); ath9k_hw_spur_mitigate_freq(ah, chan); ah->eep_ops->set_board_values(ah, chan); - ath9k_hw_set_operating_mode(ah, ah->opmode); - - ENABLE_REGWRITE_BUFFER(ah); - - REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); - REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4) - | macStaId1 - | AR_STA_ID1_RTS_USE_DEF - | (ah->config. - ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0) - | ah->sta_id1_defaults); - ath_hw_setbssidmask(common); - REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); - ath9k_hw_write_associd(ah); - REG_WRITE(ah, AR_ISR, ~0); - REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); - - REGWRITE_BUFFER_FLUSH(ah); + ath9k_hw_reset_opmode(ah, macStaId1, saveDefAntenna); r = ath9k_hw_rf_set_freq(ah, chan); if (r) @@ -1373,17 +1862,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_set_clockrate(ah); - ENABLE_REGWRITE_BUFFER(ah); - - for (i = 0; i < AR_NUM_DCU; i++) - REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); - - REGWRITE_BUFFER_FLUSH(ah); - - ah->intr_txqs = 0; - for (i = 0; i < ah->caps.total_queues; i++) - ath9k_hw_resettxqueue(ah, i); - + ath9k_hw_init_queues(ah); ath9k_hw_init_interrupt_masks(ah, ah->opmode); ath9k_hw_ani_cache_ini_regs(ah); ath9k_hw_init_qos(ah); @@ -1393,21 +1872,25 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_init_global_settings(ah); - if (!AR_SREV_9300_20_OR_LATER(ah)) { - ar9002_hw_update_async_fifo(ah); - ar9002_hw_enable_wep_aggregation(ah); + if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) { + REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER, + AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768); + REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN, + AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL); + REG_SET_BIT(ah, AR_PCU_MISC_MODE2, + AR_PCU_MISC_MODE2_ENABLE_AGGWEP); } - REG_WRITE(ah, AR_STA_ID1, - REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM); + REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); ath9k_hw_set_dma(ah); - REG_WRITE(ah, AR_OBS, 8); + if (!ath9k_hw_mci_is_enabled(ah)) + REG_WRITE(ah, AR_OBS, 8); if (ah->config.rx_intr_mitigation) { - REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); - REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000); + REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, ah->config.rimt_last); + REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, ah->config.rimt_first); } if (ah->config.tx_intr_mitigation) { @@ -1417,9 +1900,16 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_init_bb(ah, chan); + if (caldata) { + clear_bit(TXIQCAL_DONE, &caldata->cal_flags); + clear_bit(TXCLCAL_DONE, &caldata->cal_flags); + } if (!ath9k_hw_init_cal(ah, chan)) return -EIO; + if (ath9k_hw_mci_is_enabled(ah) && ar9003_mci_end_reset(ah, chan, caldata)) + return -EIO; + ENABLE_REGWRITE_BUFFER(ah); ath9k_hw_restore_chainmask(ah); @@ -1427,42 +1917,28 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REGWRITE_BUFFER_FLUSH(ah); - /* - * For big endian systems turn on swapping for descriptors - */ - if (AR_SREV_9100(ah)) { - u32 mask; - mask = REG_READ(ah, AR_CFG); - if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { - ath_dbg(common, ATH_DBG_RESET, - "CFG Byte Swap Set 0x%x\n", mask); - } else { - mask = - INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; - REG_WRITE(ah, AR_CFG, mask); - ath_dbg(common, ATH_DBG_RESET, - "Setting CFG 0x%x\n", REG_READ(ah, AR_CFG)); - } - } else { - if (common->bus_ops->ath_bus_type == ATH_USB) { - /* Configure AR9271 target WLAN */ - if (AR_SREV_9271(ah)) - REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB); - else - REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); - } -#ifdef __BIG_ENDIAN - else - REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); -#endif - } + ath9k_hw_init_desc(ah); - if (ah->btcoex_hw.enabled) + if (ath9k_hw_btcoex_is_enabled(ah)) ath9k_hw_btcoex_enable(ah); + if (ath9k_hw_mci_is_enabled(ah)) + ar9003_mci_check_bt(ah); + + ath9k_hw_loadnf(ah, chan); + ath9k_hw_start_nfcal(ah, true); + if (AR_SREV_9300_20_OR_LATER(ah)) ar9003_hw_bb_watchdog_config(ah); + if (ah->config.hw_hang_checks & HW_PHYRESTART_CLC_WAR) + ar9003_hw_disable_phy_restart(ah); + + ath9k_hw_apply_gpio_override(ah); + + if (AR_SREV_9565(ah) && common->bt_ant_diversity) + REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON); + return 0; } EXPORT_SYMBOL(ath9k_hw_reset); @@ -1475,29 +1951,40 @@ EXPORT_SYMBOL(ath9k_hw_reset); * Notify Power Mgt is disabled in self-generated frames. * If requested, force chip to sleep. */ -static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) +static void ath9k_set_power_sleep(struct ath_hw *ah) { REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); - if (setChip) { - /* - * Clear the RTC force wake bit to allow the - * mac to go to sleep. - */ - REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, - AR_RTC_FORCE_WAKE_EN); - if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah)) - REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); - /* Shutdown chip. Active low */ - if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah)) - REG_CLR_BIT(ah, (AR_RTC_RESET), - AR_RTC_RESET_EN); + if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { + REG_CLR_BIT(ah, AR_TIMER_MODE, 0xff); + REG_CLR_BIT(ah, AR_NDP2_TIMER_MODE, 0xff); + REG_CLR_BIT(ah, AR_SLP32_INC, 0xfffff); + /* xxx Required for WLAN only case ? */ + REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0); + udelay(100); + } + + /* + * Clear the RTC force wake bit to allow the + * mac to go to sleep. + */ + REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); + + if (ath9k_hw_mci_is_enabled(ah)) + udelay(100); + + if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah)) + REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); + + /* Shutdown chip. Active low */ + if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah)) { + REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN); + udelay(2); } /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */ if (AR_SREV_9300_20_OR_LATER(ah)) - REG_WRITE(ah, AR_WA, - ah->WARegVal & ~AR_WA_D3_L1_DISABLE); + REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE); } /* @@ -1505,24 +1992,38 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) * frames. If request, set power mode of chip to * auto/normal. Duration in units of 128us (1/8 TU). */ -static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip) +static void ath9k_set_power_network_sleep(struct ath_hw *ah) { + struct ath9k_hw_capabilities *pCap = &ah->caps; + REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); - if (setChip) { - struct ath9k_hw_capabilities *pCap = &ah->caps; - if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { - /* Set WakeOnInterrupt bit; clear ForceWake bit */ - REG_WRITE(ah, AR_RTC_FORCE_WAKE, - AR_RTC_FORCE_WAKE_ON_INT); - } else { - /* - * Clear the RTC force wake bit to allow the - * mac to go to sleep. - */ - REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, - AR_RTC_FORCE_WAKE_EN); - } + if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { + /* Set WakeOnInterrupt bit; clear ForceWake bit */ + REG_WRITE(ah, AR_RTC_FORCE_WAKE, + AR_RTC_FORCE_WAKE_ON_INT); + } else { + + /* When chip goes into network sleep, it could be waken + * up by MCI_INT interrupt caused by BT's HW messages + * (LNA_xxx, CONT_xxx) which chould be in a very fast + * rate (~100us). This will cause chip to leave and + * re-enter network sleep mode frequently, which in + * consequence will have WLAN MCI HW to generate lots of + * SYS_WAKING and SYS_SLEEPING messages which will make + * BT CPU to busy to process. + */ + if (ath9k_hw_mci_is_enabled(ah)) + REG_CLR_BIT(ah, AR_MCI_INTERRUPT_RX_MSG_EN, + AR_MCI_INTERRUPT_RX_HW_MSG_MASK); + /* + * Clear the RTC force wake bit to allow the + * mac to go to sleep. + */ + REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); + + if (ath9k_hw_mci_is_enabled(ah)) + udelay(30); } /* Clear Bit 14 of AR_WA after putting chip into Net Sleep mode. */ @@ -1530,7 +2031,7 @@ static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip) REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE); } -static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) +static bool ath9k_hw_set_power_awake(struct ath_hw *ah) { u32 val; int i; @@ -1541,39 +2042,42 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) udelay(10); } - 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) { - return false; - } - if (!AR_SREV_9300_20_OR_LATER(ah)) - ath9k_hw_init_pll(ah, NULL); + 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)) { + return false; } - if (AR_SREV_9100(ah)) - REG_SET_BIT(ah, AR_RTC_RESET, - AR_RTC_RESET_EN); + if (!AR_SREV_9300_20_OR_LATER(ah)) + ath9k_hw_init_pll(ah, NULL); + } + if (AR_SREV_9100(ah)) + REG_SET_BIT(ah, AR_RTC_RESET, + AR_RTC_RESET_EN); - REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, - AR_RTC_FORCE_WAKE_EN); + REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, + AR_RTC_FORCE_WAKE_EN); + if (AR_SREV_9100(ah)) + mdelay(10); + else udelay(50); - for (i = POWER_UP_TIME / 50; i > 0; i--) { - val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; - if (val == AR_RTC_STATUS_ON) - break; - udelay(50); - REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, - AR_RTC_FORCE_WAKE_EN); - } - if (i == 0) { - ath_err(ath9k_hw_common(ah), - "Failed to wakeup in %uus\n", - POWER_UP_TIME / 20); - return false; - } + for (i = POWER_UP_TIME / 50; i > 0; i--) { + val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; + if (val == AR_RTC_STATUS_ON) + break; + udelay(50); + REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, + AR_RTC_FORCE_WAKE_EN); } + if (i == 0) { + ath_err(ath9k_hw_common(ah), + "Failed to wakeup in %uus\n", + POWER_UP_TIME / 20); + return false; + } + + if (ath9k_hw_mci_is_enabled(ah)) + ar9003_mci_set_power_awake(ah); REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); @@ -1583,7 +2087,7 @@ 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); - int status = true, setChip = true; + int status = true; static const char *modes[] = { "AWAKE", "FULL-SLEEP", @@ -1594,19 +2098,22 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) if (ah->power_mode == mode) return status; - ath_dbg(common, ATH_DBG_RESET, "%s -> %s\n", + ath_dbg(common, RESET, "%s -> %s\n", modes[ah->power_mode], modes[mode]); switch (mode) { case ATH9K_PM_AWAKE: - status = ath9k_hw_set_power_awake(ah, setChip); + status = ath9k_hw_set_power_awake(ah); break; case ATH9K_PM_FULL_SLEEP: - ath9k_set_power_sleep(ah, setChip); + if (ath9k_hw_mci_is_enabled(ah)) + ar9003_mci_set_full_sleep(ah); + + ath9k_set_power_sleep(ah); ah->chip_fullsleep = true; break; case ATH9K_PM_NETWORK_SLEEP: - ath9k_set_power_network_sleep(ah, setChip); + ath9k_set_power_network_sleep(ah); break; default: ath_err(common, "Unknown power mode %u\n", mode); @@ -1639,47 +2146,31 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) switch (ah->opmode) { case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: REG_SET_BIT(ah, AR_TXCFG, AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); - REG_WRITE(ah, AR_NEXT_NDP_TIMER, - TU_TO_USEC(next_beacon + - (ah->atim_window ? ah-> - atim_window : 1))); - flags |= AR_NDP_TIMER_EN; + case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_AP: - REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon)); - REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, - TU_TO_USEC(next_beacon - - ah->config. - dma_beacon_response_time)); - REG_WRITE(ah, AR_NEXT_SWBA, - TU_TO_USEC(next_beacon - - ah->config. - sw_beacon_response_time)); + REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon); + REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, next_beacon - + TU_TO_USEC(ah->config.dma_beacon_response_time)); + REG_WRITE(ah, AR_NEXT_SWBA, next_beacon - + TU_TO_USEC(ah->config.sw_beacon_response_time)); flags |= AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN; break; default: - ath_dbg(ath9k_hw_common(ah), ATH_DBG_BEACON, - "%s: unsupported opmode: %d\n", - __func__, ah->opmode); + ath_dbg(ath9k_hw_common(ah), BEACON, + "%s: unsupported opmode: %d\n", __func__, ah->opmode); return; break; } - REG_WRITE(ah, AR_BEACON_PERIOD, TU_TO_USEC(beacon_period)); - REG_WRITE(ah, AR_DMA_BEACON_PERIOD, TU_TO_USEC(beacon_period)); - REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period)); - REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period)); + REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period); + REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period); + REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period); REGWRITE_BUFFER_FLUSH(ah); - beacon_period &= ~ATH9K_BEACON_ENA; - if (beacon_period & ATH9K_BEACON_RESET_TSF) { - ath9k_hw_reset_tsf(ah); - } - REG_SET_BIT(ah, AR_TIMER_MODE, flags); } EXPORT_SYMBOL(ath9k_hw_beaconinit); @@ -1693,19 +2184,16 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, ENABLE_REGWRITE_BUFFER(ah); - REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt)); - - REG_WRITE(ah, AR_BEACON_PERIOD, - TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); - REG_WRITE(ah, AR_DMA_BEACON_PERIOD, - TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); + REG_WRITE(ah, AR_NEXT_TBTT_TIMER, bs->bs_nexttbtt); + REG_WRITE(ah, AR_BEACON_PERIOD, bs->bs_intval); + REG_WRITE(ah, AR_DMA_BEACON_PERIOD, bs->bs_intval); REGWRITE_BUFFER_FLUSH(ah); REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold); - beaconintval = bs->bs_intval & ATH9K_BEACON_PERIOD; + beaconintval = bs->bs_intval; if (bs->bs_sleepduration > beaconintval) beaconintval = bs->bs_sleepduration; @@ -1719,16 +2207,15 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, else nextTbtt = bs->bs_nexttbtt; - ath_dbg(common, ATH_DBG_BEACON, "next DTIM %d\n", bs->bs_nextdtim); - ath_dbg(common, ATH_DBG_BEACON, "next beacon %d\n", nextTbtt); - ath_dbg(common, ATH_DBG_BEACON, "beacon period %d\n", beaconintval); - ath_dbg(common, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod); + ath_dbg(common, BEACON, "next DTIM %d\n", bs->bs_nextdtim); + ath_dbg(common, BEACON, "next beacon %d\n", nextTbtt); + ath_dbg(common, BEACON, "beacon period %d\n", beaconintval); + ath_dbg(common, BEACON, "DTIM period %d\n", dtimperiod); ENABLE_REGWRITE_BUFFER(ah); - REG_WRITE(ah, AR_NEXT_DTIM, - TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP)); - REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP)); + REG_WRITE(ah, AR_NEXT_DTIM, bs->bs_nextdtim - SLEEP_SLOP); + REG_WRITE(ah, AR_NEXT_TIM, nextTbtt - SLEEP_SLOP); REG_WRITE(ah, AR_SLEEP1, SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT) @@ -1742,8 +2229,8 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, REG_WRITE(ah, AR_SLEEP2, SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT)); - REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval)); - REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod)); + REG_WRITE(ah, AR_TIM_PERIOD, beaconintval); + REG_WRITE(ah, AR_DTIM_PERIOD, dtimperiod); REGWRITE_BUFFER_FLUSH(ah); @@ -1760,26 +2247,55 @@ EXPORT_SYMBOL(ath9k_hw_set_sta_beacon_timers); /* HW Capabilities */ /*******************/ +static u8 fixup_chainmask(u8 chip_chainmask, u8 eeprom_chainmask) +{ + eeprom_chainmask &= chip_chainmask; + if (eeprom_chainmask) + return eeprom_chainmask; + else + return chip_chainmask; +} + +/** + * ath9k_hw_dfs_tested - checks if DFS has been tested with used chipset + * @ah: the atheros hardware data structure + * + * We enable DFS support upstream on chipsets which have passed a series + * of tests. The testing requirements are going to be documented. Desired + * test requirements are documented at: + * + * http://wireless.kernel.org/en/users/Drivers/ath9k/dfs + * + * Once a new chipset gets properly tested an individual commit can be used + * to document the testing for DFS for that chipset. + */ +static bool ath9k_hw_dfs_tested(struct ath_hw *ah) +{ + + switch (ah->hw_version.macVersion) { + /* for temporary testing DFS with 9280 */ + case AR_SREV_VERSION_9280: + /* AR9580 will likely be our first target to get testing on */ + case AR_SREV_VERSION_9580: + return true; + default: + return false; + } +} + 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 capField = 0, eeval; + u16 eeval; u8 ant_div_ctl1, tx_chainmask, rx_chainmask; eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0); regulatory->current_rd = eeval; - eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1); - if (AR_SREV_9285_12_OR_LATER(ah)) - eeval |= AR9285_RDEXT_DEFAULT; - regulatory->current_rd_ext = eeval; - - capField = ah->eep_ops->get_eeprom(ah, EEP_OP_CAP); - if (ah->opmode != NL80211_IFTYPE_AP && ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) { if (regulatory->current_rd == 0x64 || @@ -1787,8 +2303,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) regulatory->current_rd += 5; else if (regulatory->current_rd == 0x41) regulatory->current_rd = 0x43; - ath_dbg(common, ATH_DBG_REGULATORY, - "regdomain mapped to 0x%x\n", regulatory->current_rd); + ath_dbg(common, REGULATORY, "regdomain mapped to 0x%x\n", + regulatory->current_rd); } eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); @@ -1804,6 +2320,20 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) if (eeval & AR5416_OPFLAGS_11G) pCap->hw_caps |= ATH9K_HW_CAP_2GHZ; + if (AR_SREV_9485(ah) || + AR_SREV_9285(ah) || + AR_SREV_9330(ah) || + AR_SREV_9565(ah)) + chip_chainmask = 1; + else if (AR_SREV_9462(ah)) + chip_chainmask = 3; + else if (!AR_SREV_9280_20_OR_LATER(ah)) + chip_chainmask = 7; + else if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9340(ah)) + chip_chainmask = 3; + else + chip_chainmask = 7; + pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK); /* * For AR9271 we will temporarilly uses the rx chainmax as read from @@ -1814,50 +2344,38 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) !(AR_SREV_9271(ah))) /* CB71: GPIO 0 is pulled down to indicate 3 rx chains */ pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7; + else if (AR_SREV_9100(ah)) + pCap->rx_chainmask = 0x7; else /* Use rx_chainmask from EEPROM. */ pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK); + pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask); + pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask); + ah->txchainmask = pCap->tx_chainmask; + ah->rxchainmask = pCap->rx_chainmask; + ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA; /* enable key search for every frame in an aggregate */ if (AR_SREV_9300_20_OR_LATER(ah)) ah->misc_mode |= AR_PCU_ALWAYS_PERFORM_KEYSEARCH; - pCap->low_2ghz_chan = 2312; - pCap->high_2ghz_chan = 2732; - - pCap->low_5ghz_chan = 4920; - pCap->high_5ghz_chan = 6100; - common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM; - if (ah->config.ht_enable) + if (ah->hw_version.devid != AR2427_DEVID_PCIE) pCap->hw_caps |= ATH9K_HW_CAP_HT; else pCap->hw_caps &= ~ATH9K_HW_CAP_HT; - if (capField & AR_EEPROM_EEPCAP_MAXQCU) - pCap->total_queues = - MS(capField, AR_EEPROM_EEPCAP_MAXQCU); - else - pCap->total_queues = ATH9K_NUM_TX_QUEUES; - - if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES) - pCap->keycache_size = - 1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES); - else - pCap->keycache_size = AR_KEYTABLE_SIZE; - - if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) - pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1; - else - pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; - if (AR_SREV_9271(ah)) pCap->num_gpio_pins = AR9271_NUM_GPIO; else if (AR_DEVID_7010(ah)) pCap->num_gpio_pins = AR7010_NUM_GPIO; + else if (AR_SREV_9300_20_OR_LATER(ah)) + pCap->num_gpio_pins = AR9300_NUM_GPIO; + else if (AR_SREV_9287_11_OR_LATER(ah)) + pCap->num_gpio_pins = AR9287_NUM_GPIO; else if (AR_SREV_9285_12_OR_LATER(ah)) pCap->num_gpio_pins = AR9285_NUM_GPIO; else if (AR_SREV_9280_20_OR_LATER(ah)) @@ -1865,16 +2383,12 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) else pCap->num_gpio_pins = AR_NUM_GPIO; - if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) { - pCap->hw_caps |= ATH9K_HW_CAP_CST; + if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX; - } else { + else pCap->rts_aggr_limit = (8 * 1024); - } - - pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM; -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) +#ifdef CONFIG_ATH9K_RFKILL ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT); if (ah->rfsilent & EEP_RFSILENT_ENABLED) { ah->rfkill_gpio = @@ -1895,40 +2409,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) else pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS; - if (regulatory->current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) { - pCap->reg_cap = - AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | - AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN | - AR_EEPROM_EEREGCAP_EN_KK_U2 | - AR_EEPROM_EEREGCAP_EN_KK_MIDBAND; - } else { - pCap->reg_cap = - AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | - AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN; - } - - /* Advertise midband for AR5416 with FCC midband set in eeprom */ - if (regulatory->current_rd_ext & (1 << REG_EXT_FCC_MIDBAND) && - AR_SREV_5416(ah)) - pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND; - - if (AR_SREV_9280_20_OR_LATER(ah) && common->btcoex_enabled) { - btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO; - btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO; - - if (AR_SREV_9285(ah)) { - btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE; - btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO; - } 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_9485(ah)) + if (!AR_SREV_9330(ah) && !AR_SREV_9485(ah) && !AR_SREV_9565(ah)) pCap->hw_caps |= ATH9K_HW_CAP_LDPC; pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH; @@ -1936,15 +2419,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->rx_status_len = sizeof(struct ar9003_rxs); pCap->tx_desc_len = sizeof(struct ar9003_txc); pCap->txs_len = sizeof(struct ar9003_txs); - if (!ah->config.paprd_disable && - ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) - pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; } else { pCap->tx_desc_len = sizeof(struct ath_desc); - if (AR_SREV_9280_20(ah) && - ((ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) <= - AR5416_EEP_MINOR_VER_16) || - ah->eep_ops->get_eeprom(ah, EEP_FSTCLK_5G))) + if (AR_SREV_9280_20(ah)) pCap->hw_caps |= ATH9K_HW_CAP_FASTCLOCK; } @@ -1957,25 +2434,33 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah)) pCap->hw_caps |= ATH9K_HW_CAP_SGI_20; - if (AR_SREV_9285(ah)) + if (AR_SREV_9285(ah)) { if (ah->eep_ops->get_eeprom(ah, EEP_MODAL_VER) >= 3) { ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); - if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1)) + if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1)) { pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; + ath_info(common, "Enable LNA combining\n"); + } } + } + if (AR_SREV_9300_20_OR_LATER(ah)) { if (ah->eep_ops->get_eeprom(ah, EEP_CHAIN_MASK_REDUCE)) pCap->hw_caps |= ATH9K_HW_CAP_APM; } - - - if (AR_SREV_9485_10(ah)) { - pCap->pcie_lcr_extsync_en = true; - pCap->pcie_lcr_offset = 0x80; + if (AR_SREV_9330(ah) || AR_SREV_9485(ah) || AR_SREV_9565(ah)) { + ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); + if ((ant_div_ctl1 >> 0x6) == 0x3) { + pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; + ath_info(common, "Enable LNA combining\n"); + } } + if (ath9k_hw_dfs_tested(ah)) + pCap->hw_caps |= ATH9K_HW_CAP_DFS; + tx_chainmask = pCap->tx_chainmask; rx_chainmask = pCap->rx_chainmask; while (tx_chainmask || rx_chainmask) { @@ -1988,6 +2473,21 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) rx_chainmask >>= 1; } + if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { + if (!(ah->ent_mode & AR_ENT_OTP_49GHZ_DISABLE)) + pCap->hw_caps |= ATH9K_HW_CAP_MCI; + + if (AR_SREV_9462_20_OR_LATER(ah)) + pCap->hw_caps |= ATH9K_HW_CAP_RTT; + } + + if (AR_SREV_9462(ah)) + pCap->hw_caps |= ATH9K_HW_WOW_DEVICE_CAPABLE; + + if (AR_SREV_9300_20_OR_LATER(ah) && + ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) + pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; + return 0; } @@ -2112,12 +2612,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)); @@ -2148,6 +2642,9 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits) ENABLE_REGWRITE_BUFFER(ah); + if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) + bits |= ATH9K_RX_FILTER_CONTROL_WRAPPER; + REG_WRITE(ah, AR_RX_FILTER, bits); phybits = 0; @@ -2158,11 +2655,9 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits) REG_WRITE(ah, AR_PHY_ERR, phybits); if (phybits) - REG_WRITE(ah, AR_RXCFG, - REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA); + REG_SET_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA); else - REG_WRITE(ah, AR_RXCFG, - REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA); + REG_CLR_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA); REGWRITE_BUFFER_FLUSH(ah); } @@ -2170,10 +2665,14 @@ EXPORT_SYMBOL(ath9k_hw_setrxfilter); bool ath9k_hw_phy_disable(struct ath_hw *ah) { + if (ath9k_hw_mci_is_enabled(ah)) + ar9003_mci_bt_gain_ctrl(ah); + if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) return false; ath9k_hw_init_pll(ah, NULL); + ah->htc_reset_init = true; return true; } EXPORT_SYMBOL(ath9k_hw_phy_disable); @@ -2191,20 +2690,57 @@ bool ath9k_hw_disable(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_disable); +static int get_antenna_gain(struct ath_hw *ah, struct ath9k_channel *chan) +{ + enum eeprom_param gain_param; + + if (IS_CHAN_2GHZ(chan)) + gain_param = EEP_ANTENNA_GAIN_2G; + else + gain_param = EEP_ANTENNA_GAIN_5G; + + return ah->eep_ops->get_eeprom(ah, gain_param); +} + +void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan, + bool test) +{ + struct ath_regulatory *reg = ath9k_hw_regulatory(ah); + struct ieee80211_channel *channel; + int chan_pwr, new_pwr, max_gain; + int ant_gain, ant_reduction = 0; + + if (!chan) + return; + + channel = chan->chan; + chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER); + new_pwr = min_t(int, chan_pwr, reg->power_limit); + max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2; + + ant_gain = get_antenna_gain(ah, chan); + if (ant_gain > max_gain) + ant_reduction = ant_gain - max_gain; + + ah->eep_ops->set_txpower(ah, chan, + ath9k_regd_get_ctl(reg, chan), + ant_reduction, new_pwr, test); +} + void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test) { - struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); + struct ath_regulatory *reg = ath9k_hw_regulatory(ah); struct ath9k_channel *chan = ah->curchan; struct ieee80211_channel *channel = chan->chan; - regulatory->power_limit = min(limit, (u32) MAX_RATE_POWER); + reg->power_limit = min_t(u32, limit, MAX_RATE_POWER); + if (test) + channel->max_power = MAX_RATE_POWER / 2; - ah->eep_ops->set_txpower(ah, chan, - ath9k_regd_get_ctl(regulatory, chan), - channel->max_antenna_gain * 2, - channel->max_power * 2, - min((u32) MAX_RATE_POWER, - (u32) regulatory->power_limit), test); + ath9k_hw_apply_txpower(ah, chan, test); + + if (test) + channel->max_power = DIV_ROUND_UP(reg->max_power_level, 2); } EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit); @@ -2264,28 +2800,27 @@ void ath9k_hw_reset_tsf(struct ath_hw *ah) { if (!ath9k_hw_wait(ah, AR_SLP32_MODE, AR_SLP32_TSF_WRITE_STATUS, 0, AH_TSF_WRITE_TIMEOUT)) - ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, + ath_dbg(ath9k_hw_common(ah), RESET, "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n"); REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); } EXPORT_SYMBOL(ath9k_hw_reset_tsf); -void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting) +void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set) { - if (setting) + if (set) ah->misc_mode |= AR_PCU_TX_ADD_TSF; else ah->misc_mode &= ~AR_PCU_TX_ADD_TSF; } EXPORT_SYMBOL(ath9k_hw_set_tsfadjust); -void ath9k_hw_set11nmac2040(struct ath_hw *ah) +void ath9k_hw_set11nmac2040(struct ath_hw *ah, struct ath9k_channel *chan) { - struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; u32 macmode; - if (conf_is_ht40(conf) && !ah->config.cwm_ignore_extcca) + if (IS_CHAN_HT40(chan) && !ah->config.cwm_ignore_extcca) macmode = AR_2040_JOINED_RX_CLEAR; else macmode = 0; @@ -2324,24 +2859,11 @@ static const struct ath_gen_timer_configuration gen_tmr_configuration[] = /* HW generic timer primitives */ -/* compute and clear index of rightmost 1 */ -static u32 rightmost_index(struct ath_gen_timer_table *timer_table, u32 *mask) -{ - u32 b; - - b = *mask; - b &= (0-b); - *mask &= ~b; - b *= debruijn32; - b >>= 27; - - return timer_table->gen_timer_index[b]; -} - -static u32 ath9k_hw_gettsf32(struct ath_hw *ah) +u32 ath9k_hw_gettsf32(struct ath_hw *ah) { return REG_READ(ah, AR_TSF_L32); } +EXPORT_SYMBOL(ath9k_hw_gettsf32); struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, void (*trigger)(void *), @@ -2352,14 +2874,13 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; struct ath_gen_timer *timer; - timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL); + if ((timer_index < AR_FIRST_NDP_TIMER) || + (timer_index >= ATH_MAX_GEN_TIMER)) + return NULL; - if (timer == NULL) { - ath_err(ath9k_hw_common(ah), - "Failed to allocate memory for hw timer[%d]\n", - timer_index); + timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL); + if (timer == NULL) return NULL; - } /* allocate a hardware generic timer slot */ timer_table->timers[timer_index] = timer; @@ -2378,24 +2899,9 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah, u32 timer_period) { struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; - u32 tsf; + u32 mask = 0; - BUG_ON(!timer_period); - - set_bit(timer->index, &timer_table->timer_mask.timer_bits); - - tsf = ath9k_hw_gettsf32(ah); - - ath_dbg(ath9k_hw_common(ah), ATH_DBG_HWTIMER, - "current tsf %x period %x timer_next %x\n", - tsf, timer_period, timer_next); - - /* - * Pull timer_next forward if the current TSF already passed it - * because of software latency - */ - if (timer_next < tsf) - timer_next = tsf + timer_period; + timer_table->timer_mask |= BIT(timer->index); /* * Program generic timer registers @@ -2407,10 +2913,33 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah, REG_SET_BIT(ah, gen_tmr_configuration[timer->index].mode_addr, gen_tmr_configuration[timer->index].mode_mask); - /* Enable both trigger and thresh interrupt masks */ - REG_SET_BIT(ah, AR_IMR_S5, - (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) | - SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG))); + if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { + /* + * Starting from AR9462, each generic timer can select which tsf + * to use. But we still follow the old rule, 0 - 7 use tsf and + * 8 - 15 use tsf2. + */ + if ((timer->index < AR_GEN_TIMER_BANK_1_LEN)) + REG_CLR_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL, + (1 << timer->index)); + else + REG_SET_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL, + (1 << timer->index)); + } + + if (timer->trigger) + mask |= SM(AR_GENTMR_BIT(timer->index), + AR_IMR_S5_GENTIMER_TRIG); + if (timer->overflow) + mask |= SM(AR_GENTMR_BIT(timer->index), + AR_IMR_S5_GENTIMER_THRESH); + + REG_SET_BIT(ah, AR_IMR_S5, mask); + + if ((ah->imask & ATH9K_INT_GENTIMER) == 0) { + ah->imask |= ATH9K_INT_GENTIMER; + ath9k_hw_set_interrupts(ah); + } } EXPORT_SYMBOL(ath9k_hw_gen_timer_start); @@ -2418,21 +2947,31 @@ void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) { struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; - if ((timer->index < AR_FIRST_NDP_TIMER) || - (timer->index >= ATH_MAX_GEN_TIMER)) { - return; - } - /* Clear generic timer enable bits. */ REG_CLR_BIT(ah, gen_tmr_configuration[timer->index].mode_addr, gen_tmr_configuration[timer->index].mode_mask); + if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { + /* + * Need to switch back to TSF if it was using TSF2. + */ + if ((timer->index >= AR_GEN_TIMER_BANK_1_LEN)) { + REG_CLR_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL, + (1 << timer->index)); + } + } + /* Disable both trigger and thresh interrupt masks */ REG_CLR_BIT(ah, AR_IMR_S5, (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) | SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG))); - clear_bit(timer->index, &timer_table->timer_mask.timer_bits); + timer_table->timer_mask &= ~BIT(timer->index); + + if (timer_table->timer_mask == 0) { + ah->imask &= ~ATH9K_INT_GENTIMER; + ath9k_hw_set_interrupts(ah); + } } EXPORT_SYMBOL(ath9k_hw_gen_timer_stop); @@ -2453,32 +2992,32 @@ void ath_gen_timer_isr(struct ath_hw *ah) { struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; struct ath_gen_timer *timer; - struct ath_common *common = ath9k_hw_common(ah); - u32 trigger_mask, thresh_mask, index; + unsigned long trigger_mask, thresh_mask; + unsigned int index; /* get hardware generic timer interrupt status */ trigger_mask = ah->intr_gen_timer_trigger; thresh_mask = ah->intr_gen_timer_thresh; - trigger_mask &= timer_table->timer_mask.val; - thresh_mask &= timer_table->timer_mask.val; - - trigger_mask &= ~thresh_mask; + trigger_mask &= timer_table->timer_mask; + thresh_mask &= timer_table->timer_mask; - while (thresh_mask) { - index = rightmost_index(timer_table, &thresh_mask); + for_each_set_bit(index, &thresh_mask, ARRAY_SIZE(timer_table->timers)) { timer = timer_table->timers[index]; - BUG_ON(!timer); - ath_dbg(common, ATH_DBG_HWTIMER, - "TSF overflow for Gen timer %d\n", index); + if (!timer) + continue; + if (!timer->overflow) + continue; + + trigger_mask &= ~BIT(index); timer->overflow(timer->arg); } - while (trigger_mask) { - index = rightmost_index(timer_table, &trigger_mask); + for_each_set_bit(index, &trigger_mask, ARRAY_SIZE(timer_table->timers)) { timer = timer_table->timers[index]; - BUG_ON(!timer); - ath_dbg(common, ATH_DBG_HWTIMER, - "Gen timer[%d] trigger\n", index); + if (!timer) + continue; + if (!timer->trigger) + continue; timer->trigger(timer->arg); } } @@ -2488,12 +3027,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; @@ -2509,6 +3042,13 @@ static struct { { AR_SREV_VERSION_9287, "9287" }, { AR_SREV_VERSION_9271, "9271" }, { AR_SREV_VERSION_9300, "9300" }, + { AR_SREV_VERSION_9330, "9330" }, + { AR_SREV_VERSION_9340, "9340" }, + { AR_SREV_VERSION_9485, "9485" }, + { AR_SREV_VERSION_9462, "9462" }, + { AR_SREV_VERSION_9550, "9550" }, + { AR_SREV_VERSION_9565, "9565" }, + { AR_SREV_VERSION_9531, "9531" }, }; /* For devices with external radios */ @@ -2562,19 +3102,19 @@ void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len) /* chipsets >= AR9280 are single-chip */ if (AR_SREV_9280_20_OR_LATER(ah)) { - used = snprintf(hw_name, len, - "Atheros AR%s Rev:%x", - ath9k_hw_mac_bb_name(ah->hw_version.macVersion), - ah->hw_version.macRev); + used = scnprintf(hw_name, len, + "Atheros AR%s Rev:%x", + ath9k_hw_mac_bb_name(ah->hw_version.macVersion), + ah->hw_version.macRev); } else { - used = snprintf(hw_name, len, - "Atheros AR%s MAC/BB Rev:%x AR%s RF Rev:%x", - ath9k_hw_mac_bb_name(ah->hw_version.macVersion), - ah->hw_version.macRev, - ath9k_hw_rf_name((ah->hw_version.analog5GhzRev & - AR_RADIO_SREV_MAJOR)), - ah->hw_version.phyRev); + used = scnprintf(hw_name, len, + "Atheros AR%s MAC/BB Rev:%x AR%s RF Rev:%x", + ath9k_hw_mac_bb_name(ah->hw_version.macVersion), + ah->hw_version.macRev, + ath9k_hw_rf_name((ah->hw_version.analog5GhzRev + & AR_RADIO_SREV_MAJOR)), + ah->hw_version.phyRev); } hw_name[used] = '\0'; |
