summaryrefslogtreecommitdiff
path: root/drivers/gpio
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2023-05-01 12:05:21 +0300
committerLinus Walleij <linus.walleij@linaro.org>2023-05-24 16:01:55 +0300
commitd5f4fa60d63aa54ae33339895b88d8932b6037ed (patch)
tree2212145423b10cbaf8a326e25bb8f1ae43b96aa7 /drivers/gpio
parentc729baa8604226a8f878296bd145ab4046c80b12 (diff)
downloadlinux-d5f4fa60d63aa54ae33339895b88d8932b6037ed.tar.xz
ARM/gpio: Push OMAP2 quirk down into TWL4030 driver
The TWL4030 GPIO driver has a custom platform data .set_up() callback to call back into the platform and do misc stuff such as hog and export a GPIO for WLAN PWR on a specific OMAP3 board. Avoid all the kludgery in the platform data and the boardfile and just put the quirks right into the driver. Make it conditional on OMAP3. I think the exported GPIO is used by some kind of userspace so ordinary DTS hogs will probably not work. Fixes: 92bf78b33b0b ("gpio: omap: use dynamic allocation of base") Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpio-twl4030.c52
1 files changed, 36 insertions, 16 deletions
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
index c1bb2c3ca6f2..446599ac234a 100644
--- a/drivers/gpio/gpio-twl4030.c
+++ b/drivers/gpio/gpio-twl4030.c
@@ -17,7 +17,9 @@
#include <linux/interrupt.h>
#include <linux/kthread.h>
#include <linux/irq.h>
+#include <linux/gpio/machine.h>
#include <linux/gpio/driver.h>
+#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/irqdomain.h>
@@ -465,8 +467,7 @@ static int gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
REG_GPIO_DEBEN1, 3);
}
-static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev,
- struct twl4030_gpio_platform_data *pdata)
+static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev)
{
struct twl4030_gpio_platform_data *omap_twl_info;
@@ -474,9 +475,6 @@ static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev,
if (!omap_twl_info)
return NULL;
- if (pdata)
- *omap_twl_info = *pdata;
-
omap_twl_info->use_leds = of_property_read_bool(dev->of_node,
"ti,use-leds");
@@ -504,9 +502,18 @@ static int gpio_twl4030_remove(struct platform_device *pdev)
return 0;
}
+/* Called from the registered devm action */
+static void gpio_twl4030_power_off_action(void *data)
+{
+ struct gpio_desc *d = data;
+
+ gpiod_unexport(d);
+ gpiochip_free_own_desc(d);
+}
+
static int gpio_twl4030_probe(struct platform_device *pdev)
{
- struct twl4030_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct twl4030_gpio_platform_data *pdata;
struct device_node *node = pdev->dev.of_node;
struct gpio_twl4030_priv *priv;
int ret, irq_base;
@@ -546,9 +553,7 @@ no_irqs:
mutex_init(&priv->mutex);
- if (node)
- pdata = of_gpio_twl4030(&pdev->dev, pdata);
-
+ pdata = of_gpio_twl4030(&pdev->dev);
if (pdata == NULL) {
dev_err(&pdev->dev, "Platform data is missing\n");
return -ENXIO;
@@ -585,17 +590,32 @@ no_irqs:
goto out;
}
- platform_set_drvdata(pdev, priv);
+ /*
+ * Special quirk for the OMAP3 to hog and export a WLAN power
+ * GPIO.
+ */
+ if (IS_ENABLED(CONFIG_ARCH_OMAP3) &&
+ of_machine_is_compatible("compulab,omap3-sbc-t3730")) {
+ struct gpio_desc *d;
- if (pdata->setup) {
- int status;
+ d = gpiochip_request_own_desc(&priv->gpio_chip,
+ 2, "wlan pwr",
+ GPIO_ACTIVE_HIGH,
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(d))
+ return dev_err_probe(&pdev->dev, PTR_ERR(d),
+ "unable to hog wlan pwr GPIO\n");
+
+ gpiod_export(d, 0);
+
+ ret = devm_add_action_or_reset(&pdev->dev, gpio_twl4030_power_off_action, d);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to install power off handler\n");
- status = pdata->setup(&pdev->dev, priv->gpio_chip.base,
- TWL4030_GPIO_MAX);
- if (status)
- dev_dbg(&pdev->dev, "setup --> %d\n", status);
}
+ platform_set_drvdata(pdev, priv);
out:
return ret;
}