diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/hw.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 54 |
1 files changed, 52 insertions, 2 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 8529014e1a5e..5e15e8e10ed3 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -20,6 +20,7 @@ #include <linux/time.h> #include <linux/bitops.h> #include <linux/etherdevice.h> +#include <linux/gpio.h> #include <asm/unaligned.h> #include "hw.h" @@ -121,6 +122,36 @@ void ath9k_hw_write_array(struct ath_hw *ah, const struct ar5416IniArray *array, REGWRITE_BUFFER_FLUSH(ah); } +void ath9k_hw_read_array(struct ath_hw *ah, u32 array[][2], int size) +{ + u32 *tmp_reg_list, *tmp_data; + int i; + + tmp_reg_list = kmalloc(size * sizeof(u32), GFP_KERNEL); + if (!tmp_reg_list) { + dev_err(ah->dev, "%s: tmp_reg_list: alloc filed\n", __func__); + return; + } + + tmp_data = kmalloc(size * sizeof(u32), GFP_KERNEL); + if (!tmp_data) { + dev_err(ah->dev, "%s tmp_data: alloc filed\n", __func__); + goto error_tmp_data; + } + + for (i = 0; i < size; i++) + tmp_reg_list[i] = array[i][0]; + + REG_READ_MULTI(ah, tmp_reg_list, tmp_data, size); + + for (i = 0; i < size; i++) + array[i][1] = tmp_data[i]; + + kfree(tmp_data); +error_tmp_data: + kfree(tmp_reg_list); +} + u32 ath9k_hw_reverse_bits(u32 val, u32 n) { u32 retval; @@ -366,6 +397,9 @@ static void ath9k_hw_init_config(struct ath_hw *ah) ah->config.rimt_first = 700; } + if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) + ah->config.pll_pwrsave = 7; + /* * We need this for PCI devices only (Cardbus, PCI, miniPCI) * _and_ if on non-uniprocessor systems (Multiprocessor/HT). @@ -1197,6 +1231,7 @@ static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) u32 mask = AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC; u32 set = AR_STA_ID1_KSRCH_MODE; + ENABLE_REG_RMW_BUFFER(ah); switch (opmode) { case NL80211_IFTYPE_ADHOC: if (!AR_SREV_9340_13(ah)) { @@ -1218,6 +1253,7 @@ static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) break; } REG_RMW(ah, AR_STA_ID1, set, mask); + REG_RMW_BUFFER_FLUSH(ah); } void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, @@ -1930,6 +1966,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (!ath9k_hw_mci_is_enabled(ah)) REG_WRITE(ah, AR_OBS, 8); + ENABLE_REG_RMW_BUFFER(ah); if (ah->config.rx_intr_mitigation) { 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); @@ -1939,6 +1976,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, 300); REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, 750); } + REG_RMW_BUFFER_FLUSH(ah); ath9k_hw_init_bb(ah, chan); @@ -2674,11 +2712,23 @@ void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val) if (AR_SREV_9271(ah)) val = ~val; - REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio), - AR_GPIO_BIT(gpio)); + if ((1 << gpio) & AR_GPIO_OE_OUT_MASK) + REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio), + AR_GPIO_BIT(gpio)); + else + gpio_set_value(gpio, val & 1); } EXPORT_SYMBOL(ath9k_hw_set_gpio); +void ath9k_hw_request_gpio(struct ath_hw *ah, u32 gpio, const char *label) +{ + if (gpio >= ah->caps.num_gpio_pins) + return; + + gpio_request_one(gpio, GPIOF_DIR_OUT | GPIOF_INIT_LOW, label); +} +EXPORT_SYMBOL(ath9k_hw_request_gpio); + void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna) { REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); |