diff options
Diffstat (limited to 'drivers/gpio')
62 files changed, 776 insertions, 410 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 44f922e10db2..6802e549621b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1263,6 +1263,7 @@ config GPIO_ADP5520 config GPIO_ADP5585 tristate "GPIO Support for ADP5585" depends on MFD_ADP5585 + select GPIOLIB_IRQCHIP help This option enables support for the GPIO function found in the Analog Devices ADP5585. @@ -1501,7 +1502,7 @@ config GPIO_MAX77759 called gpio-max77759. config GPIO_PALMAS - bool "TI PALMAS series PMICs GPIO" + tristate "TI PALMAS series PMICs GPIO" depends on MFD_PALMAS help Select this option to enable GPIO driver for the TI PALMAS diff --git a/drivers/gpio/TODO b/drivers/gpio/TODO index 4a8b349f2483..ef53892cb44d 100644 --- a/drivers/gpio/TODO +++ b/drivers/gpio/TODO @@ -131,6 +131,11 @@ Work items: helpers (x86 inb()/outb()) and convert port-mapped I/O drivers to use this with dry-coding and sending to maintainers to test +- Move the MMIO GPIO specific fields out of struct gpio_chip into a + dedicated structure. Currently every GPIO chip has them if gpio-mmio is + enabled in Kconfig even if it itself doesn't register with the helper + library. + ------------------------------------------------------------------------------- Generic regmap GPIO diff --git a/drivers/gpio/gpio-74xx-mmio.c b/drivers/gpio/gpio-74xx-mmio.c index c7ac5a9ffb1f..3ba21add3a1c 100644 --- a/drivers/gpio/gpio-74xx-mmio.c +++ b/drivers/gpio/gpio-74xx-mmio.c @@ -100,7 +100,7 @@ static int mmio_74xx_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) struct mmio_74xx_gpio_priv *priv = gpiochip_get_data(gc); if (priv->flags & MMIO_74XX_DIR_OUT) { - gc->set(gc, gpio, val); + gc->set_rv(gc, gpio, val); return 0; } diff --git a/drivers/gpio/gpio-adp5585.c b/drivers/gpio/gpio-adp5585.c index d5c0f1b267c8..b2c8836c5f84 100644 --- a/drivers/gpio/gpio-adp5585.c +++ b/drivers/gpio/gpio-adp5585.c @@ -4,67 +4,131 @@ * * Copyright 2022 NXP * Copyright 2024 Ideas on Board Oy + * Copyright 2025 Analog Devices, Inc. */ +#include <linux/bitmap.h> +#include <linux/bitops.h> +#include <linux/container_of.h> #include <linux/device.h> #include <linux/gpio/driver.h> #include <linux/mfd/adp5585.h> #include <linux/module.h> +#include <linux/mutex.h> +#include <linux/notifier.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/types.h> -#define ADP5585_GPIO_MAX 11 +/* + * Bank 0 covers pins "GPIO 1/R0" to "GPIO 6/R5", numbered 0 to 5 by the + * driver, and bank 1 covers pins "GPIO 7/C0" to "GPIO 11/C4", numbered 6 to + * 10. Some variants of the ADP5585 don't support "GPIO 6/R5". As the driver + * uses identical GPIO numbering for all variants to avoid confusion, GPIO 5 is + * marked as reserved in the device tree for variants that don't support it. + */ +#define ADP5585_BANK(n) ((n) >= 6 ? 1 : 0) +#define ADP5585_BIT(n) ((n) >= 6 ? BIT((n) - 6) : BIT(n)) + +/* + * Bank 0 covers pins "GPIO 1/R0" to "GPIO 8/R7", numbered 0 to 7 by the + * driver, bank 1 covers pins "GPIO 9/C0" to "GPIO 16/C7", numbered 8 to + * 15 and bank 3 covers pins "GPIO 17/C8" to "GPIO 19/C10", numbered 16 to 18. + */ +#define ADP5589_BANK(n) ((n) >> 3) +#define ADP5589_BIT(n) BIT((n) & 0x7) + +struct adp5585_gpio_chip { + int (*bank)(unsigned int off); + int (*bit)(unsigned int off); + unsigned int debounce_dis_a; + unsigned int rpull_cfg_a; + unsigned int gpo_data_a; + unsigned int gpo_out_a; + unsigned int gpio_dir_a; + unsigned int gpi_stat_a; + unsigned int gpi_int_lvl_a; + unsigned int gpi_ev_a; + unsigned int gpi_ev_min; + unsigned int gpi_ev_max; + bool has_bias_hole; +}; struct adp5585_gpio_dev { struct gpio_chip gpio_chip; + struct notifier_block nb; + const struct adp5585_gpio_chip *info; struct regmap *regmap; + unsigned long irq_mask; + unsigned long irq_en; + unsigned long irq_active_high; + /* used for irqchip bus locking */ + struct mutex bus_lock; }; +static int adp5585_gpio_bank(unsigned int off) +{ + return ADP5585_BANK(off); +} + +static int adp5585_gpio_bit(unsigned int off) +{ + return ADP5585_BIT(off); +} + +static int adp5589_gpio_bank(unsigned int off) +{ + return ADP5589_BANK(off); +} + +static int adp5589_gpio_bit(unsigned int off) +{ + return ADP5589_BIT(off); +} + static int adp5585_gpio_get_direction(struct gpio_chip *chip, unsigned int off) { struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip); - unsigned int bank = ADP5585_BANK(off); - unsigned int bit = ADP5585_BIT(off); + const struct adp5585_gpio_chip *info = adp5585_gpio->info; unsigned int val; - regmap_read(adp5585_gpio->regmap, ADP5585_GPIO_DIRECTION_A + bank, &val); + regmap_read(adp5585_gpio->regmap, info->gpio_dir_a + info->bank(off), &val); - return val & bit ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN; + return val & info->bit(off) ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN; } static int adp5585_gpio_direction_input(struct gpio_chip *chip, unsigned int off) { struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip); - unsigned int bank = ADP5585_BANK(off); - unsigned int bit = ADP5585_BIT(off); + const struct adp5585_gpio_chip *info = adp5585_gpio->info; - return regmap_clear_bits(adp5585_gpio->regmap, - ADP5585_GPIO_DIRECTION_A + bank, bit); + return regmap_clear_bits(adp5585_gpio->regmap, info->gpio_dir_a + info->bank(off), + info->bit(off)); } static int adp5585_gpio_direction_output(struct gpio_chip *chip, unsigned int off, int val) { struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip); - unsigned int bank = ADP5585_BANK(off); - unsigned int bit = ADP5585_BIT(off); + const struct adp5585_gpio_chip *info = adp5585_gpio->info; + unsigned int bank = info->bank(off); + unsigned int bit = info->bit(off); int ret; - ret = regmap_update_bits(adp5585_gpio->regmap, - ADP5585_GPO_DATA_OUT_A + bank, bit, - val ? bit : 0); + ret = regmap_update_bits(adp5585_gpio->regmap, info->gpo_data_a + bank, + bit, val ? bit : 0); if (ret) return ret; - return regmap_set_bits(adp5585_gpio->regmap, - ADP5585_GPIO_DIRECTION_A + bank, bit); + return regmap_set_bits(adp5585_gpio->regmap, info->gpio_dir_a + bank, + bit); } static int adp5585_gpio_get_value(struct gpio_chip *chip, unsigned int off) { struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip); - unsigned int bank = ADP5585_BANK(off); - unsigned int bit = ADP5585_BIT(off); + const struct adp5585_gpio_chip *info = adp5585_gpio->info; + unsigned int bank = info->bank(off); + unsigned int bit = info->bit(off); unsigned int reg; unsigned int val; @@ -79,8 +143,8 @@ static int adp5585_gpio_get_value(struct gpio_chip *chip, unsigned int off) * .direction_input(), .direction_output() or .set() operations racing * with this. */ - regmap_read(adp5585_gpio->regmap, ADP5585_GPIO_DIRECTION_A + bank, &val); - reg = val & bit ? ADP5585_GPO_DATA_OUT_A : ADP5585_GPI_STATUS_A; + regmap_read(adp5585_gpio->regmap, info->gpio_dir_a + bank, &val); + reg = val & bit ? info->gpo_data_a : info->gpi_stat_a; regmap_read(adp5585_gpio->regmap, reg + bank, &val); return !!(val & bit); @@ -90,17 +154,17 @@ static int adp5585_gpio_set_value(struct gpio_chip *chip, unsigned int off, int val) { struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip); - unsigned int bank = ADP5585_BANK(off); - unsigned int bit = ADP5585_BIT(off); + const struct adp5585_gpio_chip *info = adp5585_gpio->info; + unsigned int bit = adp5585_gpio->info->bit(off); - return regmap_update_bits(adp5585_gpio->regmap, - ADP5585_GPO_DATA_OUT_A + bank, + return regmap_update_bits(adp5585_gpio->regmap, info->gpo_data_a + info->bank(off), bit, val ? bit : 0); } static int adp5585_gpio_set_bias(struct adp5585_gpio_dev *adp5585_gpio, unsigned int off, unsigned int bias) { + const struct adp5585_gpio_chip *info = adp5585_gpio->info; unsigned int bit, reg, mask, val; /* @@ -108,8 +172,10 @@ static int adp5585_gpio_set_bias(struct adp5585_gpio_dev *adp5585_gpio, * consecutive registers ADP5585_RPULL_CONFIG_*, with a hole of 4 bits * after R5. */ - bit = off * 2 + (off > 5 ? 4 : 0); - reg = ADP5585_RPULL_CONFIG_A + bit / 8; + bit = off * 2; + if (info->has_bias_hole) + bit += (off > 5 ? 4 : 0); + reg = info->rpull_cfg_a + bit / 8; mask = ADP5585_Rx_PULL_CFG_MASK << (bit % 8); val = bias << (bit % 8); @@ -119,22 +185,22 @@ static int adp5585_gpio_set_bias(struct adp5585_gpio_dev *adp5585_gpio, static int adp5585_gpio_set_drive(struct adp5585_gpio_dev *adp5585_gpio, unsigned int off, enum pin_config_param drive) { - unsigned int bank = ADP5585_BANK(off); - unsigned int bit = ADP5585_BIT(off); + const struct adp5585_gpio_chip *info = adp5585_gpio->info; + unsigned int bit = adp5585_gpio->info->bit(off); return regmap_update_bits(adp5585_gpio->regmap, - ADP5585_GPO_OUT_MODE_A + bank, bit, + info->gpo_out_a + info->bank(off), bit, drive == PIN_CONFIG_DRIVE_OPEN_DRAIN ? bit : 0); } static int adp5585_gpio_set_debounce(struct adp5585_gpio_dev *adp5585_gpio, unsigned int off, unsigned int debounce) { - unsigned int bank = ADP5585_BANK(off); - unsigned int bit = ADP5585_BIT(off); + const struct adp5585_gpio_chip *info = adp5585_gpio->info; + unsigned int bit = adp5585_gpio->info->bit(off); return regmap_update_bits(adp5585_gpio->regmap, - ADP5585_DEBOUNCE_DIS_A + bank, bit, + info->debounce_dis_a + info->bank(off), bit, debounce ? 0 : bit); } @@ -172,11 +238,175 @@ static int adp5585_gpio_set_config(struct gpio_chip *chip, unsigned int off, }; } +static int adp5585_gpio_request(struct gpio_chip *chip, unsigned int off) +{ + struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip); + const struct adp5585_gpio_chip *info = adp5585_gpio->info; + struct device *dev = chip->parent; + struct adp5585_dev *adp5585 = dev_get_drvdata(dev->parent); + const struct adp5585_regs *regs = adp5585->regs; + int ret; + + ret = test_and_set_bit(off, adp5585->pin_usage); + if (ret) + return -EBUSY; + + /* make sure it's configured for GPIO */ + return regmap_clear_bits(adp5585_gpio->regmap, + regs->pin_cfg_a + info->bank(off), + info->bit(off)); +} + +static void adp5585_gpio_free(struct gpio_chip *chip, unsigned int off) +{ + struct device *dev = chip->parent; + struct adp5585_dev *adp5585 = dev_get_drvdata(dev->parent); + + clear_bit(off, adp5585->pin_usage); +} + +static int adp5585_gpio_key_event(struct notifier_block *nb, unsigned long key, + void *data) +{ + struct adp5585_gpio_dev *adp5585_gpio = container_of(nb, struct adp5585_gpio_dev, nb); + struct device *dev = adp5585_gpio->gpio_chip.parent; + unsigned long key_press = (unsigned long)data; + unsigned int irq, irq_type; + struct irq_data *irqd; + bool active_high; + unsigned int off; + + /* make sure the event is for me */ + if (key < adp5585_gpio->info->gpi_ev_min || key > adp5585_gpio->info->gpi_ev_max) + return NOTIFY_DONE; + + off = key - adp5585_gpio->info->gpi_ev_min; + active_high = test_bit(off, &adp5585_gpio->irq_active_high); + + irq = irq_find_mapping(adp5585_gpio->gpio_chip.irq.domain, off); + if (!irq) + return NOTIFY_BAD; + + irqd = irq_get_irq_data(irq); + if (!irqd) { + dev_err(dev, "Could not get irq(%u) data\n", irq); + return NOTIFY_BAD; + } + + dev_dbg_ratelimited(dev, "gpio-keys event(%u) press=%lu, a_high=%u\n", + off, key_press, active_high); + + if (!active_high) + key_press = !key_press; + + irq_type = irqd_get_trigger_type(irqd); + + if ((irq_type & IRQ_TYPE_EDGE_RISING && key_press) || + (irq_type & IRQ_TYPE_EDGE_FALLING && !key_press)) + handle_nested_irq(irq); + + return NOTIFY_STOP; +} + +static void adp5585_irq_bus_lock(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(gc); + + mutex_lock(&adp5585_gpio->bus_lock); +} + +static void adp5585_irq_bus_sync_unlock(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip); + const struct adp5585_gpio_chip *info = adp5585_gpio->info; + irq_hw_number_t hwirq = irqd_to_hwirq(d); + bool active_high = test_bit(hwirq, &adp5585_gpio->irq_active_high); + bool enabled = test_bit(hwirq, &adp5585_gpio->irq_en); + bool masked = test_bit(hwirq, &adp5585_gpio->irq_mask); + unsigned int bank = adp5585_gpio->info->bank(hwirq); + unsigned int bit = adp5585_gpio->info->bit(hwirq); + + if (masked && !enabled) + goto out_unlock; + if (!masked && enabled) + goto out_unlock; + + regmap_update_bits(adp5585_gpio->regmap, info->gpi_int_lvl_a + bank, bit, + active_high ? bit : 0); + regmap_update_bits(adp5585_gpio->regmap, info->gpi_ev_a + bank, bit, + masked ? 0 : bit); + assign_bit(hwirq, &adp5585_gpio->irq_en, !masked); + +out_unlock: + mutex_unlock(&adp5585_gpio->bus_lock); +} + +static void adp5585_irq_mask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(gc); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + __set_bit(hwirq, &adp5585_gpio->irq_mask); + gpiochip_disable_irq(gc, hwirq); +} + +static void adp5585_irq_unmask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(gc); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + gpiochip_enable_irq(gc, hwirq); + __clear_bit(hwirq, &adp5585_gpio->irq_mask); +} + +static int adp5585_irq_set_type(struct irq_data *d, unsigned int type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(gc); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + if (!(type & IRQ_TYPE_EDGE_BOTH)) + return -EINVAL; + + assign_bit(hwirq, &adp5585_gpio->irq_active_high, + type == IRQ_TYPE_EDGE_RISING); + + irq_set_handler_locked(d, handle_edge_irq); + return 0; +} + +static const struct irq_chip adp5585_irq_chip = { + .name = "adp5585", + .irq_mask = adp5585_irq_mask, + .irq_unmask = adp5585_irq_unmask, + .irq_bus_lock = adp5585_irq_bus_lock, + .irq_bus_sync_unlock = adp5585_irq_bus_sync_unlock, + .irq_set_type = adp5585_irq_set_type, + .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + +static void adp5585_gpio_unreg_notifier(void *data) +{ + struct adp5585_gpio_dev *adp5585_gpio = data; + struct device *dev = adp5585_gpio->gpio_chip.parent; + struct adp5585_dev *adp5585 = dev_get_drvdata(dev->parent); + + blocking_notifier_chain_unregister(&adp5585->event_notifier, + &adp5585_gpio->nb); +} + static int adp5585_gpio_probe(struct platform_device *pdev) { struct adp5585_dev *adp5585 = dev_get_drvdata(pdev->dev.parent); + const struct platform_device_id *id = platform_get_device_id(pdev); struct adp5585_gpio_dev *adp5585_gpio; struct device *dev = &pdev->dev; + struct gpio_irq_chip *girq; struct gpio_chip *gc; int ret; @@ -186,6 +416,10 @@ static int adp5585_gpio_probe(struct platform_device *pdev) adp5585_gpio->regmap = adp5585->regmap; + adp5585_gpio->info = (const struct adp5585_gpio_chip *)id->driver_data; + if (!adp5585_gpio->info) + return -ENODEV; + device_set_of_node_from_dev(dev, dev->parent); gc = &adp5585_gpio->gpio_chip; @@ -196,13 +430,43 @@ static int adp5585_gpio_probe(struct platform_device *pdev) gc->get = adp5585_gpio_get_value; gc->set_rv = adp5585_gpio_set_value; gc->set_config = adp5585_gpio_set_config; + gc->request = adp5585_gpio_request; + gc->free = adp5585_gpio_free; gc->can_sleep = true; gc->base = -1; - gc->ngpio = ADP5585_GPIO_MAX; + gc->ngpio = adp5585->n_pins; gc->label = pdev->name; gc->owner = THIS_MODULE; + if (device_property_present(dev->parent, "interrupt-controller")) { + if (!adp5585->irq) + return dev_err_probe(dev, -EINVAL, + "Unable to serve as interrupt controller without IRQ\n"); + + girq = &adp5585_gpio->gpio_chip.irq; + gpio_irq_chip_set_chip(girq, &adp5585_irq_chip); + girq->handler = handle_bad_irq; + girq->threaded = true; + + adp5585_gpio->nb.notifier_call = adp5585_gpio_key_event; + ret = blocking_notifier_chain_register(&adp5585->event_notifier, + &adp5585_gpio->nb); + if (ret) + return ret; + + ret = devm_add_action_or_reset(dev, adp5585_gpio_unreg_notifier, + adp5585_gpio); + if (ret) + return ret; + } + + /* everything masked by default */ + adp5585_gpio->irq_mask = ~0UL; + + ret = devm_mutex_init(dev, &adp5585_gpio->bus_lock); + if (ret) + return ret; ret = devm_gpiochip_add_data(dev, &adp5585_gpio->gpio_chip, adp5585_gpio); if (ret) @@ -211,8 +475,40 @@ static int adp5585_gpio_probe(struct platform_device *pdev) return 0; } +static const struct adp5585_gpio_chip adp5585_gpio_chip_info = { + .bank = adp5585_gpio_bank, + .bit = adp5585_gpio_bit, + .debounce_dis_a = ADP5585_DEBOUNCE_DIS_A, + .rpull_cfg_a = ADP5585_RPULL_CONFIG_A, + .gpo_data_a = ADP5585_GPO_DATA_OUT_A, + .gpo_out_a = ADP5585_GPO_OUT_MODE_A, + .gpio_dir_a = ADP5585_GPIO_DIRECTION_A, + .gpi_stat_a = ADP5585_GPI_STATUS_A, + .has_bias_hole = true, + .gpi_ev_min = ADP5585_GPI_EVENT_START, + .gpi_ev_max = ADP5585_GPI_EVENT_END, + .gpi_int_lvl_a = ADP5585_GPI_INT_LEVEL_A, + .gpi_ev_a = ADP5585_GPI_EVENT_EN_A, +}; + +static const struct adp5585_gpio_chip adp5589_gpio_chip_info = { + .bank = adp5589_gpio_bank, + .bit = adp5589_gpio_bit, + .debounce_dis_a = ADP5589_DEBOUNCE_DIS_A, + .rpull_cfg_a = ADP5589_RPULL_CONFIG_A, + .gpo_data_a = ADP5589_GPO_DATA_OUT_A, + .gpo_out_a = ADP5589_GPO_OUT_MODE_A, + .gpio_dir_a = ADP5589_GPIO_DIRECTION_A, + .gpi_stat_a = ADP5589_GPI_STATUS_A, + .gpi_ev_min = ADP5589_GPI_EVENT_START, + .gpi_ev_max = ADP5589_GPI_EVENT_END, + .gpi_int_lvl_a = ADP5589_GPI_INT_LEVEL_A, + .gpi_ev_a = ADP5589_GPI_EVENT_EN_A, +}; + static const struct platform_device_id adp5585_gpio_id_table[] = { - { "adp5585-gpio" }, + { "adp5585-gpio", (kernel_ulong_t)&adp5585_gpio_chip_info }, + { "adp5589-gpio", (kernel_ulong_t)&adp5589_gpio_chip_info }, { /* Sentinel */ } }; MODULE_DEVICE_TABLE(platform, adp5585_gpio_id_table); diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index e7671bcd5c07..e29a9589b3cc 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -436,10 +436,8 @@ static int brcmstb_gpio_irq_setup(struct platform_device *pdev, struct device_node *np = dev->of_node; int err; - priv->irq_domain = - irq_domain_create_linear(of_fwnode_handle(np), priv->num_gpios, - &brcmstb_gpio_irq_domain_ops, - priv); + priv->irq_domain = irq_domain_create_linear(dev_fwnode(dev), priv->num_gpios, + &brcmstb_gpio_irq_domain_ops, priv); if (!priv->irq_domain) { dev_err(dev, "Couldn't allocate IRQ domain\n"); return -ENXIO; diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c index d69a24dd4828..c0c8d29d0dce 100644 --- a/drivers/gpio/gpio-clps711x.c +++ b/drivers/gpio/gpio-clps711x.c @@ -62,7 +62,6 @@ static int clps711x_gpio_probe(struct platform_device *pdev) gc->base = -1; gc->owner = THIS_MODULE; - platform_set_drvdata(pdev, gc); return devm_gpiochip_add_data(&pdev->dev, gc, NULL); } diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 80a82492171e..8f3a36d0191d 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -478,7 +478,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) return irq; } - irq_domain = irq_domain_create_legacy(of_fwnode_handle(dev->of_node), ngpio, irq, 0, + irq_domain = irq_domain_create_legacy(dev_fwnode(dev), ngpio, irq, 0, &davinci_gpio_irq_ops, chips); if (!irq_domain) { dev_err(dev, "Couldn't register an IRQ domain\n"); diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index a5e6e446f39c..015f1ac32dd9 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -325,8 +325,7 @@ static int em_gio_probe(struct platform_device *pdev) irq_chip->irq_release_resources = em_gio_irq_relres; irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND; - p->irq_domain = irq_domain_create_simple(of_fwnode_handle(dev->of_node), - ngpios, 0, + p->irq_domain = irq_domain_create_simple(dev_fwnode(dev), ngpios, 0, &em_gio_irq_domain_ops, p); if (!p->irq_domain) { dev_err(dev, "cannot initialize irq domain\n"); diff --git a/drivers/gpio/gpio-en7523.c b/drivers/gpio/gpio-en7523.c index 69834db2c1cf..c08069d0d104 100644 --- a/drivers/gpio/gpio-en7523.c +++ b/drivers/gpio/gpio-en7523.c @@ -50,7 +50,7 @@ static int airoha_dir_set(struct gpio_chip *gc, unsigned int gpio, iowrite32(dir, ctrl->dir[gpio / 16]); if (out) - gc->set(gc, gpio, val); + gc->set_rv(gc, gpio, val); iowrite32(output, ctrl->output); diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c index d38a2d9854ca..f3f8bab62f94 100644 --- a/drivers/gpio/gpio-grgpio.c +++ b/drivers/gpio/gpio-grgpio.c @@ -402,9 +402,8 @@ static int grgpio_probe(struct platform_device *ofdev) return -EINVAL; } - priv->domain = irq_domain_create_linear(of_fwnode_handle(np), gc->ngpio, - &grgpio_irq_domain_ops, - priv); + priv->domain = irq_domain_create_linear(dev_fwnode(&ofdev->dev), gc->ngpio, + &grgpio_irq_domain_ops, priv); if (!priv->domain) { dev_err(dev, "Could not add irq domain\n"); return -EINVAL; diff --git a/drivers/gpio/gpio-lpc18xx.c b/drivers/gpio/gpio-lpc18xx.c index b0a8da5c058d..2dbfbf90176c 100644 --- a/drivers/gpio/gpio-lpc18xx.c +++ b/drivers/gpio/gpio-lpc18xx.c @@ -249,8 +249,8 @@ static int lpc18xx_gpio_pin_ic_probe(struct lpc18xx_gpio_chip *gc) raw_spin_lock_init(&ic->lock); ic->domain = irq_domain_create_hierarchy(parent_domain, 0, NR_LPC18XX_GPIO_PIN_IC_IRQS, - of_fwnode_handle(dev->of_node), - &lpc18xx_gpio_pin_ic_domain_ops, ic); + dev_fwnode(dev), &lpc18xx_gpio_pin_ic_domain_ops, + ic); if (!ic->domain) { pr_err("unable to add irq domain\n"); ret = -ENODEV; diff --git a/drivers/gpio/gpio-mm-lantiq.c b/drivers/gpio/gpio-mm-lantiq.c index 14ae25783438..897a1e004681 100644 --- a/drivers/gpio/gpio-mm-lantiq.c +++ b/drivers/gpio/gpio-mm-lantiq.c @@ -55,9 +55,9 @@ static void ltq_mm_apply(struct ltq_mm *chip) * @gpio: GPIO signal number. * @val: Value to be written to specified signal. * - * Set the shadow value and call ltq_mm_apply. + * Set the shadow value and call ltq_mm_apply. Always returns 0. */ -static void ltq_mm_set(struct gpio_chip *gc, unsigned offset, int value) +static int ltq_mm_set(struct gpio_chip *gc, unsigned int offset, int value) { struct ltq_mm *chip = gpiochip_get_data(gc); @@ -66,6 +66,8 @@ static void ltq_mm_set(struct gpio_chip *gc, unsigned offset, int value) else chip->shadow &= ~(1 << offset); ltq_mm_apply(chip); + + return 0; } /** @@ -78,9 +80,7 @@ static void ltq_mm_set(struct gpio_chip *gc, unsigned offset, int value) */ static int ltq_mm_dir_out(struct gpio_chip *gc, unsigned offset, int value) { - ltq_mm_set(gc, offset, value); - - return 0; + return ltq_mm_set(gc, offset, value); } /** @@ -111,7 +111,7 @@ static int ltq_mm_probe(struct platform_device *pdev) chip->mmchip.gc.ngpio = 16; chip->mmchip.gc.direction_output = ltq_mm_dir_out; - chip->mmchip.gc.set = ltq_mm_set; + chip->mmchip.gc.set_rv = ltq_mm_set; chip->mmchip.save_regs = ltq_mm_save_regs; /* store the shadow value if one was passed by the devicetree */ diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c index a8103e26298c..cf878c2ea6bf 100644 --- a/drivers/gpio/gpio-mmio.c +++ b/drivers/gpio/gpio-mmio.c @@ -211,11 +211,12 @@ static int bgpio_get_multiple_be(struct gpio_chip *gc, unsigned long *mask, return 0; } -static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val) +static int bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val) { + return 0; } -static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) +static int bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { unsigned long mask = bgpio_line2mask(gc, gpio); unsigned long flags; @@ -230,10 +231,12 @@ static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) gc->write_reg(gc->reg_dat, gc->bgpio_data); raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); + + return 0; } -static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio, - int val) +static int bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio, + int val) { unsigned long mask = bgpio_line2mask(gc, gpio); @@ -241,9 +244,11 @@ static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio, gc->write_reg(gc->reg_set, mask); else gc->write_reg(gc->reg_clr, mask); + + return 0; } -static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val) +static int bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val) { unsigned long mask = bgpio_line2mask(gc, gpio); unsigned long flags; @@ -258,6 +263,8 @@ static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val) gc->write_reg(gc->reg_set, gc->bgpio_data); raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); + + return 0; } static void bgpio_multiple_get_masks(struct gpio_chip *gc, @@ -298,21 +305,25 @@ static void bgpio_set_multiple_single_reg(struct gpio_chip *gc, raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags); } -static void bgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, +static int bgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, unsigned long *bits) { bgpio_set_multiple_single_reg(gc, mask, bits, gc->reg_dat); + + return 0; } -static void bgpio_set_multiple_set(struct gpio_chip *gc, unsigned long *mask, - unsigned long *bits) +static int bgpio_set_multiple_set(struct gpio_chip *gc, unsigned long *mask, + unsigned long *bits) { bgpio_set_multiple_single_reg(gc, mask, bits, gc->reg_set); + + return 0; } -static void bgpio_set_multiple_with_clear(struct gpio_chip *gc, - unsigned long *mask, - unsigned long *bits) +static int bgpio_set_multiple_with_clear(struct gpio_chip *gc, + unsigned long *mask, + unsigned long *bits) { unsigned long set_mask, clear_mask; @@ -322,6 +333,8 @@ static void bgpio_set_multiple_with_clear(struct gpio_chip *gc, gc->write_reg(gc->reg_set, set_mask); if (clear_mask) gc->write_reg(gc->reg_clr, clear_mask); + + return 0; } static int bgpio_dir_return(struct gpio_chip *gc, unsigned int gpio, bool dir_out) @@ -335,6 +348,11 @@ static int bgpio_dir_return(struct gpio_chip *gc, unsigned int gpio, bool dir_ou return pinctrl_gpio_direction_input(gc, gpio); } +static int bgpio_dir_in_err(struct gpio_chip *gc, unsigned int gpio) +{ + return -EINVAL; +} + static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio) { return bgpio_dir_return(gc, gpio, false); @@ -349,7 +367,7 @@ static int bgpio_dir_out_err(struct gpio_chip *gc, unsigned int gpio, static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { - gc->set(gc, gpio, val); + gc->set_rv(gc, gpio, val); return bgpio_dir_return(gc, gpio, true); } @@ -414,14 +432,14 @@ static int bgpio_dir_out_dir_first(struct gpio_chip *gc, unsigned int gpio, int val) { bgpio_dir_out(gc, gpio, val); - gc->set(gc, gpio, val); + gc->set_rv(gc, gpio, val); return bgpio_dir_return(gc, gpio, true); } static int bgpio_dir_out_val_first(struct gpio_chip *gc, unsigned int gpio, int val) { - gc->set(gc, gpio, val); + gc->set_rv(gc, gpio, val); bgpio_dir_out(gc, gpio, val); return bgpio_dir_return(gc, gpio, true); } @@ -510,18 +528,18 @@ static int bgpio_setup_io(struct gpio_chip *gc, if (set && clr) { gc->reg_set = set; gc->reg_clr = clr; - gc->set = bgpio_set_with_clear; - gc->set_multiple = bgpio_set_multiple_with_clear; + gc->set_rv = bgpio_set_with_clear; + gc->set_multiple_rv = bgpio_set_multiple_with_clear; } else if (set && !clr) { gc->reg_set = set; - gc->set = bgpio_set_set; - gc->set_multiple = bgpio_set_multiple_set; + gc->set_rv = bgpio_set_set; + gc->set_multiple_rv = bgpio_set_multiple_set; } else if (flags & BGPIOF_NO_OUTPUT) { - gc->set = bgpio_set_none; - gc->set_multiple = NULL; + gc->set_rv = bgpio_set_none; + gc->set_multiple_rv = NULL; } else { - gc->set = bgpio_set; - gc->set_multiple = bgpio_set_multiple; + gc->set_rv = bgpio_set; + gc->set_multiple_rv = bgpio_set_multiple; } if (!(flags & BGPIOF_UNREADABLE_REG_SET) && @@ -566,7 +584,11 @@ static int bgpio_setup_direction(struct gpio_chip *gc, gc->direction_output = bgpio_dir_out_err; else gc->direction_output = bgpio_simple_dir_out; - gc->direction_input = bgpio_simple_dir_in; + + if (flags & BGPIOF_NO_INPUT) + gc->direction_input = bgpio_dir_in_err; + else + gc->direction_input = bgpio_simple_dir_in; } return 0; @@ -654,7 +676,7 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev, } gc->bgpio_data = gc->read_reg(gc->reg_dat); - if (gc->set == bgpio_set_set && + if (gc->set_rv == bgpio_set_set && !(flags & BGPIOF_UNREADABLE_REG_SET)) gc->bgpio_data = gc->read_reg(gc->reg_set); diff --git a/drivers/gpio/gpio-moxtet.c b/drivers/gpio/gpio-moxtet.c index 61f9efd6c64f..27dd9c3e7b77 100644 --- a/drivers/gpio/gpio-moxtet.c +++ b/drivers/gpio/gpio-moxtet.c @@ -52,15 +52,15 @@ static int moxtet_gpio_get_value(struct gpio_chip *gc, unsigned int offset) return !!(ret & BIT(offset)); } -static void moxtet_gpio_set_value(struct gpio_chip *gc, unsigned int offset, - int val) +static int moxtet_gpio_set_value(struct gpio_chip *gc, unsigned int offset, + int val) { struct moxtet_gpio_chip *chip = gpiochip_get_data(gc); int state; state = moxtet_device_written(chip->dev); if (state < 0) - return; + return state; offset -= MOXTET_GPIO_INPUTS; @@ -69,7 +69,7 @@ static void moxtet_gpio_set_value(struct gpio_chip *gc, unsigned int offset, else state &= ~BIT(offset); - moxtet_device_write(chip->dev, state); + return moxtet_device_write(chip->dev, state); } static int moxtet_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) @@ -104,13 +104,11 @@ static int moxtet_gpio_direction_output(struct gpio_chip *gc, struct moxtet_gpio_chip *chip = gpiochip_get_data(gc); if (chip->desc->out_mask & BIT(offset)) - moxtet_gpio_set_value(gc, offset, val); + return moxtet_gpio_set_value(gc, offset, val); else if (chip->desc->in_mask & BIT(offset)) return -ENOTSUPP; - else - return -EINVAL; - return 0; + return -EINVAL; } static int moxtet_gpio_probe(struct device *dev) @@ -142,7 +140,7 @@ static int moxtet_gpio_probe(struct device *dev) chip->gpio_chip.direction_input = moxtet_gpio_direction_input; chip->gpio_chip.direction_output = moxtet_gpio_direction_output; chip->gpio_chip.get = moxtet_gpio_get_value; - chip->gpio_chip.set = moxtet_gpio_set_value; + chip->gpio_chip.set_rv = moxtet_gpio_set_value; chip->gpio_chip.base = -1; chip->gpio_chip.ngpio = MOXTET_GPIO_NGPIOS; diff --git a/drivers/gpio/gpio-mpc5200.c b/drivers/gpio/gpio-mpc5200.c index 091d96f2d682..40d587176a75 100644 --- a/drivers/gpio/gpio-mpc5200.c +++ b/drivers/gpio/gpio-mpc5200.c @@ -69,7 +69,7 @@ __mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) out_8(®s->wkup_dvo, chip->shadow_dvo); } -static void +static int mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { unsigned long flags; @@ -81,6 +81,8 @@ mpc52xx_wkup_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) spin_unlock_irqrestore(&gpio_lock, flags); pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); + + return 0; } static int mpc52xx_wkup_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) @@ -151,7 +153,7 @@ static int mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev) gc->direction_input = mpc52xx_wkup_gpio_dir_in; gc->direction_output = mpc52xx_wkup_gpio_dir_out; gc->get = mpc52xx_wkup_gpio_get; - gc->set = mpc52xx_wkup_gpio_set; + gc->set_rv = mpc52xx_wkup_gpio_set; ret = of_mm_gpiochip_add_data(ofdev->dev.of_node, &chip->mmchip, chip); if (ret) @@ -228,7 +230,7 @@ __mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) out_be32(®s->simple_dvo, chip->shadow_dvo); } -static void +static int mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { unsigned long flags; @@ -240,6 +242,8 @@ mpc52xx_simple_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) spin_unlock_irqrestore(&gpio_lock, flags); pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); + + return 0; } static int mpc52xx_simple_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) @@ -311,7 +315,7 @@ static int mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev) gc->direction_input = mpc52xx_simple_gpio_dir_in; gc->direction_output = mpc52xx_simple_gpio_dir_out; gc->get = mpc52xx_simple_gpio_get; - gc->set = mpc52xx_simple_gpio_set; + gc->set_rv = mpc52xx_simple_gpio_set; ret = of_mm_gpiochip_add_data(ofdev->dev.of_node, &chip->mmchip, chip); if (ret) diff --git a/drivers/gpio/gpio-mpfs.c b/drivers/gpio/gpio-mpfs.c index 561a961c97a6..3415cb7ebb0f 100644 --- a/drivers/gpio/gpio-mpfs.c +++ b/drivers/gpio/gpio-mpfs.c @@ -99,16 +99,19 @@ static int mpfs_gpio_get(struct gpio_chip *gc, unsigned int gpio_index) return regmap_test_bits(mpfs_gpio->regs, mpfs_gpio->offsets->inp, BIT(gpio_index)); } -static void mpfs_gpio_set(struct gpio_chip *gc, unsigned int gpio_index, int value) +static int mpfs_gpio_set(struct gpio_chip *gc, unsigned int gpio_index, int value) { struct mpfs_gpio_chip *mpfs_gpio = gpiochip_get_data(gc); + int ret; mpfs_gpio_get(gc, gpio_index); - regmap_update_bits(mpfs_gpio->regs, mpfs_gpio->offsets->outp, BIT(gpio_index), - value << gpio_index); + ret = regmap_update_bits(mpfs_gpio->regs, mpfs_gpio->offsets->outp, + BIT(gpio_index), value << gpio_index); mpfs_gpio_get(gc, gpio_index); + + return ret; } static int mpfs_gpio_probe(struct platform_device *pdev) @@ -147,7 +150,7 @@ static int mpfs_gpio_probe(struct platform_device *pdev) mpfs_gpio->gc.direction_output = mpfs_gpio_direction_output; mpfs_gpio->gc.get_direction = mpfs_gpio_get_direction; mpfs_gpio->gc.get = mpfs_gpio_get; - mpfs_gpio->gc.set = mpfs_gpio_set; + mpfs_gpio->gc.set_rv = mpfs_gpio_set; mpfs_gpio->gc.base = -1; mpfs_gpio->gc.ngpio = ngpios; mpfs_gpio->gc.label = dev_name(dev); diff --git a/drivers/gpio/gpio-mpsse.c b/drivers/gpio/gpio-mpsse.c index 3ea32c5e33d1..b17de08e9e03 100644 --- a/drivers/gpio/gpio-mpsse.c +++ b/drivers/gpio/gpio-mpsse.c @@ -160,8 +160,8 @@ static int gpio_mpsse_get_bank(struct mpsse_priv *priv, u8 bank) return buf; } -static void gpio_mpsse_set_multiple(struct gpio_chip *chip, unsigned long *mask, - unsigned long *bits) +static int gpio_mpsse_set_multiple(struct gpio_chip *chip, unsigned long *mask, + unsigned long *bits) { unsigned long i, bank, bank_mask, bank_bits; int ret; @@ -180,11 +180,11 @@ static void gpio_mpsse_set_multiple(struct gpio_chip *chip, unsigned long *mask, ret = gpio_mpsse_set_bank(priv, bank); if (ret) - dev_err(&priv->intf->dev, - "Couldn't set values for bank %ld!", - bank); + return ret; } } + + return 0; } static int gpio_mpsse_get_multiple(struct gpio_chip *chip, unsigned long *mask, @@ -227,7 +227,7 @@ static int gpio_mpsse_gpio_get(struct gpio_chip *chip, unsigned int offset) return 0; } -static void gpio_mpsse_gpio_set(struct gpio_chip *chip, unsigned int offset, +static int gpio_mpsse_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) { unsigned long mask = 0, bits = 0; @@ -236,7 +236,7 @@ static void gpio_mpsse_gpio_set(struct gpio_chip *chip, unsigned int offset, if (value) __set_bit(offset, &bits); - gpio_mpsse_set_multiple(chip, &mask, &bits); + return gpio_mpsse_set_multiple(chip, &mask, &bits); } static int gpio_mpsse_direction_output(struct gpio_chip *chip, @@ -249,9 +249,7 @@ static int gpio_mpsse_direction_output(struct gpio_chip *chip, scoped_guard(mutex, &priv->io_mutex) priv->gpio_dir[bank] |= BIT(bank_offset); - gpio_mpsse_gpio_set(chip, offset, value); - - return 0; + return gpio_mpsse_gpio_set(chip, offset, value); } static int gpio_mpsse_direction_input(struct gpio_chip *chip, @@ -450,9 +448,9 @@ static int gpio_mpsse_probe(struct usb_interface *interface, priv->gpio.direction_input = gpio_mpsse_direction_input; priv->gpio.direction_output = gpio_mpsse_direction_output; priv->gpio.get = gpio_mpsse_gpio_get; - priv->gpio.set = gpio_mpsse_gpio_set; + priv->gpio.set_rv = gpio_mpsse_gpio_set; priv->gpio.get_multiple = gpio_mpsse_get_multiple; - priv->gpio.set_multiple = gpio_mpsse_set_multiple; + priv->gpio.set_multiple_rv = gpio_mpsse_set_multiple; priv->gpio.base = -1; priv->gpio.ngpio = 16; priv->gpio.offset = priv->intf_id * priv->gpio.ngpio; diff --git a/drivers/gpio/gpio-msc313.c b/drivers/gpio/gpio-msc313.c index 6db9e469e0dc..992339a89d19 100644 --- a/drivers/gpio/gpio-msc313.c +++ b/drivers/gpio/gpio-msc313.c @@ -486,7 +486,7 @@ struct msc313_gpio { u8 *saved; }; -static void msc313_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) +static int msc313_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) { struct msc313_gpio *gpio = gpiochip_get_data(chip); u8 gpioreg = readb_relaxed(gpio->base + gpio->gpio_data->offsets[offset]); @@ -497,6 +497,8 @@ static void msc313_gpio_set(struct gpio_chip *chip, unsigned int offset, int val gpioreg &= ~MSC313_GPIO_OUT; writeb_relaxed(gpioreg, gpio->base + gpio->gpio_data->offsets[offset]); + + return 0; } static int msc313_gpio_get(struct gpio_chip *chip, unsigned int offset) @@ -656,7 +658,7 @@ static int msc313_gpio_probe(struct platform_device *pdev) gpiochip->direction_input = msc313_gpio_direction_input; gpiochip->direction_output = msc313_gpio_direction_output; gpiochip->get = msc313_gpio_get; - gpiochip->set = msc313_gpio_set; + gpiochip->set_rv = msc313_gpio_set; gpiochip->base = -1; gpiochip->ngpio = gpio->gpio_data->num; gpiochip->names = gpio->gpio_data->names; diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 57633a7b4270..24792b8eb083 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -1236,8 +1236,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev) if (!have_irqs) return 0; - mvchip->domain = - irq_domain_create_linear(of_fwnode_handle(np), ngpios, &irq_generic_chip_ops, NULL); + mvchip->domain = irq_domain_create_linear(dev_fwnode(&pdev->dev), ngpios, + &irq_generic_chip_ops, NULL); if (!mvchip->domain) { dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n", mvchip->chip.label); diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index fae1a30f8ae6..4af5a2972d12 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -509,8 +509,8 @@ static int mxc_gpio_probe(struct platform_device *pdev) goto out_bgio; } - port->domain = irq_domain_create_legacy(of_fwnode_handle(np), 32, irq_base, 0, - &irq_domain_simple_ops, NULL); + port->domain = irq_domain_create_legacy(dev_fwnode(&pdev->dev), 32, irq_base, 0, + &irq_domain_simple_ops, NULL); if (!port->domain) { err = -ENODEV; goto out_bgio; diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index b418fbccb26c..0ea46f3d04e1 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -303,7 +303,7 @@ static int mxs_gpio_probe(struct platform_device *pdev) goto out_iounmap; } - port->domain = irq_domain_create_legacy(of_fwnode_handle(np), 32, irq_base, 0, + port->domain = irq_domain_create_legacy(dev_fwnode(&pdev->dev), 32, irq_base, 0, &irq_domain_simple_ops, NULL); if (!port->domain) { err = -ENODEV; diff --git a/drivers/gpio/gpio-nomadik.c b/drivers/gpio/gpio-nomadik.c index fa19a44943fd..296d13845b30 100644 --- a/drivers/gpio/gpio-nomadik.c +++ b/drivers/gpio/gpio-nomadik.c @@ -347,8 +347,8 @@ static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned int offset) return value; } -static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned int offset, - int val) +static int nmk_gpio_set_output(struct gpio_chip *chip, unsigned int offset, + int val) { struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(chip); @@ -357,6 +357,8 @@ static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned int offset, __nmk_gpio_set_output(nmk_chip, offset, val); clk_disable(nmk_chip->clk); + + return 0; } static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned int offset, @@ -672,7 +674,7 @@ static int nmk_gpio_probe(struct platform_device *pdev) chip->direction_input = nmk_gpio_make_input; chip->get = nmk_gpio_get_input; chip->direction_output = nmk_gpio_make_output; - chip->set = nmk_gpio_set_output; + chip->set_rv = nmk_gpio_set_output; chip->dbg_show = nmk_gpio_dbg_show; chip->can_sleep = false; chip->owner = THIS_MODULE; diff --git a/drivers/gpio/gpio-npcm-sgpio.c b/drivers/gpio/gpio-npcm-sgpio.c index 260570614543..25b203a89e38 100644 --- a/drivers/gpio/gpio-npcm-sgpio.c +++ b/drivers/gpio/gpio-npcm-sgpio.c @@ -211,9 +211,7 @@ static int npcm_sgpio_dir_in(struct gpio_chip *gc, unsigned int offset) static int npcm_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, int val) { - gc->set(gc, offset, val); - - return 0; + return gc->set_rv(gc, offset, val); } static int npcm_sgpio_get_direction(struct gpio_chip *gc, unsigned int offset) @@ -226,7 +224,7 @@ static int npcm_sgpio_get_direction(struct gpio_chip *gc, unsigned int offset) return GPIO_LINE_DIRECTION_IN; } -static void npcm_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val) +static int npcm_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val) { struct npcm_sgpio *gpio = gpiochip_get_data(gc); const struct npcm_sgpio_bank *bank = offset_to_bank(offset); @@ -242,6 +240,8 @@ static void npcm_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val) reg &= ~BIT(GPIO_BIT(offset)); iowrite8(reg, addr); + + return 0; } static int npcm_sgpio_get(struct gpio_chip *gc, unsigned int offset) @@ -546,7 +546,7 @@ static int npcm_sgpio_probe(struct platform_device *pdev) gpio->chip.direction_output = npcm_sgpio_dir_out; gpio->chip.get_direction = npcm_sgpio_get_direction; gpio->chip.get = npcm_sgpio_get; - gpio->chip.set = npcm_sgpio_set; + gpio->chip.set_rv = npcm_sgpio_set; gpio->chip.label = dev_name(&pdev->dev); gpio->chip.base = -1; diff --git a/drivers/gpio/gpio-octeon.c b/drivers/gpio/gpio-octeon.c index afb0e8a791e5..24966161742a 100644 --- a/drivers/gpio/gpio-octeon.c +++ b/drivers/gpio/gpio-octeon.c @@ -47,12 +47,15 @@ static int octeon_gpio_dir_in(struct gpio_chip *chip, unsigned offset) return 0; } -static void octeon_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +static int octeon_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) { struct octeon_gpio *gpio = gpiochip_get_data(chip); u64 mask = 1ull << offset; u64 reg = gpio->register_base + (value ? TX_SET : TX_CLEAR); cvmx_write_csr(reg, mask); + + return 0; } static int octeon_gpio_dir_out(struct gpio_chip *chip, unsigned offset, @@ -105,7 +108,7 @@ static int octeon_gpio_probe(struct platform_device *pdev) chip->direction_input = octeon_gpio_dir_in; chip->get = octeon_gpio_get; chip->direction_output = octeon_gpio_dir_out; - chip->set = octeon_gpio_set; + chip->set_rv = octeon_gpio_set; err = devm_gpiochip_add_data(&pdev->dev, chip, gpio); if (err) return err; diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 54c4bfdccf56..ed5c88a5c520 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -953,7 +953,7 @@ static int omap_gpio_set_config(struct gpio_chip *chip, unsigned offset, return ret; } -static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +static int omap_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) { struct gpio_bank *bank; unsigned long flags; @@ -962,10 +962,12 @@ static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value) raw_spin_lock_irqsave(&bank->lock, flags); bank->set_dataout(bank, offset, value); raw_spin_unlock_irqrestore(&bank->lock, flags); + + return 0; } -static void omap_gpio_set_multiple(struct gpio_chip *chip, unsigned long *mask, - unsigned long *bits) +static int omap_gpio_set_multiple(struct gpio_chip *chip, unsigned long *mask, + unsigned long *bits) { struct gpio_bank *bank = gpiochip_get_data(chip); void __iomem *reg = bank->base + bank->regs->dataout; @@ -977,6 +979,8 @@ static void omap_gpio_set_multiple(struct gpio_chip *chip, unsigned long *mask, writel_relaxed(l, reg); bank->context.dataout = l; raw_spin_unlock_irqrestore(&bank->lock, flags); + + return 0; } /*---------------------------------------------------------------------*/ @@ -1042,8 +1046,8 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct device *pm_dev) bank->chip.get_multiple = omap_gpio_get_multiple; bank->chip.direction_output = omap_gpio_output; bank->chip.set_config = omap_gpio_set_config; - bank->chip.set = omap_gpio_set; - bank->chip.set_multiple = omap_gpio_set_multiple; + bank->chip.set_rv = omap_gpio_set; + bank->chip.set_multiple_rv = omap_gpio_set_multiple; if (bank->is_mpuio) { bank->chip.label = "mpuio"; if (bank->regs->wkup_en) diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c index 28dba7048509..9329d8ce8f59 100644 --- a/drivers/gpio/gpio-palmas.c +++ b/drivers/gpio/gpio-palmas.c @@ -54,12 +54,11 @@ static int palmas_gpio_get(struct gpio_chip *gc, unsigned offset) return !!(val & BIT(offset)); } -static void palmas_gpio_set(struct gpio_chip *gc, unsigned offset, - int value) +static int palmas_gpio_set(struct gpio_chip *gc, unsigned int offset, + int value) { struct palmas_gpio *pg = gpiochip_get_data(gc); struct palmas *palmas = pg->palmas; - int ret; unsigned int reg; int gpio16 = (offset/8); @@ -71,9 +70,7 @@ static void palmas_gpio_set(struct gpio_chip *gc, unsigned offset, reg = (value) ? PALMAS_GPIO_SET_DATA_OUT : PALMAS_GPIO_CLEAR_DATA_OUT; - ret = palmas_write(palmas, PALMAS_GPIO_BASE, reg, BIT(offset)); - if (ret < 0) - dev_err(gc->parent, "Reg 0x%02x write failed, %d\n", reg, ret); + return palmas_write(palmas, PALMAS_GPIO_BASE, reg, BIT(offset)); } static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset, @@ -89,7 +86,9 @@ static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset, reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR; /* Set the initial value */ - palmas_gpio_set(gc, offset, value); + ret = palmas_gpio_set(gc, offset, value); + if (ret) + return ret; ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, BIT(offset), BIT(offset)); @@ -140,6 +139,7 @@ static const struct of_device_id of_palmas_gpio_match[] = { { .compatible = "ti,tps80036-gpio", .data = &tps80036_dev_data,}, { }, }; +MODULE_DEVICE_TABLE(of, of_palmas_gpio_match); static int palmas_gpio_probe(struct platform_device *pdev) { @@ -166,7 +166,7 @@ static int palmas_gpio_probe(struct platform_device *pdev) palmas_gpio->gpio_chip.direction_input = palmas_gpio_input; palmas_gpio->gpio_chip.direction_output = palmas_gpio_output; palmas_gpio->gpio_chip.to_irq = palmas_gpio_to_irq; - palmas_gpio->gpio_chip.set = palmas_gpio_set; + palmas_gpio->gpio_chip.set_rv = palmas_gpio_set; palmas_gpio->gpio_chip.get = palmas_gpio_get; palmas_gpio->gpio_chip.parent = &pdev->dev; @@ -197,3 +197,13 @@ static int __init palmas_gpio_init(void) return platform_driver_register(&palmas_gpio_driver); } subsys_initcall(palmas_gpio_init); + +static void __exit palmas_gpio_exit(void) +{ + platform_driver_unregister(&palmas_gpio_driver); +} +module_exit(palmas_gpio_exit); + +MODULE_DESCRIPTION("TI PALMAS series GPIO driver"); +MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-pca9570.c b/drivers/gpio/gpio-pca9570.c index d37ba4049368..a33246f20fd8 100644 --- a/drivers/gpio/gpio-pca9570.c +++ b/drivers/gpio/gpio-pca9570.c @@ -88,7 +88,7 @@ static int pca9570_get(struct gpio_chip *chip, unsigned offset) return !!(buffer & BIT(offset)); } -static void pca9570_set(struct gpio_chip *chip, unsigned offset, int value) +static int pca9570_set(struct gpio_chip *chip, unsigned int offset, int value) { struct pca9570 *gpio = gpiochip_get_data(chip); u8 buffer; @@ -110,6 +110,7 @@ static void pca9570_set(struct gpio_chip *chip, unsigned offset, int value) out: mutex_unlock(&gpio->lock); + return ret; } static int pca9570_probe(struct i2c_client *client) @@ -125,7 +126,7 @@ static int pca9570_probe(struct i2c_client *client) gpio->chip.owner = THIS_MODULE; gpio->chip.get_direction = pca9570_get_direction; gpio->chip.get = pca9570_get; - gpio->chip.set = pca9570_set; + gpio->chip.set_rv = pca9570_set; gpio->chip.base = -1; gpio->chip_data = device_get_match_data(&client->dev); gpio->chip.ngpio = gpio->chip_data->ngpio; diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index 2e5f5d7f8865..a04203680333 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c @@ -171,21 +171,24 @@ static int pcf857x_output(struct gpio_chip *chip, unsigned int offset, int value return status; } -static void pcf857x_set(struct gpio_chip *chip, unsigned int offset, int value) +static int pcf857x_set(struct gpio_chip *chip, unsigned int offset, int value) { - pcf857x_output(chip, offset, value); + return pcf857x_output(chip, offset, value); } -static void pcf857x_set_multiple(struct gpio_chip *chip, unsigned long *mask, - unsigned long *bits) +static int pcf857x_set_multiple(struct gpio_chip *chip, unsigned long *mask, + unsigned long *bits) { struct pcf857x *gpio = gpiochip_get_data(chip); + int status; mutex_lock(&gpio->lock); gpio->out &= ~*mask; gpio->out |= *bits & *mask; - gpio->write(gpio->client, gpio->out); + status = gpio->write(gpio->client, gpio->out); mutex_unlock(&gpio->lock); + + return status; } /*-------------------------------------------------------------------------*/ @@ -292,8 +295,8 @@ static int pcf857x_probe(struct i2c_client *client) gpio->chip.owner = THIS_MODULE; gpio->chip.get = pcf857x_get; gpio->chip.get_multiple = pcf857x_get_multiple; - gpio->chip.set = pcf857x_set; - gpio->chip.set_multiple = pcf857x_set_multiple; + gpio->chip.set_rv = pcf857x_set; + gpio->chip.set_multiple_rv = pcf857x_set_multiple; gpio->chip.direction_input = pcf857x_input; gpio->chip.direction_output = pcf857x_output; gpio->chip.ngpio = (uintptr_t)i2c_get_match_data(client); diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index 63f25c72eac2..c6f313342ba0 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -99,7 +99,7 @@ struct pch_gpio { spinlock_t spinlock; }; -static void pch_gpio_set(struct gpio_chip *gpio, unsigned int nr, int val) +static int pch_gpio_set(struct gpio_chip *gpio, unsigned int nr, int val) { u32 reg_val; struct pch_gpio *chip = gpiochip_get_data(gpio); @@ -114,6 +114,8 @@ static void pch_gpio_set(struct gpio_chip *gpio, unsigned int nr, int val) iowrite32(reg_val, &chip->reg->po); spin_unlock_irqrestore(&chip->spinlock, flags); + + return 0; } static int pch_gpio_get(struct gpio_chip *gpio, unsigned int nr) @@ -217,7 +219,7 @@ static void pch_gpio_setup(struct pch_gpio *chip) gpio->direction_input = pch_gpio_direction_input; gpio->get = pch_gpio_get; gpio->direction_output = pch_gpio_direction_output; - gpio->set = pch_gpio_set; + gpio->set_rv = pch_gpio_set; gpio->base = -1; gpio->ngpio = gpio_pins[chip->ioh]; gpio->can_sleep = false; diff --git a/drivers/gpio/gpio-pisosr.c b/drivers/gpio/gpio-pisosr.c index e3013e778e15..a69b74866a13 100644 --- a/drivers/gpio/gpio-pisosr.c +++ b/drivers/gpio/gpio-pisosr.c @@ -67,13 +67,6 @@ static int pisosr_gpio_direction_input(struct gpio_chip *chip, return 0; } -static int pisosr_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - /* This device is input only */ - return -EINVAL; -} - static int pisosr_gpio_get(struct gpio_chip *chip, unsigned offset) { struct pisosr_gpio *gpio = gpiochip_get_data(chip); @@ -108,7 +101,6 @@ static const struct gpio_chip template_chip = { .owner = THIS_MODULE, .get_direction = pisosr_gpio_get_direction, .direction_input = pisosr_gpio_direction_input, - .direction_output = pisosr_gpio_direction_output, .get = pisosr_gpio_get, .get_multiple = pisosr_gpio_get_multiple, .base = -1, diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 1c273727ffa3..98cfac4eac85 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -115,11 +115,13 @@ static int pl061_get_value(struct gpio_chip *gc, unsigned offset) return !!readb(pl061->base + (BIT(offset + 2))); } -static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value) +static int pl061_set_value(struct gpio_chip *gc, unsigned int offset, int value) { struct pl061 *pl061 = gpiochip_get_data(gc); writeb(!!value << offset, pl061->base + (BIT(offset + 2))); + + return 0; } static int pl061_irq_type(struct irq_data *d, unsigned trigger) @@ -328,7 +330,7 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) pl061->gc.direction_input = pl061_direction_input; pl061->gc.direction_output = pl061_direction_output; pl061->gc.get = pl061_get_value; - pl061->gc.set = pl061_set_value; + pl061->gc.set_rv = pl061_set_value; pl061->gc.ngpio = PL061_GPIO_NR; pl061->gc.label = dev_name(dev); pl061->gc.parent = dev; diff --git a/drivers/gpio/gpio-pmic-eic-sprd.c b/drivers/gpio/gpio-pmic-eic-sprd.c index d9b228bea42e..cb015fb5c946 100644 --- a/drivers/gpio/gpio-pmic-eic-sprd.c +++ b/drivers/gpio/gpio-pmic-eic-sprd.c @@ -109,12 +109,6 @@ static int sprd_pmic_eic_direction_input(struct gpio_chip *chip, return 0; } -static void sprd_pmic_eic_set(struct gpio_chip *chip, unsigned int offset, - int value) -{ - /* EICs are always input, nothing need to do here. */ -} - static int sprd_pmic_eic_set_debounce(struct gpio_chip *chip, unsigned int offset, unsigned int debounce) @@ -351,7 +345,6 @@ static int sprd_pmic_eic_probe(struct platform_device *pdev) pmic_eic->chip.request = sprd_pmic_eic_request; pmic_eic->chip.free = sprd_pmic_eic_free; pmic_eic->chip.set_config = sprd_pmic_eic_set_config; - pmic_eic->chip.set = sprd_pmic_eic_set; pmic_eic->chip.get = sprd_pmic_eic_get; pmic_eic->chip.can_sleep = true; diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index aead35ea090e..13f7da2a9486 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -315,12 +315,14 @@ static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset) return !!(gplr & GPIO_bit(offset)); } -static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +static int pxa_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) { void __iomem *base = gpio_bank_base(chip, offset); writel_relaxed(GPIO_bit(offset), base + (value ? GPSR_OFFSET : GPCR_OFFSET)); + + return 0; } #ifdef CONFIG_OF_GPIO @@ -353,7 +355,7 @@ static int pxa_init_gpio_chip(struct pxa_gpio_chip *pchip, int ngpio, void __iom pchip->chip.direction_input = pxa_gpio_direction_input; pchip->chip.direction_output = pxa_gpio_direction_output; pchip->chip.get = pxa_gpio_get; - pchip->chip.set = pxa_gpio_set; + pchip->chip.set_rv = pxa_gpio_set; pchip->chip.to_irq = pxa_gpio_to_irq; pchip->chip.ngpio = ngpio; pchip->chip.request = gpiochip_generic_request; @@ -642,9 +644,8 @@ static int pxa_gpio_probe(struct platform_device *pdev) if (!pxa_last_gpio) return -EINVAL; - pchip->irqdomain = irq_domain_create_legacy(of_fwnode_handle(pdev->dev.of_node), - pxa_last_gpio + 1, irq_base, 0, - &pxa_irq_domain_ops, pchip); + pchip->irqdomain = irq_domain_create_legacy(dev_fwnode(&pdev->dev), pxa_last_gpio + 1, + irq_base, 0, &pxa_irq_domain_ops, pchip); if (!pchip->irqdomain) return -ENOMEM; diff --git a/drivers/gpio/gpio-raspberrypi-exp.c b/drivers/gpio/gpio-raspberrypi-exp.c index 9d1b95e429f1..b4b607515a04 100644 --- a/drivers/gpio/gpio-raspberrypi-exp.c +++ b/drivers/gpio/gpio-raspberrypi-exp.c @@ -175,7 +175,7 @@ static int rpi_exp_gpio_get(struct gpio_chip *gc, unsigned int off) return !!get.state; } -static void rpi_exp_gpio_set(struct gpio_chip *gc, unsigned int off, int val) +static int rpi_exp_gpio_set(struct gpio_chip *gc, unsigned int off, int val) { struct rpi_exp_gpio *gpio; struct gpio_get_set_state set; @@ -188,10 +188,14 @@ static void rpi_exp_gpio_set(struct gpio_chip *gc, unsigned int off, int val) ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_STATE, &set, sizeof(set)); - if (ret || set.gpio != 0) + if (ret || set.gpio != 0) { dev_err(gc->parent, "Failed to set GPIO %u state (%d %x)\n", off, ret, set.gpio); + return ret ? ret : -EIO; + } + + return 0; } static int rpi_exp_gpio_probe(struct platform_device *pdev) @@ -228,7 +232,7 @@ static int rpi_exp_gpio_probe(struct platform_device *pdev) rpi_gpio->gc.direction_output = rpi_exp_gpio_dir_out; rpi_gpio->gc.get_direction = rpi_exp_gpio_get_direction; rpi_gpio->gc.get = rpi_exp_gpio_get; - rpi_gpio->gc.set = rpi_exp_gpio_set; + rpi_gpio->gc.set_rv = rpi_exp_gpio_set; rpi_gpio->gc.can_sleep = true; return devm_gpiochip_add_data(dev, &rpi_gpio->gc, rpi_gpio); diff --git a/drivers/gpio/gpio-rc5t583.c b/drivers/gpio/gpio-rc5t583.c index c34dcadaee36..cf3e91d235df 100644 --- a/drivers/gpio/gpio-rc5t583.c +++ b/drivers/gpio/gpio-rc5t583.c @@ -35,14 +35,20 @@ static int rc5t583_gpio_get(struct gpio_chip *gc, unsigned int offset) return !!(val & BIT(offset)); } -static void rc5t583_gpio_set(struct gpio_chip *gc, unsigned int offset, int val) +static int rc5t583_gpio_set(struct gpio_chip *gc, unsigned int offset, int val) { struct rc5t583_gpio *rc5t583_gpio = gpiochip_get_data(gc); struct device *parent = rc5t583_gpio->rc5t583->dev; + int ret; + if (val) - rc5t583_set_bits(parent, RC5T583_GPIO_IOOUT, BIT(offset)); + ret = rc5t583_set_bits(parent, RC5T583_GPIO_IOOUT, + BIT(offset)); else - rc5t583_clear_bits(parent, RC5T583_GPIO_IOOUT, BIT(offset)); + ret = rc5t583_clear_bits(parent, RC5T583_GPIO_IOOUT, + BIT(offset)); + + return ret; } static int rc5t583_gpio_dir_input(struct gpio_chip *gc, unsigned int offset) @@ -66,7 +72,10 @@ static int rc5t583_gpio_dir_output(struct gpio_chip *gc, unsigned offset, struct device *parent = rc5t583_gpio->rc5t583->dev; int ret; - rc5t583_gpio_set(gc, offset, value); + ret = rc5t583_gpio_set(gc, offset, value); + if (ret) + return ret; + ret = rc5t583_set_bits(parent, RC5T583_GPIO_IOSEL, BIT(offset)); if (ret < 0) return ret; @@ -109,7 +118,7 @@ static int rc5t583_gpio_probe(struct platform_device *pdev) rc5t583_gpio->gpio_chip.free = rc5t583_gpio_free, rc5t583_gpio->gpio_chip.direction_input = rc5t583_gpio_dir_input, rc5t583_gpio->gpio_chip.direction_output = rc5t583_gpio_dir_output, - rc5t583_gpio->gpio_chip.set = rc5t583_gpio_set, + rc5t583_gpio->gpio_chip.set_rv = rc5t583_gpio_set, rc5t583_gpio->gpio_chip.get = rc5t583_gpio_get, rc5t583_gpio->gpio_chip.to_irq = rc5t583_gpio_to_irq, rc5t583_gpio->gpio_chip.ngpio = RC5T583_MAX_GPIO, diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index 18c965ee02c8..1d121a427590 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -331,14 +331,11 @@ static int gpio_rcar_get(struct gpio_chip *chip, unsigned offset) static int gpio_rcar_get_multiple(struct gpio_chip *chip, unsigned long *mask, unsigned long *bits) { + u32 bankmask = mask[0] & GENMASK(chip->ngpio - 1, 0); struct gpio_rcar_priv *p = gpiochip_get_data(chip); - u32 bankmask, outputs, m, val = 0; + u32 outputs, m, val = 0; unsigned long flags; - bankmask = mask[0] & GENMASK(chip->ngpio - 1, 0); - if (!bankmask) - return 0; - if (p->info.has_always_in) { bits[0] = gpio_rcar_read(p, INDT) & bankmask; return 0; @@ -359,7 +356,7 @@ static int gpio_rcar_get_multiple(struct gpio_chip *chip, unsigned long *mask, return 0; } -static void gpio_rcar_set(struct gpio_chip *chip, unsigned offset, int value) +static int gpio_rcar_set(struct gpio_chip *chip, unsigned int offset, int value) { struct gpio_rcar_priv *p = gpiochip_get_data(chip); unsigned long flags; @@ -367,18 +364,17 @@ static void gpio_rcar_set(struct gpio_chip *chip, unsigned offset, int value) raw_spin_lock_irqsave(&p->lock, flags); gpio_rcar_modify_bit(p, OUTDT, offset, value); raw_spin_unlock_irqrestore(&p->lock, flags); + + return 0; } -static void gpio_rcar_set_multiple(struct gpio_chip *chip, unsigned long *mask, - unsigned long *bits) +static int gpio_rcar_set_multiple(struct gpio_chip *chip, unsigned long *mask, + unsigned long *bits) { + u32 bankmask = mask[0] & GENMASK(chip->ngpio - 1, 0); struct gpio_rcar_priv *p = gpiochip_get_data(chip); unsigned long flags; - u32 val, bankmask; - - bankmask = mask[0] & GENMASK(chip->ngpio - 1, 0); - if (!bankmask) - return; + u32 val; raw_spin_lock_irqsave(&p->lock, flags); val = gpio_rcar_read(p, OUTDT); @@ -386,6 +382,8 @@ static void gpio_rcar_set_multiple(struct gpio_chip *chip, unsigned long *mask, val |= (bankmask & bits[0]); gpio_rcar_write(p, OUTDT, val); raw_spin_unlock_irqrestore(&p->lock, flags); + + return 0; } static int gpio_rcar_direction_output(struct gpio_chip *chip, unsigned offset, @@ -537,8 +535,8 @@ static int gpio_rcar_probe(struct platform_device *pdev) gpio_chip->get = gpio_rcar_get; gpio_chip->get_multiple = gpio_rcar_get_multiple; gpio_chip->direction_output = gpio_rcar_direction_output; - gpio_chip->set = gpio_rcar_set; - gpio_chip->set_multiple = gpio_rcar_set_multiple; + gpio_chip->set_rv = gpio_rcar_set; + gpio_chip->set_multiple_rv = gpio_rcar_set_multiple; gpio_chip->label = name; gpio_chip->parent = dev; gpio_chip->owner = THIS_MODULE; diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c index ec7fb9220a47..a75ed8021de5 100644 --- a/drivers/gpio/gpio-rdc321x.c +++ b/drivers/gpio/gpio-rdc321x.c @@ -64,8 +64,8 @@ static void rdc_gpio_set_value_impl(struct gpio_chip *chip, } /* set GPIO pin to value */ -static void rdc_gpio_set_value(struct gpio_chip *chip, - unsigned gpio, int value) +static int rdc_gpio_set_value(struct gpio_chip *chip, unsigned int gpio, + int value) { struct rdc321x_gpio *gpch; @@ -73,6 +73,8 @@ static void rdc_gpio_set_value(struct gpio_chip *chip, spin_lock(&gpch->lock); rdc_gpio_set_value_impl(chip, gpio, value); spin_unlock(&gpch->lock); + + return 0; } static int rdc_gpio_config(struct gpio_chip *chip, @@ -157,7 +159,7 @@ static int rdc321x_gpio_probe(struct platform_device *pdev) rdc321x_gpio_dev->chip.direction_input = rdc_gpio_direction_input; rdc321x_gpio_dev->chip.direction_output = rdc_gpio_config; rdc321x_gpio_dev->chip.get = rdc_gpio_get_value; - rdc321x_gpio_dev->chip.set = rdc_gpio_set_value; + rdc321x_gpio_dev->chip.set_rv = rdc_gpio_set_value; rdc321x_gpio_dev->chip.base = 0; rdc321x_gpio_dev->chip.ngpio = pdata->max_gpios; diff --git a/drivers/gpio/gpio-reg.c b/drivers/gpio/gpio-reg.c index 73c7260d89c0..d8da99f97385 100644 --- a/drivers/gpio/gpio-reg.c +++ b/drivers/gpio/gpio-reg.c @@ -46,7 +46,7 @@ static int gpio_reg_direction_output(struct gpio_chip *gc, unsigned offset, if (r->direction & BIT(offset)) return -ENOTSUPP; - gc->set(gc, offset, value); + gc->set_rv(gc, offset, value); return 0; } @@ -57,7 +57,7 @@ static int gpio_reg_direction_input(struct gpio_chip *gc, unsigned offset) return r->direction & BIT(offset) ? 0 : -ENOTSUPP; } -static void gpio_reg_set(struct gpio_chip *gc, unsigned offset, int value) +static int gpio_reg_set(struct gpio_chip *gc, unsigned int offset, int value) { struct gpio_reg *r = to_gpio_reg(gc); unsigned long flags; @@ -72,6 +72,8 @@ static void gpio_reg_set(struct gpio_chip *gc, unsigned offset, int value) r->out = val; writel_relaxed(val, r->reg); spin_unlock_irqrestore(&r->lock, flags); + + return 0; } static int gpio_reg_get(struct gpio_chip *gc, unsigned offset) @@ -92,8 +94,8 @@ static int gpio_reg_get(struct gpio_chip *gc, unsigned offset) return !!(val & mask); } -static void gpio_reg_set_multiple(struct gpio_chip *gc, unsigned long *mask, - unsigned long *bits) +static int gpio_reg_set_multiple(struct gpio_chip *gc, unsigned long *mask, + unsigned long *bits) { struct gpio_reg *r = to_gpio_reg(gc); unsigned long flags; @@ -102,6 +104,8 @@ static void gpio_reg_set_multiple(struct gpio_chip *gc, unsigned long *mask, r->out = (r->out & ~*mask) | (*bits & *mask); writel_relaxed(r->out, r->reg); spin_unlock_irqrestore(&r->lock, flags); + + return 0; } static int gpio_reg_to_irq(struct gpio_chip *gc, unsigned offset) @@ -157,9 +161,9 @@ struct gpio_chip *gpio_reg_init(struct device *dev, void __iomem *reg, r->gc.get_direction = gpio_reg_get_direction; r->gc.direction_input = gpio_reg_direction_input; r->gc.direction_output = gpio_reg_direction_output; - r->gc.set = gpio_reg_set; + r->gc.set_rv = gpio_reg_set; r->gc.get = gpio_reg_get; - r->gc.set_multiple = gpio_reg_set_multiple; + r->gc.set_multiple_rv = gpio_reg_set_multiple; if (irqs) r->gc.to_irq = gpio_reg_to_irq; r->gc.base = base; diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c index c63352f2f1ec..ecd60ff9e1dd 100644 --- a/drivers/gpio/gpio-rockchip.c +++ b/drivers/gpio/gpio-rockchip.c @@ -177,8 +177,8 @@ static int rockchip_gpio_set_direction(struct gpio_chip *chip, return 0; } -static void rockchip_gpio_set(struct gpio_chip *gc, unsigned int offset, - int value) +static int rockchip_gpio_set(struct gpio_chip *gc, unsigned int offset, + int value) { struct rockchip_pin_bank *bank = gpiochip_get_data(gc); unsigned long flags; @@ -186,6 +186,8 @@ static void rockchip_gpio_set(struct gpio_chip *gc, unsigned int offset, raw_spin_lock_irqsave(&bank->slock, flags); rockchip_gpio_writel_bit(bank, offset, value, bank->gpio_regs->port_dr); raw_spin_unlock_irqrestore(&bank->slock, flags); + + return 0; } static int rockchip_gpio_get(struct gpio_chip *gc, unsigned int offset) @@ -325,7 +327,7 @@ static int rockchip_gpio_to_irq(struct gpio_chip *gc, unsigned int offset) static const struct gpio_chip rockchip_gpiolib_chip = { .request = gpiochip_generic_request, .free = gpiochip_generic_free, - .set = rockchip_gpio_set, + .set_rv = rockchip_gpio_set, .get = rockchip_gpio_get, .get_direction = rockchip_gpio_get_direction, .direction_input = rockchip_gpio_direction_input, @@ -521,8 +523,8 @@ static int rockchip_interrupts_register(struct rockchip_pin_bank *bank) struct irq_chip_generic *gc; int ret; - bank->domain = irq_domain_create_linear(of_fwnode_handle(bank->of_node), 32, - &irq_generic_chip_ops, NULL); + bank->domain = irq_domain_create_linear(dev_fwnode(bank->dev), 32, &irq_generic_chip_ops, + NULL); if (!bank->domain) { dev_warn(bank->dev, "could not init irq domain for bank %s\n", bank->name); diff --git a/drivers/gpio/gpio-rtd.c b/drivers/gpio/gpio-rtd.c index bf7f008f58d7..25bbd749b019 100644 --- a/drivers/gpio/gpio-rtd.c +++ b/drivers/gpio/gpio-rtd.c @@ -275,7 +275,7 @@ static int rtd_gpio_set_config(struct gpio_chip *chip, unsigned int offset, } } -static void rtd_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) +static int rtd_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) { struct rtd_gpio *data = gpiochip_get_data(chip); u32 mask = BIT(offset % 32); @@ -292,6 +292,8 @@ static void rtd_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) else val &= ~mask; writel_relaxed(val, data->base + dato_reg_offset); + + return 0; } static int rtd_gpio_get(struct gpio_chip *chip, unsigned int offset) @@ -563,7 +565,7 @@ static int rtd_gpio_probe(struct platform_device *pdev) data->gpio_chip.get_direction = rtd_gpio_get_direction; data->gpio_chip.direction_input = rtd_gpio_direction_input; data->gpio_chip.direction_output = rtd_gpio_direction_output; - data->gpio_chip.set = rtd_gpio_set; + data->gpio_chip.set_rv = rtd_gpio_set; data->gpio_chip.get = rtd_gpio_get; data->gpio_chip.set_config = rtd_gpio_set_config; data->gpio_chip.parent = dev; diff --git a/drivers/gpio/gpio-sa1100.c b/drivers/gpio/gpio-sa1100.c index 3f3ee36bc3cb..e9d054d78ccb 100644 --- a/drivers/gpio/gpio-sa1100.c +++ b/drivers/gpio/gpio-sa1100.c @@ -43,11 +43,14 @@ static int sa1100_gpio_get(struct gpio_chip *chip, unsigned offset) BIT(offset); } -static void sa1100_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +static int sa1100_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) { int reg = value ? R_GPSR : R_GPCR; writel_relaxed(BIT(offset), sa1100_gpio_chip(chip)->membase + reg); + + return 0; } static int sa1100_get_direction(struct gpio_chip *chip, unsigned offset) @@ -96,7 +99,7 @@ static struct sa1100_gpio_chip sa1100_gpio_chip = { .get_direction = sa1100_get_direction, .direction_input = sa1100_direction_input, .direction_output = sa1100_direction_output, - .set = sa1100_gpio_set, + .set_rv = sa1100_gpio_set, .get = sa1100_gpio_get, .to_irq = sa1100_to_irq, .base = 0, diff --git a/drivers/gpio/gpio-sama5d2-piobu.c b/drivers/gpio/gpio-sama5d2-piobu.c index d770a6f3d846..c31244cf5e89 100644 --- a/drivers/gpio/gpio-sama5d2-piobu.c +++ b/drivers/gpio/gpio-sama5d2-piobu.c @@ -169,15 +169,15 @@ static int sama5d2_piobu_get(struct gpio_chip *chip, unsigned int pin) /* * sama5d2_piobu_set() - gpiochip set */ -static void sama5d2_piobu_set(struct gpio_chip *chip, unsigned int pin, - int value) +static int sama5d2_piobu_set(struct gpio_chip *chip, unsigned int pin, + int value) { if (!value) value = PIOBU_LOW; else value = PIOBU_HIGH; - sama5d2_piobu_write_value(chip, pin, PIOBU_SOD, value); + return sama5d2_piobu_write_value(chip, pin, PIOBU_SOD, value); } static int sama5d2_piobu_probe(struct platform_device *pdev) @@ -196,7 +196,7 @@ static int sama5d2_piobu_probe(struct platform_device *pdev) piobu->chip.direction_input = sama5d2_piobu_direction_input; piobu->chip.direction_output = sama5d2_piobu_direction_output; piobu->chip.get = sama5d2_piobu_get; - piobu->chip.set = sama5d2_piobu_set; + piobu->chip.set_rv = sama5d2_piobu_set; piobu->chip.base = -1; piobu->chip.ngpio = PIOBU_NUM; piobu->chip.can_sleep = 0; diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c index ff0341b1222f..833ffdd98d74 100644 --- a/drivers/gpio/gpio-sch.c +++ b/drivers/gpio/gpio-sch.c @@ -117,7 +117,7 @@ static int sch_gpio_get(struct gpio_chip *gc, unsigned int gpio_num) return sch_gpio_reg_get(sch, gpio_num, GLV); } -static void sch_gpio_set(struct gpio_chip *gc, unsigned int gpio_num, int val) +static int sch_gpio_set(struct gpio_chip *gc, unsigned int gpio_num, int val) { struct sch_gpio *sch = gpiochip_get_data(gc); unsigned long flags; @@ -125,6 +125,8 @@ static void sch_gpio_set(struct gpio_chip *gc, unsigned int gpio_num, int val) spin_lock_irqsave(&sch->lock, flags); sch_gpio_reg_set(sch, gpio_num, GLV, val); spin_unlock_irqrestore(&sch->lock, flags); + + return 0; } static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned int gpio_num, @@ -146,8 +148,7 @@ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned int gpio_num, * But we cannot prevent a short low pulse if direction is set to high * and an external pull-up is connected. */ - sch_gpio_set(gc, gpio_num, val); - return 0; + return sch_gpio_set(gc, gpio_num, val); } static int sch_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio_num) @@ -166,7 +167,7 @@ static const struct gpio_chip sch_gpio_chip = { .direction_input = sch_gpio_direction_in, .get = sch_gpio_get, .direction_output = sch_gpio_direction_out, - .set = sch_gpio_set, + .set_rv = sch_gpio_set, .get_direction = sch_gpio_get_direction, }; diff --git a/drivers/gpio/gpio-sch311x.c b/drivers/gpio/gpio-sch311x.c index ba4fccf3cc94..44fb5fc21fb8 100644 --- a/drivers/gpio/gpio-sch311x.c +++ b/drivers/gpio/gpio-sch311x.c @@ -178,14 +178,16 @@ static void __sch311x_gpio_set(struct sch311x_gpio_block *block, outb(data, block->runtime_reg + block->data_reg); } -static void sch311x_gpio_set(struct gpio_chip *chip, unsigned offset, - int value) +static int sch311x_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) { struct sch311x_gpio_block *block = gpiochip_get_data(chip); spin_lock(&block->lock); __sch311x_gpio_set(block, offset, value); spin_unlock(&block->lock); + + return 0; } static int sch311x_gpio_direction_in(struct gpio_chip *chip, unsigned offset) @@ -295,7 +297,7 @@ static int sch311x_gpio_probe(struct platform_device *pdev) block->chip.get_direction = sch311x_gpio_get_direction; block->chip.set_config = sch311x_gpio_set_config; block->chip.get = sch311x_gpio_get; - block->chip.set = sch311x_gpio_set; + block->chip.set_rv = sch311x_gpio_set; block->chip.ngpio = 8; block->chip.parent = &pdev->dev; block->chip.base = sch311x_gpio_blocks[i].base; diff --git a/drivers/gpio/gpio-siox.c b/drivers/gpio/gpio-siox.c index 051bc99bdfb2..95355dda621b 100644 --- a/drivers/gpio/gpio-siox.c +++ b/drivers/gpio/gpio-siox.c @@ -160,8 +160,8 @@ static int gpio_siox_get(struct gpio_chip *chip, unsigned int offset) return ret; } -static void gpio_siox_set(struct gpio_chip *chip, - unsigned int offset, int value) +static int gpio_siox_set(struct gpio_chip *chip, + unsigned int offset, int value) { struct gpio_siox_ddata *ddata = gpiochip_get_data(chip); u8 mask = 1 << (19 - offset); @@ -174,6 +174,8 @@ static void gpio_siox_set(struct gpio_chip *chip, ddata->setdata[0] &= ~mask; mutex_unlock(&ddata->lock); + + return 0; } static int gpio_siox_direction_input(struct gpio_chip *chip, @@ -191,8 +193,7 @@ static int gpio_siox_direction_output(struct gpio_chip *chip, if (offset < 12) return -EINVAL; - gpio_siox_set(chip, offset, value); - return 0; + return gpio_siox_set(chip, offset, value); } static int gpio_siox_get_direction(struct gpio_chip *chip, unsigned int offset) @@ -236,7 +237,7 @@ static int gpio_siox_probe(struct siox_device *sdevice) gc->parent = dev; gc->owner = THIS_MODULE; gc->get = gpio_siox_get; - gc->set = gpio_siox_set; + gc->set_rv = gpio_siox_set; gc->direction_input = gpio_siox_direction_input; gc->direction_output = gpio_siox_direction_output; gc->get_direction = gpio_siox_get_direction; diff --git a/drivers/gpio/gpio-sloppy-logic-analyzer.c b/drivers/gpio/gpio-sloppy-logic-analyzer.c index 8cf3b171c599..969dddd3d6fa 100644 --- a/drivers/gpio/gpio-sloppy-logic-analyzer.c +++ b/drivers/gpio/gpio-sloppy-logic-analyzer.c @@ -306,7 +306,7 @@ static void gpio_la_poll_remove(struct platform_device *pdev) } static const struct of_device_id gpio_la_poll_of_match[] = { - { .compatible = GPIO_LA_NAME }, + { .compatible = "gpio-sloppy-logic-analyzer" }, { } }; MODULE_DEVICE_TABLE(of, gpio_la_poll_of_match); diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c index 6a3c4c625138..abd13c79ace0 100644 --- a/drivers/gpio/gpio-sodaville.c +++ b/drivers/gpio/gpio-sodaville.c @@ -169,8 +169,8 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd, IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); - sd->id = irq_domain_create_legacy(of_fwnode_handle(pdev->dev.of_node), SDV_NUM_PUB_GPIOS, - sd->irq_base, 0, &irq_domain_sdv_ops, sd); + sd->id = irq_domain_create_legacy(dev_fwnode(&pdev->dev), SDV_NUM_PUB_GPIOS, sd->irq_base, + 0, &irq_domain_sdv_ops, sd); if (!sd->id) return -ENODEV; diff --git a/drivers/gpio/gpio-spear-spics.c b/drivers/gpio/gpio-spear-spics.c index 51539185400d..55f0e8afa291 100644 --- a/drivers/gpio/gpio-spear-spics.c +++ b/drivers/gpio/gpio-spear-spics.c @@ -51,13 +51,8 @@ struct spear_spics { struct gpio_chip chip; }; -/* gpio framework specific routines */ -static int spics_get_value(struct gpio_chip *chip, unsigned offset) -{ - return -ENXIO; -} - -static void spics_set_value(struct gpio_chip *chip, unsigned offset, int value) +static int spics_set_value(struct gpio_chip *chip, unsigned int offset, + int value) { struct spear_spics *spics = gpiochip_get_data(chip); u32 tmp; @@ -74,18 +69,14 @@ static void spics_set_value(struct gpio_chip *chip, unsigned offset, int value) tmp &= ~(0x1 << spics->cs_value_bit); tmp |= value << spics->cs_value_bit; writel_relaxed(tmp, spics->base + spics->perip_cfg); -} -static int spics_direction_input(struct gpio_chip *chip, unsigned offset) -{ - return -ENXIO; + return 0; } static int spics_direction_output(struct gpio_chip *chip, unsigned offset, int value) { - spics_set_value(chip, offset, value); - return 0; + return spics_set_value(chip, offset, value); } static int spics_request(struct gpio_chip *chip, unsigned offset) @@ -148,10 +139,8 @@ static int spics_gpio_probe(struct platform_device *pdev) spics->chip.base = -1; spics->chip.request = spics_request; spics->chip.free = spics_free; - spics->chip.direction_input = spics_direction_input; spics->chip.direction_output = spics_direction_output; - spics->chip.get = spics_get_value; - spics->chip.set = spics_set_value; + spics->chip.set_rv = spics_set_value; spics->chip.label = dev_name(&pdev->dev); spics->chip.parent = &pdev->dev; spics->chip.owner = THIS_MODULE; diff --git a/drivers/gpio/gpio-sprd.c b/drivers/gpio/gpio-sprd.c index c117c11bfb29..bbd5bf51c088 100644 --- a/drivers/gpio/gpio-sprd.c +++ b/drivers/gpio/gpio-sprd.c @@ -108,10 +108,12 @@ static int sprd_gpio_get(struct gpio_chip *chip, unsigned int offset) return sprd_gpio_read(chip, offset, SPRD_GPIO_DATA); } -static void sprd_gpio_set(struct gpio_chip *chip, unsigned int offset, - int value) +static int sprd_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) { sprd_gpio_update(chip, offset, SPRD_GPIO_DATA, value); + + return 0; } static void sprd_gpio_irq_mask(struct irq_data *data) @@ -243,7 +245,7 @@ static int sprd_gpio_probe(struct platform_device *pdev) sprd_gpio->chip.request = sprd_gpio_request; sprd_gpio->chip.free = sprd_gpio_free; sprd_gpio->chip.get = sprd_gpio_get; - sprd_gpio->chip.set = sprd_gpio_set; + sprd_gpio->chip.set_rv = sprd_gpio_set; sprd_gpio->chip.direction_input = sprd_gpio_direction_input; sprd_gpio->chip.direction_output = sprd_gpio_direction_output; diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index dce8ff322e47..0a270156e0be 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c @@ -54,7 +54,7 @@ static int stmpe_gpio_get(struct gpio_chip *chip, unsigned offset) return !!(ret & mask); } -static void stmpe_gpio_set(struct gpio_chip *chip, unsigned offset, int val) +static int stmpe_gpio_set(struct gpio_chip *chip, unsigned int offset, int val) { struct stmpe_gpio *stmpe_gpio = gpiochip_get_data(chip); struct stmpe *stmpe = stmpe_gpio->stmpe; @@ -67,9 +67,9 @@ static void stmpe_gpio_set(struct gpio_chip *chip, unsigned offset, int val) * For them we need to write 0 to clear and 1 to set. */ if (stmpe->regs[STMPE_IDX_GPSR_LSB] == stmpe->regs[STMPE_IDX_GPCR_LSB]) - stmpe_set_bits(stmpe, reg, mask, val ? mask : 0); - else - stmpe_reg_write(stmpe, reg, mask); + return stmpe_set_bits(stmpe, reg, mask, val ? mask : 0); + + return stmpe_reg_write(stmpe, reg, mask); } static int stmpe_gpio_get_direction(struct gpio_chip *chip, @@ -98,8 +98,11 @@ static int stmpe_gpio_direction_output(struct gpio_chip *chip, struct stmpe *stmpe = stmpe_gpio->stmpe; u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB + (offset / 8)]; u8 mask = BIT(offset % 8); + int ret; - stmpe_gpio_set(chip, offset, val); + ret = stmpe_gpio_set(chip, offset, val); + if (ret) + return ret; return stmpe_set_bits(stmpe, reg, mask, mask); } @@ -133,7 +136,7 @@ static const struct gpio_chip template_chip = { .direction_input = stmpe_gpio_direction_input, .get = stmpe_gpio_get, .direction_output = stmpe_gpio_direction_output, - .set = stmpe_gpio_set, + .set_rv = stmpe_gpio_set, .request = stmpe_gpio_request, .can_sleep = true, }; diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c index 5a6406d1f03a..fdda8de6ca36 100644 --- a/drivers/gpio/gpio-stp-xway.c +++ b/drivers/gpio/gpio-stp-xway.c @@ -113,7 +113,7 @@ static int xway_stp_get(struct gpio_chip *gc, unsigned int gpio) * * Set the shadow value and call ltq_ebu_apply. */ -static void xway_stp_set(struct gpio_chip *gc, unsigned gpio, int val) +static int xway_stp_set(struct gpio_chip *gc, unsigned int gpio, int val) { struct xway_stp *chip = gpiochip_get_data(gc); @@ -124,6 +124,8 @@ static void xway_stp_set(struct gpio_chip *gc, unsigned gpio, int val) xway_stp_w32(chip->virt, chip->shadow, XWAY_STP_CPU0); if (!chip->reserved) xway_stp_w32_mask(chip->virt, 0, XWAY_STP_CON_SWU, XWAY_STP_CON0); + + return 0; } /** @@ -136,9 +138,7 @@ static void xway_stp_set(struct gpio_chip *gc, unsigned gpio, int val) */ static int xway_stp_dir_out(struct gpio_chip *gc, unsigned gpio, int val) { - xway_stp_set(gc, gpio, val); - - return 0; + return xway_stp_set(gc, gpio, val); } /** @@ -249,7 +249,7 @@ static int xway_stp_probe(struct platform_device *pdev) chip->gc.label = "stp-xway"; chip->gc.direction_output = xway_stp_dir_out; chip->gc.get = xway_stp_get; - chip->gc.set = xway_stp_set; + chip->gc.set_rv = xway_stp_set; chip->gc.request = xway_stp_request; chip->gc.base = -1; chip->gc.owner = THIS_MODULE; diff --git a/drivers/gpio/gpio-syscon.c b/drivers/gpio/gpio-syscon.c index 5ab394ec81e6..f86f78655c24 100644 --- a/drivers/gpio/gpio-syscon.c +++ b/drivers/gpio/gpio-syscon.c @@ -40,8 +40,8 @@ struct syscon_gpio_data { unsigned int bit_count; unsigned int dat_bit_offset; unsigned int dir_bit_offset; - void (*set)(struct gpio_chip *chip, - unsigned offset, int value); + int (*set)(struct gpio_chip *chip, unsigned int offset, + int value); }; struct syscon_gpio_priv { @@ -68,17 +68,17 @@ static int syscon_gpio_get(struct gpio_chip *chip, unsigned offset) return !!(val & BIT(offs % SYSCON_REG_BITS)); } -static void syscon_gpio_set(struct gpio_chip *chip, unsigned offset, int val) +static int syscon_gpio_set(struct gpio_chip *chip, unsigned int offset, int val) { struct syscon_gpio_priv *priv = gpiochip_get_data(chip); unsigned int offs; offs = priv->dreg_offset + priv->data->dat_bit_offset + offset; - regmap_update_bits(priv->syscon, - (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, - BIT(offs % SYSCON_REG_BITS), - val ? BIT(offs % SYSCON_REG_BITS) : 0); + return regmap_update_bits(priv->syscon, + (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, + BIT(offs % SYSCON_REG_BITS), + val ? BIT(offs % SYSCON_REG_BITS) : 0); } static int syscon_gpio_dir_in(struct gpio_chip *chip, unsigned offset) @@ -115,9 +115,7 @@ static int syscon_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int val) BIT(offs % SYSCON_REG_BITS)); } - chip->set(chip, offset, val); - - return 0; + return chip->set_rv(chip, offset, val); } static const struct syscon_gpio_data clps711x_mctrl_gpio = { @@ -127,8 +125,8 @@ static const struct syscon_gpio_data clps711x_mctrl_gpio = { .dat_bit_offset = 0x40 * 8 + 8, }; -static void rockchip_gpio_set(struct gpio_chip *chip, unsigned int offset, - int val) +static int rockchip_gpio_set(struct gpio_chip *chip, unsigned int offset, + int val) { struct syscon_gpio_priv *priv = gpiochip_get_data(chip); unsigned int offs; @@ -144,6 +142,8 @@ static void rockchip_gpio_set(struct gpio_chip *chip, unsigned int offset, data); if (ret < 0) dev_err(chip->parent, "gpio write failed ret(%d)\n", ret); + + return ret; } static const struct syscon_gpio_data rockchip_rk3328_gpio_mute = { @@ -156,7 +156,8 @@ static const struct syscon_gpio_data rockchip_rk3328_gpio_mute = { #define KEYSTONE_LOCK_BIT BIT(0) -static void keystone_gpio_set(struct gpio_chip *chip, unsigned offset, int val) +static int keystone_gpio_set(struct gpio_chip *chip, unsigned int offset, + int val) { struct syscon_gpio_priv *priv = gpiochip_get_data(chip); unsigned int offs; @@ -165,7 +166,7 @@ static void keystone_gpio_set(struct gpio_chip *chip, unsigned offset, int val) offs = priv->dreg_offset + priv->data->dat_bit_offset + offset; if (!val) - return; + return 0; ret = regmap_update_bits( priv->syscon, @@ -174,6 +175,8 @@ static void keystone_gpio_set(struct gpio_chip *chip, unsigned offset, int val) BIT(offs % SYSCON_REG_BITS) | KEYSTONE_LOCK_BIT); if (ret < 0) dev_err(chip->parent, "gpio write failed ret(%d)\n", ret); + + return ret; } static const struct syscon_gpio_data keystone_dsp_gpio = { @@ -248,7 +251,7 @@ static int syscon_gpio_probe(struct platform_device *pdev) if (priv->data->flags & GPIO_SYSCON_FEAT_IN) priv->chip.direction_input = syscon_gpio_dir_in; if (priv->data->flags & GPIO_SYSCON_FEAT_OUT) { - priv->chip.set = priv->data->set ? : syscon_gpio_set; + priv->chip.set_rv = priv->data->set ? : syscon_gpio_set; priv->chip.direction_output = syscon_gpio_dir_out; } diff --git a/drivers/gpio/gpio-tangier.c b/drivers/gpio/gpio-tangier.c index a415e6d36173..ce17b98e0623 100644 --- a/drivers/gpio/gpio-tangier.c +++ b/drivers/gpio/gpio-tangier.c @@ -90,7 +90,7 @@ static int tng_gpio_get(struct gpio_chip *chip, unsigned int offset) return !!(readl(gplr) & BIT(shift)); } -static void tng_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) +static int tng_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) { struct tng_gpio *priv = gpiochip_get_data(chip); void __iomem *reg; @@ -101,6 +101,8 @@ static void tng_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) guard(raw_spinlock_irqsave)(&priv->lock); writel(BIT(shift), reg); + + return 0; } static int tng_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) @@ -428,7 +430,7 @@ int devm_tng_gpio_probe(struct device *dev, struct tng_gpio *gpio) gpio->chip.direction_input = tng_gpio_direction_input; gpio->chip.direction_output = tng_gpio_direction_output; gpio->chip.get = tng_gpio_get; - gpio->chip.set = tng_gpio_set; + gpio->chip.set_rv = tng_gpio_set; gpio->chip.get_direction = tng_gpio_get_direction; gpio->chip.set_config = tng_gpio_set_config; gpio->chip.base = info->base; diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c index 8cf676fd0a0b..1869ee7f9423 100644 --- a/drivers/gpio/gpio-tb10x.c +++ b/drivers/gpio/gpio-tb10x.c @@ -183,9 +183,8 @@ static int tb10x_gpio_probe(struct platform_device *pdev) if (ret != 0) return ret; - tb10x_gpio->domain = irq_domain_create_linear(of_fwnode_handle(np), - tb10x_gpio->gc.ngpio, - &irq_generic_chip_ops, NULL); + tb10x_gpio->domain = irq_domain_create_linear(dev_fwnode(dev), tb10x_gpio->gc.ngpio, + &irq_generic_chip_ops, NULL); if (!tb10x_gpio->domain) { return -ENOMEM; } diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index e62ee7e56908..0bd32809fd68 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c @@ -49,7 +49,7 @@ static int tc3589x_gpio_get(struct gpio_chip *chip, unsigned int offset) return !!(ret & mask); } -static void tc3589x_gpio_set(struct gpio_chip *chip, unsigned int offset, int val) +static int tc3589x_gpio_set(struct gpio_chip *chip, unsigned int offset, int val) { struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip); struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; @@ -57,7 +57,7 @@ static void tc3589x_gpio_set(struct gpio_chip *chip, unsigned int offset, int va unsigned int pos = offset % 8; u8 data[] = {val ? BIT(pos) : 0, BIT(pos)}; - tc3589x_block_write(tc3589x, reg, ARRAY_SIZE(data), data); + return tc3589x_block_write(tc3589x, reg, ARRAY_SIZE(data), data); } static int tc3589x_gpio_direction_output(struct gpio_chip *chip, @@ -67,8 +67,11 @@ static int tc3589x_gpio_direction_output(struct gpio_chip *chip, struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; u8 reg = TC3589x_GPIODIR0 + offset / 8; unsigned int pos = offset % 8; + int ret; - tc3589x_gpio_set(chip, offset, val); + ret = tc3589x_gpio_set(chip, offset, val); + if (ret) + return ret; return tc3589x_set_bits(tc3589x, reg, BIT(pos), BIT(pos)); } @@ -146,7 +149,7 @@ static const struct gpio_chip template_chip = { .label = "tc3589x", .owner = THIS_MODULE, .get = tc3589x_gpio_get, - .set = tc3589x_gpio_set, + .set_rv = tc3589x_gpio_set, .direction_output = tc3589x_gpio_direction_output, .direction_input = tc3589x_gpio_direction_input, .get_direction = tc3589x_gpio_get_direction, diff --git a/drivers/gpio/gpio-ts5500.c b/drivers/gpio/gpio-ts5500.c index 61cbec5c06a7..bb432ed73698 100644 --- a/drivers/gpio/gpio-ts5500.c +++ b/drivers/gpio/gpio-ts5500.c @@ -244,7 +244,7 @@ static int ts5500_gpio_output(struct gpio_chip *chip, unsigned offset, int val) return 0; } -static void ts5500_gpio_set(struct gpio_chip *chip, unsigned offset, int val) +static int ts5500_gpio_set(struct gpio_chip *chip, unsigned offset, int val) { struct ts5500_priv *priv = gpiochip_get_data(chip); const struct ts5500_dio line = priv->pinout[offset]; @@ -256,6 +256,8 @@ static void ts5500_gpio_set(struct gpio_chip *chip, unsigned offset, int val) else ts5500_clear_mask(line.value_mask, line.value_addr); spin_unlock_irqrestore(&priv->lock, flags); + + return 0; } static int ts5500_gpio_to_irq(struct gpio_chip *chip, unsigned offset) @@ -338,7 +340,7 @@ static int ts5500_dio_probe(struct platform_device *pdev) priv->gpio_chip.direction_input = ts5500_gpio_input; priv->gpio_chip.direction_output = ts5500_gpio_output; priv->gpio_chip.get = ts5500_gpio_get; - priv->gpio_chip.set = ts5500_gpio_set; + priv->gpio_chip.set_rv = ts5500_gpio_set; priv->gpio_chip.to_irq = ts5500_gpio_to_irq; priv->gpio_chip.base = -1; diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c index 0d17985a5fdc..c5d7825f19c1 100644 --- a/drivers/gpio/gpio-twl4030.c +++ b/drivers/gpio/gpio-twl4030.c @@ -523,7 +523,7 @@ static int gpio_twl4030_probe(struct platform_device *pdev) return irq_base; } - irq_domain_create_legacy(of_fwnode_handle(pdev->dev.of_node), TWL4030_GPIO_MAX, irq_base, 0, + irq_domain_create_legacy(dev_fwnode(&pdev->dev), TWL4030_GPIO_MAX, irq_base, 0, &irq_domain_simple_ops, NULL); ret = twl4030_sih_setup(&pdev->dev, TWL4030_MODULE_GPIO, irq_base); diff --git a/drivers/gpio/gpio-virtuser.c b/drivers/gpio/gpio-virtuser.c index eab6726953b4..a10eab7d2617 100644 --- a/drivers/gpio/gpio-virtuser.c +++ b/drivers/gpio/gpio-virtuser.c @@ -215,9 +215,7 @@ static int gpio_virtuser_set_array_value(struct gpio_descs *descs, struct gpio_virtuser_irq_work_context ctx; if (!atomic) - return gpiod_set_array_value_cansleep(descs->ndescs, - descs->desc, - descs->info, values); + return gpiod_multi_set_value_cansleep(descs, values); gpio_virtuser_init_irq_work_context(&ctx); ctx.work = IRQ_WORK_INIT_HARD(gpio_virtuser_set_value_array_atomic); diff --git a/drivers/gpio/gpiolib-legacy.c b/drivers/gpio/gpiolib-legacy.c index aeae6df8bec9..3bc93ccadb5b 100644 --- a/drivers/gpio/gpiolib-legacy.c +++ b/drivers/gpio/gpiolib-legacy.c @@ -86,44 +86,6 @@ static void devm_gpio_release(struct device *dev, void *res) } /** - * devm_gpio_request - request a GPIO for a managed device - * @dev: device to request the GPIO for - * @gpio: GPIO to allocate - * @label: the name of the requested GPIO - * - * Except for the extra @dev argument, this function takes the - * same arguments and performs the same function as gpio_request(). - * GPIOs requested with this function will be automatically freed - * on driver detach. - * - * **DEPRECATED** This function is deprecated and must not be used in new code. - * - * Returns: - * 0 on success, or negative errno on failure. - */ -int devm_gpio_request(struct device *dev, unsigned gpio, const char *label) -{ - unsigned *dr; - int rc; - - dr = devres_alloc(devm_gpio_release, sizeof(unsigned), GFP_KERNEL); - if (!dr) - return -ENOMEM; - - rc = gpio_request(gpio, label); - if (rc) { - devres_free(dr); - return rc; - } - - *dr = gpio; - devres_add(dev, dr); - - return 0; -} -EXPORT_SYMBOL_GPL(devm_gpio_request); - -/** * devm_gpio_request_one - request a single GPIO with initial setup * @dev: device to request for * @gpio: the GPIO number diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 4a3aa09dad9d..c4c21e25c682 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -3,7 +3,6 @@ #include <linux/bitops.h> #include <linux/cleanup.h> #include <linux/device.h> -#include <linux/idr.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/kdev_t.h> @@ -12,7 +11,6 @@ #include <linux/mutex.h> #include <linux/printk.h> #include <linux/slab.h> -#include <linux/spinlock.h> #include <linux/string.h> #include <linux/srcu.h> #include <linux/sysfs.h> @@ -45,6 +43,11 @@ struct gpiod_data { bool direction_can_change; }; +struct gpiodev_data { + struct gpio_device *gdev; + struct device *cdev_base; /* Class device by GPIO base */ +}; + /* * Lock to serialise gpiod export and unexport, and prevent re-export of * gpiod whose chip is being unregistered. @@ -73,7 +76,7 @@ static DEFINE_MUTEX(sysfs_lock); */ static ssize_t direction_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { struct gpiod_data *data = dev_get_drvdata(dev); struct gpio_desc *desc = data->desc; @@ -88,11 +91,12 @@ static ssize_t direction_show(struct device *dev, } static ssize_t direction_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) + struct device_attribute *attr, const char *buf, + size_t size) { struct gpiod_data *data = dev_get_drvdata(dev); struct gpio_desc *desc = data->desc; - ssize_t status; + ssize_t status; guard(mutex)(&data->mutex); @@ -109,12 +113,12 @@ static ssize_t direction_store(struct device *dev, } static DEVICE_ATTR_RW(direction); -static ssize_t value_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t value_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct gpiod_data *data = dev_get_drvdata(dev); struct gpio_desc *desc = data->desc; - ssize_t status; + ssize_t status; scoped_guard(mutex, &data->mutex) status = gpiod_get_value_cansleep(desc); @@ -125,8 +129,8 @@ static ssize_t value_show(struct device *dev, return sysfs_emit(buf, "%zd\n", status); } -static ssize_t value_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) +static ssize_t value_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) { struct gpiod_data *data = dev_get_drvdata(dev); struct gpio_desc *desc = data->desc; @@ -179,22 +183,22 @@ static int gpio_sysfs_request_irq(struct device *dev, unsigned char flags) irq_flags = IRQF_SHARED; if (flags & GPIO_IRQF_TRIGGER_FALLING) { irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? - IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING; + IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING; set_bit(FLAG_EDGE_FALLING, &desc->flags); } if (flags & GPIO_IRQF_TRIGGER_RISING) { irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? - IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; + IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; set_bit(FLAG_EDGE_RISING, &desc->flags); } /* * FIXME: This should be done in the irq_request_resources callback - * when the irq is requested, but a few drivers currently fail - * to do so. + * when the irq is requested, but a few drivers currently fail to do + * so. * - * Remove this redundant call (along with the corresponding - * unlock) when those drivers have been fixed. + * Remove this redundant call (along with the corresponding unlock) + * when those drivers have been fixed. */ ret = gpiochip_lock_as_irq(guard.gc, gpio_chip_hwgpio(desc)); if (ret < 0) @@ -240,15 +244,15 @@ static void gpio_sysfs_free_irq(struct device *dev) sysfs_put(data->value_kn); } -static const char * const trigger_names[] = { +static const char *const trigger_names[] = { [GPIO_IRQF_TRIGGER_NONE] = "none", [GPIO_IRQF_TRIGGER_FALLING] = "falling", [GPIO_IRQF_TRIGGER_RISING] = "rising", [GPIO_IRQF_TRIGGER_BOTH] = "both", }; -static ssize_t edge_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t edge_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct gpiod_data *data = dev_get_drvdata(dev); int flags; @@ -262,8 +266,8 @@ static ssize_t edge_show(struct device *dev, return sysfs_emit(buf, "%s\n", trigger_names[flags]); } -static ssize_t edge_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) +static ssize_t edge_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) { struct gpiod_data *data = dev_get_drvdata(dev); ssize_t status = size; @@ -302,7 +306,6 @@ static int gpio_sysfs_set_active_low(struct device *dev, int value) struct gpio_desc *desc = data->desc; int status = 0; - if (!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) == !!value) return 0; @@ -310,7 +313,7 @@ static int gpio_sysfs_set_active_low(struct device *dev, int value) /* reconfigure poll(2) support if enabled on one edge only */ if (flags == GPIO_IRQF_TRIGGER_FALLING || - flags == GPIO_IRQF_TRIGGER_RISING) { + flags == GPIO_IRQF_TRIGGER_RISING) { gpio_sysfs_free_irq(dev); status = gpio_sysfs_request_irq(dev, flags); } @@ -321,7 +324,7 @@ static int gpio_sysfs_set_active_low(struct device *dev, int value) } static ssize_t active_low_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { struct gpiod_data *data = dev_get_drvdata(dev); struct gpio_desc *desc = data->desc; @@ -334,7 +337,8 @@ static ssize_t active_low_show(struct device *dev, } static ssize_t active_low_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) + struct device_attribute *attr, + const char *buf, size_t size) { struct gpiod_data *data = dev_get_drvdata(dev); ssize_t status; @@ -397,30 +401,30 @@ static const struct attribute_group *gpio_groups[] = { * /ngpio ... matching gpio_chip.ngpio */ -static ssize_t base_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t base_show(struct device *dev, struct device_attribute *attr, + char *buf) { - const struct gpio_device *gdev = dev_get_drvdata(dev); + const struct gpiodev_data *data = dev_get_drvdata(dev); - return sysfs_emit(buf, "%u\n", gdev->base); + return sysfs_emit(buf, "%u\n", data->gdev->base); } static DEVICE_ATTR_RO(base); -static ssize_t label_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t label_show(struct device *dev, struct device_attribute *attr, + char *buf) { - const struct gpio_device *gdev = dev_get_drvdata(dev); + const struct gpiodev_data *data = dev_get_drvdata(dev); - return sysfs_emit(buf, "%s\n", gdev->label); + return sysfs_emit(buf, "%s\n", data->gdev->label); } static DEVICE_ATTR_RO(label); -static ssize_t ngpio_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t ngpio_show(struct device *dev, struct device_attribute *attr, + char *buf) { - const struct gpio_device *gdev = dev_get_drvdata(dev); + const struct gpiodev_data *data = dev_get_drvdata(dev); - return sysfs_emit(buf, "%u\n", gdev->ngpio); + return sysfs_emit(buf, "%u\n", data->gdev->ngpio); } static DEVICE_ATTR_RO(ngpio); @@ -439,8 +443,8 @@ ATTRIBUTE_GROUPS(gpiochip); * integer N ... number of GPIO to unexport */ static ssize_t export_store(const struct class *class, - const struct class_attribute *attr, - const char *buf, size_t len) + const struct class_attribute *attr, + const char *buf, size_t len) { struct gpio_desc *desc; int status, offset; @@ -498,8 +502,8 @@ done: static CLASS_ATTR_WO(export); static ssize_t unexport_store(const struct class *class, - const struct class_attribute *attr, - const char *buf, size_t len) + const struct class_attribute *attr, + const char *buf, size_t len) { struct gpio_desc *desc; int status; @@ -546,6 +550,26 @@ static const struct class gpio_class = { .class_groups = gpio_class_groups, }; +static int match_gdev(struct device *dev, const void *desc) +{ + struct gpiodev_data *data = dev_get_drvdata(dev); + const struct gpio_device *gdev = desc; + + return data && data->gdev == gdev; +} + +static struct gpiodev_data * +gdev_get_data(struct gpio_device *gdev) __must_hold(&sysfs_lock) +{ + struct device *cdev __free(put_device) = class_find_device(&gpio_class, + NULL, gdev, + match_gdev); + if (!cdev) + return NULL; + + return dev_get_drvdata(cdev); +}; + /** * gpiod_export - export a GPIO through sysfs * @desc: GPIO to make available, already requested @@ -591,12 +615,6 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) guard(mutex)(&sysfs_lock); - /* check if chip is being removed */ - if (!gdev->mockdev) { - status = -ENODEV; - goto err_clear_bit; - } - if (!test_bit(FLAG_REQUESTED, &desc->flags)) { gpiod_dbg(desc, "%s: unavailable (not requested)\n", __func__); status = -EPERM; @@ -713,15 +731,17 @@ void gpiod_unexport(struct gpio_desc *desc) } put_device(dev); + mutex_destroy(&data->mutex); kfree(data); } EXPORT_SYMBOL_GPL(gpiod_unexport); int gpiochip_sysfs_register(struct gpio_device *gdev) { + struct gpiodev_data *data; struct gpio_chip *chip; struct device *parent; - struct device *dev; + int err; /* * Many systems add gpio chips for SOC support very early, @@ -747,32 +767,42 @@ int gpiochip_sysfs_register(struct gpio_device *gdev) else parent = &gdev->dev; - /* use chip->base for the ID; it's already known to be unique */ - dev = device_create_with_groups(&gpio_class, parent, MKDEV(0, 0), gdev, - gpiochip_groups, GPIOCHIP_NAME "%d", - chip->base); - if (IS_ERR(dev)) - return PTR_ERR(dev); + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->gdev = gdev; guard(mutex)(&sysfs_lock); - gdev->mockdev = dev; + + /* use chip->base for the ID; it's already known to be unique */ + data->cdev_base = device_create_with_groups(&gpio_class, parent, + MKDEV(0, 0), data, + gpiochip_groups, + GPIOCHIP_NAME "%d", + chip->base); + if (IS_ERR(data->cdev_base)) { + err = PTR_ERR(data->cdev_base); + kfree(data); + return err; + } return 0; } void gpiochip_sysfs_unregister(struct gpio_device *gdev) { + struct gpiodev_data *data; struct gpio_desc *desc; struct gpio_chip *chip; scoped_guard(mutex, &sysfs_lock) { - if (!gdev->mockdev) + data = gdev_get_data(gdev); + if (!data) return; - device_unregister(gdev->mockdev); - - /* prevent further gpiod exports */ - gdev->mockdev = NULL; + device_unregister(data->cdev_base); + kfree(data); } guard(srcu)(&gdev->srcu); @@ -798,9 +828,6 @@ static int gpiofind_sysfs_register(struct gpio_chip *gc, const void *data) struct gpio_device *gdev = gc->gpiodev; int ret; - if (gdev->mockdev) - return 0; - ret = gpiochip_sysfs_register(gdev); if (ret) chip_err(gc, "failed to register the sysfs entry: %d\n", ret); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index fdafa0df1b43..7b2174b10219 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -75,6 +75,19 @@ static const struct bus_type gpio_bus_type = { }; /* + * At the end we want all GPIOs to be dynamically allocated from 0. + * However, some legacy drivers still perform fixed allocation. + * Until they are all fixed, leave 0-512 space for them. + */ +#define GPIO_DYNAMIC_BASE 512 +/* + * Define the maximum of the possible GPIO in the global numberspace. + * While the GPIO base and numbers are positive, we limit it with signed + * maximum as a lot of code is using negative values for special cases. + */ +#define GPIO_DYNAMIC_MAX INT_MAX + +/* * Number of GPIOs to use for the fast path in set array */ #define FASTPATH_NGPIO CONFIG_GPIOLIB_FASTPATH_LIMIT @@ -266,20 +279,6 @@ struct gpio_device *gpiod_to_gpio_device(struct gpio_desc *desc) EXPORT_SYMBOL_GPL(gpiod_to_gpio_device); /** - * gpiod_is_equal() - Check if two GPIO descriptors refer to the same pin. - * @desc: Descriptor to compare. - * @other: The second descriptor to compare against. - * - * Returns: - * True if the descriptors refer to the same physical pin. False otherwise. - */ -bool gpiod_is_equal(struct gpio_desc *desc, struct gpio_desc *other) -{ - return desc == other; -} -EXPORT_SYMBOL_GPL(gpiod_is_equal); - -/** * gpio_device_get_base() - Get the base GPIO number allocated by this device * @gdev: GPIO device * @@ -387,6 +386,21 @@ static int validate_desc(const struct gpio_desc *desc, const char *func) return; \ } while (0) +/** + * gpiod_is_equal() - Check if two GPIO descriptors refer to the same pin. + * @desc: Descriptor to compare. + * @other: The second descriptor to compare against. + * + * Returns: + * True if the descriptors refer to the same physical pin. False otherwise. + */ +bool gpiod_is_equal(const struct gpio_desc *desc, const struct gpio_desc *other) +{ + return validate_desc(desc, __func__) > 0 && + !IS_ERR_OR_NULL(other) && desc == other; +} +EXPORT_SYMBOL_GPL(gpiod_is_equal); + static int gpiochip_get_direction(struct gpio_chip *gc, unsigned int offset) { int ret; diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 58f64056de77..9b74738a9ca5 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -27,8 +27,6 @@ * @dev: the GPIO device struct * @chrdev: character device for the GPIO device * @id: numerical ID number for the GPIO chip - * @mockdev: class device used by the deprecated sysfs interface (may be - * NULL) * @owner: helps prevent removal of modules exporting active GPIOs * @chip: pointer to the corresponding gpiochip, holding static * data for this device @@ -65,7 +63,6 @@ struct gpio_device { struct device dev; struct cdev chrdev; int id; - struct device *mockdev; struct module *owner; struct gpio_chip __rcu *chip; struct gpio_desc *descs; |