diff options
Diffstat (limited to 'drivers/gpio/gpio-wm8994.c')
| -rw-r--r-- | drivers/gpio/gpio-wm8994.c | 106 |
1 files changed, 50 insertions, 56 deletions
diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c index ae409fd94af7..a0665cf3ff2f 100644 --- a/drivers/gpio/gpio-wm8994.c +++ b/drivers/gpio/gpio-wm8994.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * gpiolib support for Wolfson WM8994 * @@ -5,17 +6,13 @@ * * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * */ +#include <linux/cleanup.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h> #include <linux/mfd/core.h> #include <linux/platform_device.h> #include <linux/seq_file.h> @@ -31,14 +28,9 @@ struct wm8994_gpio { struct gpio_chip gpio_chip; }; -static inline struct wm8994_gpio *to_wm8994_gpio(struct gpio_chip *chip) -{ - return container_of(chip, struct wm8994_gpio, gpio_chip); -} - static int wm8994_gpio_request(struct gpio_chip *chip, unsigned offset) { - struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); + struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip); struct wm8994 *wm8994 = wm8994_gpio->wm8994; switch (wm8994->type) { @@ -61,7 +53,7 @@ static int wm8994_gpio_request(struct gpio_chip *chip, unsigned offset) static int wm8994_gpio_direction_in(struct gpio_chip *chip, unsigned offset) { - struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); + struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip); struct wm8994 *wm8994 = wm8994_gpio->wm8994; return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, @@ -70,7 +62,7 @@ static int wm8994_gpio_direction_in(struct gpio_chip *chip, unsigned offset) static int wm8994_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); + struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip); struct wm8994 *wm8994 = wm8994_gpio->wm8994; int ret; @@ -87,7 +79,7 @@ static int wm8994_gpio_get(struct gpio_chip *chip, unsigned offset) static int wm8994_gpio_direction_out(struct gpio_chip *chip, unsigned offset, int value) { - struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); + struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip); struct wm8994 *wm8994 = wm8994_gpio->wm8994; if (value) @@ -97,20 +89,43 @@ static int wm8994_gpio_direction_out(struct gpio_chip *chip, WM8994_GPN_DIR | WM8994_GPN_LVL, value); } -static void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +static int wm8994_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) { - struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); + struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip); struct wm8994 *wm8994 = wm8994_gpio->wm8994; if (value) value = WM8994_GPN_LVL; - wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value); + return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, + value); +} + +static int wm8994_gpio_set_config(struct gpio_chip *chip, unsigned int offset, + unsigned long config) +{ + struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip); + struct wm8994 *wm8994 = wm8994_gpio->wm8994; + + switch (pinconf_to_config_param(config)) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, + WM8994_GPN_OP_CFG_MASK, + WM8994_GPN_OP_CFG); + case PIN_CONFIG_DRIVE_PUSH_PULL: + return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, + WM8994_GPN_OP_CFG_MASK, 0); + default: + break; + } + + return -ENOTSUPP; } static int wm8994_gpio_to_irq(struct gpio_chip *chip, unsigned offset) { - struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); + struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip); struct wm8994 *wm8994 = wm8994_gpio->wm8994; return regmap_irq_get_virq(wm8994->irq_data, offset); @@ -174,31 +189,31 @@ static const char *wm8994_gpio_fn(u16 fn) static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) { - struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); + struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip); struct wm8994 *wm8994 = wm8994_gpio->wm8994; int i; for (i = 0; i < chip->ngpio; i++) { - int gpio = i + chip->base; int reg; - const char *label; /* We report the GPIO even if it's not requested since * we're also reporting things like alternate * functions which apply even when the GPIO is not in * use as a GPIO. */ - label = gpiochip_is_requested(chip, i); - if (!label) - label = "Unrequested"; + char *label __free(kfree) = gpiochip_dup_line_label(chip, i); + if (IS_ERR(label)) { + dev_err(wm8994->dev, "Failed to duplicate label\n"); + continue; + } - seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label); + seq_printf(s, " gpio-%-3d (%-20.20s) ", i, + label ?: "Unrequested"); reg = wm8994_reg_read(wm8994, WM8994_GPIO_1 + i); if (reg < 0) { dev_err(wm8994->dev, - "GPIO control %d read failed: %d\n", - gpio, reg); + "GPIO control %d read failed: %d\n", i, reg); seq_printf(s, "\n"); continue; } @@ -222,7 +237,7 @@ static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) if (reg & WM8994_GPN_OP_CFG) seq_printf(s, "open drain "); else - seq_printf(s, "CMOS "); + seq_printf(s, "push-pull "); seq_printf(s, "%s (%x)\n", wm8994_gpio_fn(reg & WM8994_GPN_FN_MASK), reg); @@ -232,7 +247,7 @@ static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) #define wm8994_gpio_dbg_show NULL #endif -static struct gpio_chip template_chip = { +static const struct gpio_chip template_chip = { .label = "wm8994", .owner = THIS_MODULE, .request = wm8994_gpio_request, @@ -240,17 +255,17 @@ static struct gpio_chip template_chip = { .get = wm8994_gpio_get, .direction_output = wm8994_gpio_direction_out, .set = wm8994_gpio_set, + .set_config = wm8994_gpio_set_config, .to_irq = wm8994_gpio_to_irq, .dbg_show = wm8994_gpio_dbg_show, - .can_sleep = 1, + .can_sleep = true, }; static int wm8994_gpio_probe(struct platform_device *pdev) { struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent); - struct wm8994_pdata *pdata = wm8994->dev->platform_data; + struct wm8994_pdata *pdata = dev_get_platdata(wm8994->dev); struct wm8994_gpio *wm8994_gpio; - int ret; wm8994_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm8994_gpio), GFP_KERNEL); @@ -260,39 +275,18 @@ static int wm8994_gpio_probe(struct platform_device *pdev) wm8994_gpio->wm8994 = wm8994; wm8994_gpio->gpio_chip = template_chip; wm8994_gpio->gpio_chip.ngpio = WM8994_GPIO_MAX; - wm8994_gpio->gpio_chip.dev = &pdev->dev; + wm8994_gpio->gpio_chip.parent = &pdev->dev; if (pdata && pdata->gpio_base) wm8994_gpio->gpio_chip.base = pdata->gpio_base; else wm8994_gpio->gpio_chip.base = -1; - ret = gpiochip_add(&wm8994_gpio->gpio_chip); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", - ret); - goto err; - } - - platform_set_drvdata(pdev, wm8994_gpio); - - return ret; - -err: - return ret; -} - -static int wm8994_gpio_remove(struct platform_device *pdev) -{ - struct wm8994_gpio *wm8994_gpio = platform_get_drvdata(pdev); - - return gpiochip_remove(&wm8994_gpio->gpio_chip); + return devm_gpiochip_add_data(&pdev->dev, &wm8994_gpio->gpio_chip, wm8994_gpio); } static struct platform_driver wm8994_gpio_driver = { .driver.name = "wm8994-gpio", - .driver.owner = THIS_MODULE, .probe = wm8994_gpio_probe, - .remove = wm8994_gpio_remove, }; static int __init wm8994_gpio_init(void) |
