@@ -20,7 +20,7 @@
#include <linux/time.h>
#include <linux/bitops.h>
#include <linux/etherdevice.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <asm/unaligned.h>
#include "hw.h"
@@ -2727,19 +2727,25 @@ static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah, u32 gpio, u32 type)
static void ath9k_hw_gpio_cfg_soc(struct ath_hw *ah, u32 gpio, bool out,
const char *label)
{
+ enum gpiod_flags flags = out ? GPIOD_OUT_LOW : GPIOD_IN;
+ struct gpio_desc *gpiod;
int err;
- if (ah->caps.gpio_requested & BIT(gpio))
+ if (ah->gpiods[gpio])
return;
- err = gpio_request_one(gpio, out ? GPIOF_OUT_INIT_LOW : GPIOF_IN, label);
- if (err) {
+ /* Obtains a system specific GPIO descriptor from another GPIO controller */
+ gpiod = devm_gpiod_get_index(ah->dev, NULL, gpio, flags);
+
+ if (IS_ERR(gpiod)) {
+ err = PTR_ERR(gpiod);
ath_err(ath9k_hw_common(ah), "request GPIO%d failed:%d\n",
gpio, err);
return;
}
- ah->caps.gpio_requested |= BIT(gpio);
+ gpiod_set_consumer_name(gpiod, label);
+ ah->gpiods[gpio] = gpiod;
}
static void ath9k_hw_gpio_cfg_wmac(struct ath_hw *ah, u32 gpio, bool out,
@@ -2800,11 +2806,6 @@ void ath9k_hw_gpio_free(struct ath_hw *ah, u32 gpio)
return;
WARN_ON(gpio >= ah->caps.num_gpio_pins);
-
- if (ah->caps.gpio_requested & BIT(gpio)) {
- gpio_free(gpio);
- ah->caps.gpio_requested &= ~BIT(gpio);
- }
}
EXPORT_SYMBOL(ath9k_hw_gpio_free);
@@ -2832,8 +2833,8 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
val = REG_READ(ah, AR_GPIO_IN(ah)) & BIT(gpio);
else
val = MS_REG_READ(AR, gpio);
- } else if (BIT(gpio) & ah->caps.gpio_requested) {
- val = gpio_get_value(gpio) & BIT(gpio);
+ } else if (ah->gpiods[gpio]) {
+ val = gpiod_get_value(ah->gpiods[gpio]);
} else {
WARN_ON(1);
}
@@ -2856,8 +2857,8 @@ void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val)
AR7010_GPIO_OUT : AR_GPIO_IN_OUT(ah);
REG_RMW(ah, out_addr, val << gpio, BIT(gpio));
- } else if (BIT(gpio) & ah->caps.gpio_requested) {
- gpio_set_value(gpio, val);
+ } else if (ah->gpiods[gpio]) {
+ gpiod_set_value(ah->gpiods[gpio], val);
} else {
WARN_ON(1);
}
@@ -19,6 +19,7 @@
#include <linux/if_ether.h>
#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
#include <linux/io.h>
#include <linux/firmware.h>
@@ -302,7 +303,6 @@ struct ath9k_hw_capabilities {
u8 max_rxchains;
u8 num_gpio_pins;
u32 gpio_mask;
- u32 gpio_requested;
u8 rx_hp_qdepth;
u8 rx_lp_qdepth;
u8 rx_status_len;
@@ -783,6 +783,7 @@ struct ath_hw {
struct ath9k_hw_capabilities caps;
struct ath9k_channel channels[ATH9K_NUM_CHANNELS];
struct ath9k_channel *curchan;
+ struct gpio_desc *gpiods[32];
union {
struct ar5416_eeprom_def def;
The ath9k has an odd use of system-wide GPIOs: if the chip does not have internal GPIO capability, it will try to obtain a GPIO line from the system GPIO controller: if (BIT(gpio) & ah->caps.gpio_mask) ath9k_hw_gpio_cfg_wmac(...); else if (AR_SREV_SOC(ah)) ath9k_hw_gpio_cfg_soc(ah, gpio, out, label); Where ath9k_hw_gpio_cfg_soc() will attempt to issue gpio_request_one() passing the local GPIO number of the controller (0..31) to gpio_request_one(). This is somewhat peculiar and possibly even dangerous: there is nowadays no guarantee of the numbering of these system-wide GPIOs, and assuming that GPIO 0..31 as used by ath9k would correspond to GPIOs 0..31 on the system as a whole seems a bit wild. My best guess is that everyone actually using this driver has support for the local (custom) GPIO API and the bit in h->caps.gpio_mask is always set for any GPIO the driver may try to obtain, so this facility to use system-wide GPIOs is actually unused and could be deleted. Anyway: I cannot know if this is really the case, so implement a fallback handling using GPIO descriptors obtained from the ah->dev device indexed 0..31. These can for example be passed in the device tree, ACPI or through board files. I doubt that anyone will use them, but this makes it possible to obtain a system-wide GPIO for any of the 0..31 GPIOs potentially requested by the driver. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> --- drivers/net/wireless/ath/ath9k/hw.c | 29 +++++++++++++++-------------- drivers/net/wireless/ath/ath9k/hw.h | 3 ++- 2 files changed, 17 insertions(+), 15 deletions(-)