diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-07-05 21:48:14 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-07-05 21:48:14 +0300 |
commit | b8052599420cd94505baec1f22b4e7c9e5ae5fce (patch) | |
tree | 80775d4b6c6d67948a1c5e9aa6bd70cb00838b7a /drivers | |
parent | 1f89a590b26e34ec7c32fbafaed446e52c3d0c3f (diff) | |
parent | c34c1228fc1cfe83aed909995f5b82e0ab7cb977 (diff) | |
download | linux-b8052599420cd94505baec1f22b4e7c9e5ae5fce.tar.xz |
Merge tag 'gpio-updates-for-v5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux
Pull gpio updates from Bartosz Golaszewski:
"One new driver, support for new models in existing ones, dt-bindings
conversions for several modules and improvements all over the place.
Summary:
- new driver for the IDT 79RC3243x GPIO controller
- device tree bindings coversion to YAML for the following drivers:
gpio-rk3328-grf, gpio-omap, gpio-davinci, gpio-zynq, gpio-stp,
gpio-pcf857x
- cleanup of probe functions in many drivers from Alexandru Ardelean,
mostly dropping unnecessary calls to platform_set_drvdata() and
removing error messages where none are needed (handled by the
subsystem already)
- several improvements to the core gpiolib and the sysfs interface
code from Andy Shevchenko
- conversion of the gpio-xilinx driver to using the bitmap API +
improvements of suspend/resume handling + minor tweaks
- convert the gpio-stmpe to using devres helpers exclusively in probe
for improved robustness
- updates for the generic gpio-regmap driver
- updates for the gpio-dwapb driver
- support for a new model in gpio-pca953x
- cleanups in gpio-tegra186, gpio-104-idio-16, gpio-mxs & gpio-xgene
- slight code refactoring of the gpio-zynq driver
- documentation fixes from Mauro Carvalho Chehab
- a bunch of minor tweaks and improvements all over the place"
* tag 'gpio-updates-for-v5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: (57 commits)
docs: driver-api: gpio: using-gpio.rst: avoid using ReST :doc:`foo` markup
dt-bindings: gpio: pcf857x: Convert to json-schema
gpio: mxs: Prefer unsigned int to bare use of unsigned
dt-bindings: gpio: stp: convert to json-schema
dt-bindings: gpio: zynq: convert bindings to YAML
dt-bindings: gpio: gpio-davinci: Convert to json-schema
gpio: pca953x: Add support for the On Semi pca9655
gpio: gpio-xilinx: update on suspend and resume calls
gpio: zynq: Check return value of irq_get_irq_data
gpio: zynq: Check return value of pm_runtime_get_sync
gpio: zynq: use module_platform_driver to simplify the code
gpio: idt3243x: Fix return value check in idt_gpio_probe()
MAINTAINERS: update ti,omap-gpio.yaml reference
dt-bindings: gpio: Add devicetree binding for IDT 79RC32434 GPIO controller
gpio: Add support for IDT 79RC3243x GPIO controller
gpio: regmap: move drvdata to config data
gpio-dwapb: Drop unused headers and sort the rest
gpio: gpio-regmap: Use devm_add_action_or_reset()
gpio: dwapb: Switch to use fwnode_irq_get()
gpio: dwapb: Drop redundant check in dwapb_irq_set_type()
...
Diffstat (limited to 'drivers')
36 files changed, 562 insertions, 549 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 63b84ba161dc..fab571016adf 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -782,6 +782,18 @@ config GPIO_MSC313 Say Y here to support the main GPIO block on MStar/SigmaStar ARMv7 based SoCs. +config GPIO_IDT3243X + tristate "IDT 79RC3243X GPIO support" + depends on MIKROTIK_RB532 || COMPILE_TEST + select GPIO_GENERIC + select GPIOLIB_IRQCHIP + help + Select this option to enable GPIO driver for + IDT 79RC3243X based devices like Mikrotik RB532. + + To compile this driver as a module, choose M here: the module will + be called gpio-idt3243x. + endmenu menu "Port-mapped I/O GPIO drivers" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index d7c81e1611a4..32a32659866a 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_GPIO_HISI) += gpio-hisi.o obj-$(CONFIG_GPIO_HLWD) += gpio-hlwd.o obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o obj-$(CONFIG_GPIO_ICH) += gpio-ich.o +obj-$(CONFIG_GPIO_IDT3243X) += gpio-idt3243x.o obj-$(CONFIG_GPIO_IOP) += gpio-iop.o obj-$(CONFIG_GPIO_IT87) += gpio-it87.o obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-16.c index 50ad0280fd78..55b40299ebfa 100644 --- a/drivers/gpio/gpio-104-idio-16.c +++ b/drivers/gpio/gpio-104-idio-16.c @@ -44,11 +44,12 @@ struct idio_16_gpio { struct gpio_chip chip; raw_spinlock_t lock; unsigned long irq_mask; - unsigned base; - unsigned out_state; + unsigned int base; + unsigned int out_state; }; -static int idio_16_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +static int idio_16_gpio_get_direction(struct gpio_chip *chip, + unsigned int offset) { if (offset > 15) return GPIO_LINE_DIRECTION_IN; @@ -56,22 +57,23 @@ static int idio_16_gpio_get_direction(struct gpio_chip *chip, unsigned offset) return GPIO_LINE_DIRECTION_OUT; } -static int idio_16_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +static int idio_16_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) { return 0; } static int idio_16_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int value) + unsigned int offset, int value) { chip->set(chip, offset, value); return 0; } -static int idio_16_gpio_get(struct gpio_chip *chip, unsigned offset) +static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset) { struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - const unsigned mask = BIT(offset-16); + const unsigned int mask = BIT(offset-16); if (offset < 16) return -EINVAL; @@ -96,10 +98,11 @@ static int idio_16_gpio_get_multiple(struct gpio_chip *chip, return 0; } -static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) { struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - const unsigned mask = BIT(offset); + const unsigned int mask = BIT(offset); unsigned long flags; if (offset > 15) @@ -180,7 +183,7 @@ static void idio_16_irq_unmask(struct irq_data *data) } } -static int idio_16_irq_set_type(struct irq_data *data, unsigned flow_type) +static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type) { /* The only valid irq types are none and both-edges */ if (flow_type != IRQ_TYPE_NONE && diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c index 0386ede53f3a..c55e821c63b6 100644 --- a/drivers/gpio/gpio-adp5520.c +++ b/drivers/gpio/gpio-adp5520.c @@ -113,10 +113,8 @@ static int adp5520_gpio_probe(struct platform_device *pdev) if (pdata->gpio_en_mask & (1 << i)) dev->lut[gpios++] = 1 << i; - if (gpios < 1) { - ret = -EINVAL; - goto err; - } + if (gpios < 1) + return -EINVAL; gc = &dev->gpio_chip; gc->direction_input = adp5520_gpio_direction_input; @@ -148,18 +146,10 @@ static int adp5520_gpio_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "failed to write\n"); - goto err; + return ret; } - ret = devm_gpiochip_add_data(&pdev->dev, &dev->gpio_chip, dev); - if (ret) - goto err; - - platform_set_drvdata(pdev, dev); - return 0; - -err: - return ret; + return devm_gpiochip_add_data(&pdev->dev, &dev->gpio_chip, dev); } static struct platform_driver adp5520_gpio_driver = { diff --git a/drivers/gpio/gpio-altera-a10sr.c b/drivers/gpio/gpio-altera-a10sr.c index b5917c48e4dc..6af51feda06f 100644 --- a/drivers/gpio/gpio-altera-a10sr.c +++ b/drivers/gpio/gpio-altera-a10sr.c @@ -78,7 +78,6 @@ static const struct gpio_chip altr_a10sr_gc = { static int altr_a10sr_gpio_probe(struct platform_device *pdev) { struct altr_a10sr_gpio *gpio; - int ret; struct altr_a10sr *a10sr = dev_get_drvdata(pdev->dev.parent); gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); @@ -91,15 +90,7 @@ static int altr_a10sr_gpio_probe(struct platform_device *pdev) gpio->gp.parent = pdev->dev.parent; gpio->gp.of_node = pdev->dev.of_node; - ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); } static const struct of_device_id altr_a10sr_gpio_of_match[] = { diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c index 678ddd375891..9b780dc5d390 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c @@ -234,7 +234,6 @@ static int ath79_gpio_probe(struct platform_device *pdev) ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); if (!ctrl) return -ENOMEM; - platform_set_drvdata(pdev, ctrl); if (np) { err = of_property_read_u32(np, "ngpios", &ath79_gpio_count); @@ -290,13 +289,7 @@ static int ath79_gpio_probe(struct platform_device *pdev) girq->handler = handle_simple_irq; } - err = devm_gpiochip_add_data(dev, &ctrl->gc, ctrl); - if (err) { - dev_err(dev, - "cannot add AR71xx GPIO chip, error=%d", err); - return err; - } - return 0; + return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl); } static struct platform_driver ath79_gpio_driver = { diff --git a/drivers/gpio/gpio-bd9571mwv.c b/drivers/gpio/gpio-bd9571mwv.c index df6102b57734..9a4d55f703bb 100644 --- a/drivers/gpio/gpio-bd9571mwv.c +++ b/drivers/gpio/gpio-bd9571mwv.c @@ -97,25 +97,16 @@ static const struct gpio_chip template_chip = { static int bd9571mwv_gpio_probe(struct platform_device *pdev) { struct bd9571mwv_gpio *gpio; - int ret; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) return -ENOMEM; - platform_set_drvdata(pdev, gpio); - gpio->regmap = dev_get_regmap(pdev->dev.parent, NULL); gpio->chip = template_chip; gpio->chip.parent = pdev->dev.parent; - ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); } static const struct platform_device_id bd9571mwv_gpio_id_table[] = { diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c index 9aa59afdcbbf..559188d80c2b 100644 --- a/drivers/gpio/gpio-da9052.c +++ b/drivers/gpio/gpio-da9052.c @@ -196,7 +196,6 @@ static int da9052_gpio_probe(struct platform_device *pdev) { struct da9052_gpio *gpio; struct da9052_pdata *pdata; - int ret; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) @@ -209,15 +208,7 @@ static int da9052_gpio_probe(struct platform_device *pdev) if (pdata && pdata->gpio_base) gpio->gp.base = pdata->gpio_base; - ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); } static struct platform_driver da9052_gpio_driver = { diff --git a/drivers/gpio/gpio-da9055.c b/drivers/gpio/gpio-da9055.c index 6ad0c37b862e..49446a030f10 100644 --- a/drivers/gpio/gpio-da9055.c +++ b/drivers/gpio/gpio-da9055.c @@ -133,7 +133,6 @@ static int da9055_gpio_probe(struct platform_device *pdev) { struct da9055_gpio *gpio; struct da9055_pdata *pdata; - int ret; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) @@ -146,15 +145,7 @@ static int da9055_gpio_probe(struct platform_device *pdev) if (pdata && pdata->gpio_base) gpio->gp.base = pdata->gpio_base; - ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio); } static struct platform_driver da9055_gpio_driver = { diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index d3233cc4b76b..3eb13d6d31ef 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -13,17 +13,15 @@ #include <linux/io.h> #include <linux/ioport.h> #include <linux/irq.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> +#include <linux/platform_data/gpio-dwapb.h> #include <linux/platform_device.h> #include <linux/property.h> #include <linux/reset.h> -#include <linux/spinlock.h> -#include <linux/platform_data/gpio-dwapb.h> #include <linux/slab.h> +#include <linux/spinlock.h> #include "gpiolib.h" #include "gpiolib-acpi.h" @@ -297,9 +295,6 @@ static int dwapb_irq_set_type(struct irq_data *d, u32 type) irq_hw_number_t bit = irqd_to_hwirq(d); unsigned long level, polarity, flags; - if (type & ~IRQ_TYPE_SENSE_MASK) - return -EINVAL; - spin_lock_irqsave(&gc->bgpio_lock, flags); level = dwapb_read(gpio, GPIO_INTTYPE_LEVEL); polarity = dwapb_read(gpio, GPIO_INT_POLARITY); @@ -531,17 +526,13 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, static void dwapb_get_irq(struct device *dev, struct fwnode_handle *fwnode, struct dwapb_port_property *pp) { - struct device_node *np = NULL; - int irq = -ENXIO, j; - - if (fwnode_property_read_bool(fwnode, "interrupt-controller")) - np = to_of_node(fwnode); + int irq, j; for (j = 0; j < pp->ngpio; j++) { - if (np) - irq = of_irq_get(np, j); - else if (has_acpi_companion(dev)) + if (has_acpi_companion(dev)) irq = platform_get_irq_optional(to_platform_device(dev), j); + else + irq = fwnode_irq_get(fwnode, j); if (irq > 0) pp->irq[j] = irq; } diff --git a/drivers/gpio/gpio-idt3243x.c b/drivers/gpio/gpio-idt3243x.c new file mode 100644 index 000000000000..50003ad2e589 --- /dev/null +++ b/drivers/gpio/gpio-idt3243x.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Driver for IDT/Renesas 79RC3243x Interrupt Controller */ + +#include <linux/bitops.h> +#include <linux/gpio/driver.h> +#include <linux/irq.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/platform_device.h> +#include <linux/spinlock.h> + +#define IDT_PIC_IRQ_PEND 0x00 +#define IDT_PIC_IRQ_MASK 0x08 + +#define IDT_GPIO_DIR 0x00 +#define IDT_GPIO_DATA 0x04 +#define IDT_GPIO_ILEVEL 0x08 +#define IDT_GPIO_ISTAT 0x0C + +struct idt_gpio_ctrl { + struct gpio_chip gc; + void __iomem *pic; + void __iomem *gpio; + u32 mask_cache; +}; + +static void idt_gpio_dispatch(struct irq_desc *desc) +{ + struct gpio_chip *gc = irq_desc_get_handler_data(desc); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + struct irq_chip *host_chip = irq_desc_get_chip(desc); + unsigned int bit, virq; + unsigned long pending; + + chained_irq_enter(host_chip, desc); + + pending = readl(ctrl->pic + IDT_PIC_IRQ_PEND); + pending &= ~ctrl->mask_cache; + for_each_set_bit(bit, &pending, gc->ngpio) { + virq = irq_linear_revmap(gc->irq.domain, bit); + if (virq) + generic_handle_irq(virq); + } + + chained_irq_exit(host_chip, desc); +} + +static int idt_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + unsigned int sense = flow_type & IRQ_TYPE_SENSE_MASK; + unsigned long flags; + u32 ilevel; + + /* hardware only supports level triggered */ + if (sense == IRQ_TYPE_NONE || (sense & IRQ_TYPE_EDGE_BOTH)) + return -EINVAL; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + ilevel = readl(ctrl->gpio + IDT_GPIO_ILEVEL); + if (sense & IRQ_TYPE_LEVEL_HIGH) + ilevel |= BIT(d->hwirq); + else if (sense & IRQ_TYPE_LEVEL_LOW) + ilevel &= ~BIT(d->hwirq); + + writel(ilevel, ctrl->gpio + IDT_GPIO_ILEVEL); + irq_set_handler_locked(d, handle_level_irq); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); + return 0; +} + +static void idt_gpio_ack(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + + writel(~BIT(d->hwirq), ctrl->gpio + IDT_GPIO_ISTAT); +} + +static void idt_gpio_mask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + unsigned long flags; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + ctrl->mask_cache |= BIT(d->hwirq); + writel(ctrl->mask_cache, ctrl->pic + IDT_PIC_IRQ_MASK); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); +} + +static void idt_gpio_unmask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + unsigned long flags; + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + ctrl->mask_cache &= ~BIT(d->hwirq); + writel(ctrl->mask_cache, ctrl->pic + IDT_PIC_IRQ_MASK); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); +} + +static int idt_gpio_irq_init_hw(struct gpio_chip *gc) +{ + struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc); + + /* Mask interrupts. */ + ctrl->mask_cache = 0xffffffff; + writel(ctrl->mask_cache, ctrl->pic + IDT_PIC_IRQ_MASK); + + return 0; +} + +static struct irq_chip idt_gpio_irqchip = { + .name = "IDTGPIO", + .irq_mask = idt_gpio_mask, + .irq_ack = idt_gpio_ack, + .irq_unmask = idt_gpio_unmask, + .irq_set_type = idt_gpio_irq_set_type +}; + +static int idt_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct gpio_irq_chip *girq; + struct idt_gpio_ctrl *ctrl; + unsigned int parent_irq; + int ngpios; + int ret; + + + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); + if (!ctrl) + return -ENOMEM; + + ctrl->gpio = devm_platform_ioremap_resource_byname(pdev, "gpio"); + if (IS_ERR(ctrl->gpio)) + return PTR_ERR(ctrl->gpio); + + ctrl->gc.parent = dev; + + ret = bgpio_init(&ctrl->gc, &pdev->dev, 4, ctrl->gpio + IDT_GPIO_DATA, + NULL, NULL, ctrl->gpio + IDT_GPIO_DIR, NULL, 0); + if (ret) { + dev_err(dev, "bgpio_init failed\n"); + return ret; + } + + ret = device_property_read_u32(dev, "ngpios", &ngpios); + if (!ret) + ctrl->gc.ngpio = ngpios; + + if (device_property_read_bool(dev, "interrupt-controller")) { + ctrl->pic = devm_platform_ioremap_resource_byname(pdev, "pic"); + if (IS_ERR(ctrl->pic)) + return PTR_ERR(ctrl->pic); + + parent_irq = platform_get_irq(pdev, 0); + if (!parent_irq) + return -EINVAL; + + girq = &ctrl->gc.irq; + girq->chip = &idt_gpio_irqchip; + girq->init_hw = idt_gpio_irq_init_hw; + girq->parent_handler = idt_gpio_dispatch; + girq->num_parents = 1; + girq->parents = devm_kcalloc(dev, girq->num_parents, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + + girq->parents[0] = parent_irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + } + + return devm_gpiochip_add_data(&pdev->dev, &ctrl->gc, ctrl); +} + +static const struct of_device_id idt_gpio_of_match[] = { + { .compatible = "idt,32434-gpio" }, + { } +}; +MODULE_DEVICE_TABLE(of, idt_gpio_of_match); + +static struct platform_driver idt_gpio_driver = { + .probe = idt_gpio_probe, + .driver = { + .name = "idt3243x-gpio", + .of_match_table = idt_gpio_of_match, + }, +}; +module_platform_driver(idt_gpio_driver); + +MODULE_DESCRIPTION("IDT 79RC3243x GPIO/PIC Driver"); +MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-logicvc.c b/drivers/gpio/gpio-logicvc.c index 015632cf159f..992cc958a43f 100644 --- a/drivers/gpio/gpio-logicvc.c +++ b/drivers/gpio/gpio-logicvc.c @@ -114,10 +114,8 @@ static int logicvc_gpio_probe(struct platform_device *pdev) } base = devm_ioremap_resource(dev, &res); - if (IS_ERR(base)) { - dev_err(dev, "Failed to map I/O base\n"); + if (IS_ERR(base)) return PTR_ERR(base); - } logicvc_gpio_regmap_config.max_register = resource_size(&res) - logicvc_gpio_regmap_config.reg_stride; diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index d7e73876a3b9..0a9d746a0fe0 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -144,12 +144,9 @@ static void gpio_mockup_set_multiple(struct gpio_chip *gc, static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip, unsigned int offset, int value) { + struct gpio_chip *gc = &chip->gc; + struct gpio_desc *desc = gpiochip_get_desc(gc, offset); int curr, irq, irq_type, ret = 0; - struct gpio_desc *desc; - struct gpio_chip *gc; - - gc = &chip->gc; - desc = &gc->gpiodev->descs[offset]; mutex_lock(&chip->lock); @@ -369,7 +366,7 @@ static void gpio_mockup_debugfs_setup(struct device *dev, priv->chip = chip; priv->offset = i; - priv->desc = &gc->gpiodev->descs[i]; + priv->desc = gpiochip_get_desc(gc, i); debugfs_create_file(name, 0200, chip->dbg_dir, priv, &gpio_mockup_debugfs_ops); diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 524b668eb1ac..31a336b86ff2 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -229,14 +229,14 @@ static int mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base) return rv; } -static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset) +static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned int offset) { struct mxs_gpio_port *port = gpiochip_get_data(gc); return irq_find_mapping(port->domain, offset); } -static int mxs_gpio_get_direction(struct gpio_chip *gc, unsigned offset) +static int mxs_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) { struct mxs_gpio_port *port = gpiochip_get_data(gc); u32 mask = 1 << offset; diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index c91d05651596..f5cfc0698799 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -1241,6 +1241,7 @@ static const struct of_device_id pca953x_dt_ids[] = { { .compatible = "onnn,cat9554", .data = OF_953X( 8, PCA_INT), }, { .compatible = "onnn,pca9654", .data = OF_953X( 8, PCA_INT), }, + { .compatible = "onnn,pca9655", .data = OF_953X(16, PCA_INT), }, { .compatible = "exar,xra1202", .data = OF_953X( 8, 0), }, { } diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c index 134cedf151a7..69c219742083 100644 --- a/drivers/gpio/gpio-regmap.c +++ b/drivers/gpio/gpio-regmap.c @@ -178,12 +178,6 @@ static int gpio_regmap_direction_output(struct gpio_chip *chip, return gpio_regmap_set_direction(chip, offset, true); } -void gpio_regmap_set_drvdata(struct gpio_regmap *gpio, void *data) -{ - gpio->driver_data = data; -} -EXPORT_SYMBOL_GPL(gpio_regmap_set_drvdata); - void *gpio_regmap_get_drvdata(struct gpio_regmap *gpio) { return gpio->driver_data; @@ -226,6 +220,7 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config return ERR_PTR(-ENOMEM); gpio->parent = config->parent; + gpio->driver_data = config->drvdata; gpio->regmap = config->regmap; gpio->ngpio_per_reg = config->ngpio_per_reg; gpio->reg_stride = config->reg_stride; @@ -311,9 +306,9 @@ void gpio_regmap_unregister(struct gpio_regmap *gpio) } EXPORT_SYMBOL_GPL(gpio_regmap_unregister); -static void devm_gpio_regmap_unregister(struct device *dev, void *res) +static void devm_gpio_regmap_unregister(void *res) { - gpio_regmap_unregister(*(struct gpio_regmap **)res); + gpio_regmap_unregister(res); } /** @@ -330,20 +325,17 @@ static void devm_gpio_regmap_unregister(struct device *dev, void *res) struct gpio_regmap *devm_gpio_regmap_register(struct device *dev, const struct gpio_regmap_config *config) { - struct gpio_regmap **ptr, *gpio; - - ptr = devres_alloc(devm_gpio_regmap_unregister, sizeof(*ptr), - GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); + struct gpio_regmap *gpio; + int ret; gpio = gpio_regmap_register(config); - if (!IS_ERR(gpio)) { - *ptr = gpio; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } + + if (IS_ERR(gpio)) + return gpio; + + ret = devm_add_action_or_reset(dev, devm_gpio_regmap_unregister, gpio); + if (ret) + return ERR_PTR(ret); return gpio; } diff --git a/drivers/gpio/gpio-spear-spics.c b/drivers/gpio/gpio-spear-spics.c index 6eca531b7d96..49aac2bb8d2c 100644 --- a/drivers/gpio/gpio-spear-spics.c +++ b/drivers/gpio/gpio-spear-spics.c @@ -122,7 +122,6 @@ static int spics_gpio_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct spear_spics *spics; - int ret; spics = devm_kzalloc(&pdev->dev, sizeof(*spics), GFP_KERNEL); if (!spics) @@ -148,8 +147,6 @@ static int spics_gpio_probe(struct platform_device *pdev) &spics->cs_enable_shift)) goto err_dt_data; - platform_set_drvdata(pdev, spics); - spics->chip.ngpio = NUM_OF_GPIO; spics->chip.base = -1; spics->chip.request = spics_request; @@ -163,14 +160,7 @@ static int spics_gpio_probe(struct platform_device *pdev) spics->chip.owner = THIS_MODULE; spics->last_off = -1; - ret = devm_gpiochip_add_data(&pdev->dev, &spics->chip, spics); - if (ret) { - dev_err(&pdev->dev, "unable to add gpio chip\n"); - return ret; - } - - dev_info(&pdev->dev, "spear spics registered\n"); - return 0; + return devm_gpiochip_add_data(&pdev->dev, &spics->chip, spics); err_dt_data: dev_err(&pdev->dev, "DT probe failed\n"); diff --git a/drivers/gpio/gpio-sprd.c b/drivers/gpio/gpio-sprd.c index 36ea8a3bd451..25c37edcbc6c 100644 --- a/drivers/gpio/gpio-sprd.c +++ b/drivers/gpio/gpio-sprd.c @@ -222,7 +222,6 @@ static int sprd_gpio_probe(struct platform_device *pdev) { struct gpio_irq_chip *irq; struct sprd_gpio *sprd_gpio; - int ret; sprd_gpio = devm_kzalloc(&pdev->dev, sizeof(*sprd_gpio), GFP_KERNEL); if (!sprd_gpio) @@ -259,14 +258,7 @@ static int sprd_gpio_probe(struct platform_device *pdev) irq->num_parents = 1; irq->parents = &sprd_gpio->irq; - ret = devm_gpiochip_add_data(&pdev->dev, &sprd_gpio->chip, sprd_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, sprd_gpio); - return 0; + return devm_gpiochip_add_data(&pdev->dev, &sprd_gpio->chip, sprd_gpio); } static const struct of_device_id sprd_gpio_of_match[] = { diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c index a74bb97a41e2..392fcab06ab8 100644 --- a/drivers/gpio/gpio-sta2x11.c +++ b/drivers/gpio/gpio-sta2x11.c @@ -398,15 +398,7 @@ static int gsta_probe(struct platform_device *dev) return err; } - err = devm_gpiochip_add_data(&dev->dev, &chip->gpio, chip); - if (err < 0) { - dev_err(&dev->dev, "sta2x11 gpio: Can't register (%i)\n", - -err); - return err; - } - - platform_set_drvdata(dev, chip); - return 0; + return devm_gpiochip_add_data(&dev->dev, &chip->gpio, chip); } static struct platform_driver sta2x11_gpio_platform_driver = { diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index b94ef8181428..dd4d58b4ae49 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c @@ -449,6 +449,11 @@ static void stmpe_init_irq_valid_mask(struct gpio_chip *gc, } } +static void stmpe_gpio_disable(void *stmpe) +{ + stmpe_disable(stmpe, STMPE_BLOCK_GPIO); +} + static int stmpe_gpio_probe(struct platform_device *pdev) { struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); @@ -461,7 +466,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev) return -EINVAL; } - stmpe_gpio = kzalloc(sizeof(*stmpe_gpio), GFP_KERNEL); + stmpe_gpio = devm_kzalloc(&pdev->dev, sizeof(*stmpe_gpio), GFP_KERNEL); if (!stmpe_gpio) return -ENOMEM; @@ -489,7 +494,11 @@ static int stmpe_gpio_probe(struct platform_device *pdev) ret = stmpe_enable(stmpe, STMPE_BLOCK_GPIO); if (ret) - goto out_free; + return ret; + + ret = devm_add_action_or_reset(&pdev->dev, stmpe_gpio_disable, stmpe); + if (ret) + return ret; if (irq > 0) { struct gpio_irq_chip *girq; @@ -499,7 +508,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev) "stmpe-gpio", stmpe_gpio); if (ret) { dev_err(&pdev->dev, "unable to get irq: %d\n", ret); - goto out_disable; + return ret; } girq = &stmpe_gpio->chip.irq; @@ -514,22 +523,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev) girq->init_valid_mask = stmpe_init_irq_valid_mask; } - ret = gpiochip_add_data(&stmpe_gpio->chip, stmpe_gpio); - if (ret) { - dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); - goto out_disable; - } - - platform_set_drvdata(pdev, stmpe_gpio); - - return 0; - -out_disable: - stmpe_disable(stmpe, STMPE_BLOCK_GPIO); - gpiochip_remove(&stmpe_gpio->chip); -out_free: - kfree(stmpe_gpio); - return ret; + return devm_gpiochip_add_data(&pdev->dev, &stmpe_gpio->chip, stmpe_gpio); } static struct platform_driver stmpe_gpio_driver = { diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 55b8dbd13d11..8d158492488f 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c @@ -357,16 +357,7 @@ static int tc3589x_gpio_probe(struct platform_device *pdev) return ret; } - ret = devm_gpiochip_add_data(&pdev->dev, &tc3589x_gpio->chip, - tc3589x_gpio); - if (ret) { - dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tc3589x_gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &tc3589x_gpio->chip, tc3589x_gpio); } static struct platform_driver tc3589x_gpio_driver = { diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index 05974b760796..d38980b9923a 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -730,18 +730,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev) offset += port->pins; } - platform_set_drvdata(pdev, gpio); - - err = devm_gpiochip_add_data(&pdev->dev, &gpio->gpio, gpio); - if (err < 0) - return err; - - return 0; -} - -static int tegra186_gpio_remove(struct platform_device *pdev) -{ - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gpio, gpio); } #define TEGRA186_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \ @@ -913,7 +902,6 @@ static struct platform_driver tegra186_gpio_driver = { .of_match_table = tegra186_gpio_of_match, }, .probe = tegra186_gpio_probe, - .remove = tegra186_gpio_remove, }; module_platform_driver(tegra186_gpio_driver); diff --git a/drivers/gpio/gpio-tps65218.c b/drivers/gpio/gpio-tps65218.c index 43a1150055ce..3517debe2b0b 100644 --- a/drivers/gpio/gpio-tps65218.c +++ b/drivers/gpio/gpio-tps65218.c @@ -187,7 +187,6 @@ static int tps65218_gpio_probe(struct platform_device *pdev) { struct tps65218 *tps65218 = dev_get_drvdata(pdev->dev.parent); struct tps65218_gpio *tps65218_gpio; - int ret; tps65218_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps65218_gpio), GFP_KERNEL); @@ -201,16 +200,8 @@ static int tps65218_gpio_probe(struct platform_device *pdev) tps65218_gpio->gpio_chip.of_node = pdev->dev.of_node; #endif - ret = devm_gpiochip_add_data(&pdev->dev, &tps65218_gpio->gpio_chip, - tps65218_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tps65218_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &tps65218_gpio->gpio_chip, + tps65218_gpio); } static const struct of_device_id tps65218_dt_match[] = { diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c index 9b6cc74f47c8..da0304b764a5 100644 --- a/drivers/gpio/gpio-tps6586x.c +++ b/drivers/gpio/gpio-tps6586x.c @@ -76,7 +76,6 @@ static int tps6586x_gpio_probe(struct platform_device *pdev) { struct tps6586x_platform_data *pdata; struct tps6586x_gpio *tps6586x_gpio; - int ret; pdata = dev_get_platdata(pdev->dev.parent); tps6586x_gpio = devm_kzalloc(&pdev->dev, @@ -106,16 +105,8 @@ static int tps6586x_gpio_probe(struct platform_device *pdev) else tps6586x_gpio->gpio_chip.base = -1; - ret = devm_gpiochip_add_data(&pdev->dev, &tps6586x_gpio->gpio_chip, - tps6586x_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tps6586x_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &tps6586x_gpio->gpio_chip, + tps6586x_gpio); } static struct platform_driver tps6586x_gpio_driver = { diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c index 0c0b445c75c0..7fa8c841081f 100644 --- a/drivers/gpio/gpio-tps65910.c +++ b/drivers/gpio/gpio-tps65910.c @@ -165,16 +165,8 @@ static int tps65910_gpio_probe(struct platform_device *pdev) } skip_init: - ret = devm_gpiochip_add_data(&pdev->dev, &tps65910_gpio->gpio_chip, - tps65910_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tps65910_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &tps65910_gpio->gpio_chip, + tps65910_gpio); } static struct platform_driver tps65910_gpio_driver = { diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c index 510d9ed9fd2a..fab771cb6a87 100644 --- a/drivers/gpio/gpio-tps65912.c +++ b/drivers/gpio/gpio-tps65912.c @@ -99,7 +99,6 @@ static int tps65912_gpio_probe(struct platform_device *pdev) { struct tps65912 *tps = dev_get_drvdata(pdev->dev.parent); struct tps65912_gpio *gpio; - int ret; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) @@ -109,16 +108,7 @@ static int tps65912_gpio_probe(struct platform_device *pdev) gpio->gpio_chip = template_chip; gpio->gpio_chip.parent = tps->dev; - ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gpio_chip, - gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, gpio); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->gpio_chip, gpio); } static const struct platform_device_id tps65912_gpio_id_table[] = { diff --git a/drivers/gpio/gpio-tps68470.c b/drivers/gpio/gpio-tps68470.c index f7f5f770e0fb..423b7bc30ae8 100644 --- a/drivers/gpio/gpio-tps68470.c +++ b/drivers/gpio/gpio-tps68470.c @@ -125,7 +125,6 @@ static const char *tps68470_names[TPS68470_N_GPIO] = { static int tps68470_gpio_probe(struct platform_device *pdev) { struct tps68470_gpio_data *tps68470_gpio; - int ret; tps68470_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps68470_gpio), GFP_KERNEL); @@ -146,16 +145,7 @@ static int tps68470_gpio_probe(struct platform_device *pdev) tps68470_gpio->gc.base = -1; tps68470_gpio->gc.parent = &pdev->dev; - ret = devm_gpiochip_add_data(&pdev->dev, &tps68470_gpio->gc, - tps68470_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to register gpio_chip: %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tps68470_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &tps68470_gpio->gc, tps68470_gpio); } static struct platform_driver tps68470_gpio_driver = { diff --git a/drivers/gpio/gpio-visconti.c b/drivers/gpio/gpio-visconti.c index 0e3d19828eb1..47455810bdb9 100644 --- a/drivers/gpio/gpio-visconti.c +++ b/drivers/gpio/gpio-visconti.c @@ -187,15 +187,7 @@ static int visconti_gpio_probe(struct platform_device *pdev) girq->default_type = IRQ_TYPE_NONE; girq->handler = handle_level_irq; - ret = devm_gpiochip_add_data(dev, &priv->gpio_chip, priv); - if (ret) { - dev_err(dev, "failed to add GPIO chip\n"); - return ret; - } - - platform_set_drvdata(pdev, priv); - - return ret; + return devm_gpiochip_add_data(dev, &priv->gpio_chip, priv); } static const struct of_device_id visconti_gpio_of_match[] = { diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c index a3a32a77041f..9cf1e5ebb352 100644 --- a/drivers/gpio/gpio-wm831x.c +++ b/drivers/gpio/gpio-wm831x.c @@ -261,7 +261,6 @@ static int wm831x_gpio_probe(struct platform_device *pdev) struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_pdata *pdata = &wm831x->pdata; struct wm831x_gpio *wm831x_gpio; - int ret; wm831x_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm831x_gpio), GFP_KERNEL); @@ -280,16 +279,7 @@ static int wm831x_gpio_probe(struct platform_device *pdev) wm831x_gpio->gpio_chip.of_node = wm831x->dev->of_node; #endif - ret = devm_gpiochip_add_data(&pdev->dev, &wm831x_gpio->gpio_chip, - wm831x_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, wm831x_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &wm831x_gpio->gpio_chip, wm831x_gpio); } static struct platform_driver wm831x_gpio_driver = { diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c index 460f0a4b04bd..b1b131fb9804 100644 --- a/drivers/gpio/gpio-wm8350.c +++ b/drivers/gpio/gpio-wm8350.c @@ -105,7 +105,6 @@ static int wm8350_gpio_probe(struct platform_device *pdev) struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent); struct wm8350_platform_data *pdata = dev_get_platdata(wm8350->dev); struct wm8350_gpio_data *wm8350_gpio; - int ret; wm8350_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm8350_gpio), GFP_KERNEL); @@ -121,16 +120,7 @@ static int wm8350_gpio_probe(struct platform_device *pdev) else wm8350_gpio->gpio_chip.base = -1; - ret = devm_gpiochip_add_data(&pdev->dev, &wm8350_gpio->gpio_chip, - wm8350_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, wm8350_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &wm8350_gpio->gpio_chip, wm8350_gpio); } static struct platform_driver wm8350_gpio_driver = { diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c index 9af89cf7f6bc..f4a474cef32d 100644 --- a/drivers/gpio/gpio-wm8994.c +++ b/drivers/gpio/gpio-wm8994.c @@ -263,7 +263,6 @@ static int wm8994_gpio_probe(struct platform_device *pdev) struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent); struct wm8994_pdata *pdata = dev_get_platdata(wm8994->dev); struct wm8994_gpio *wm8994_gpio; - int ret; wm8994_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm8994_gpio), GFP_KERNEL); @@ -279,17 +278,7 @@ static int wm8994_gpio_probe(struct platform_device *pdev) else wm8994_gpio->gpio_chip.base = -1; - ret = devm_gpiochip_add_data(&pdev->dev, &wm8994_gpio->gpio_chip, - wm8994_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Could not register gpiochip, %d\n", - ret); - return ret; - } - - platform_set_drvdata(pdev, wm8994_gpio); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &wm8994_gpio->gpio_chip, wm8994_gpio); } static struct platform_driver wm8994_gpio_driver = { diff --git a/drivers/gpio/gpio-xgene.c b/drivers/gpio/gpio-xgene.c index 532b0df8a1f2..fb4b0c67aeef 100644 --- a/drivers/gpio/gpio-xgene.c +++ b/drivers/gpio/gpio-xgene.c @@ -159,7 +159,6 @@ static SIMPLE_DEV_PM_OPS(xgene_gpio_pm, xgene_gpio_suspend, xgene_gpio_resume); static int xgene_gpio_probe(struct platform_device *pdev) { struct xgene_gpio *gpio; - int err = 0; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) @@ -183,15 +182,7 @@ static int xgene_gpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, gpio); - err = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); - if (err) { - dev_err(&pdev->dev, - "failed to register gpiochip.\n"); - return err; - } - - dev_info(&pdev->dev, "X-Gene GPIO driver registered.\n"); - return 0; + return devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); } static const struct of_device_id xgene_gpio_of_match[] = { diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index 136557e7dd3c..c329c3a606e8 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -5,6 +5,7 @@ * Copyright 2008 - 2013 Xilinx, Inc. */ +#include <linux/bitmap.h> #include <linux/bitops.h> #include <linux/clk.h> #include <linux/errno.h> @@ -23,7 +24,8 @@ #define XGPIO_DATA_OFFSET (0x0) /* Data register */ #define XGPIO_TRI_OFFSET (0x4) /* I/O direction register */ -#define XGPIO_CHANNEL_OFFSET 0x8 +#define XGPIO_CHANNEL0_OFFSET 0x0 +#define XGPIO_CHANNEL1_OFFSET 0x8 #define XGPIO_GIER_OFFSET 0x11c /* Global Interrupt Enable */ #define XGPIO_GIER_IE BIT(31) @@ -43,56 +45,101 @@ * struct xgpio_instance - Stores information about GPIO device * @gc: GPIO chip * @regs: register block - * @gpio_width: GPIO width for every channel - * @gpio_state: GPIO write state shadow register - * @gpio_last_irq_read: GPIO read state register from last interrupt - * @gpio_dir: GPIO direction shadow register + * @hw_map: GPIO pin mapping on hardware side + * @sw_map: GPIO pin mapping on software side + * @state: GPIO write state shadow register + * @last_irq_read: GPIO read state register from last interrupt + * @dir: GPIO direction shadow register * @gpio_lock: Lock used for synchronization * @irq: IRQ used by GPIO device * @irqchip: IRQ chip - * @irq_enable: GPIO IRQ enable/disable bitfield - * @irq_rising_edge: GPIO IRQ rising edge enable/disable bitfield - * @irq_falling_edge: GPIO IRQ falling edge enable/disable bitfield + * @enable: GPIO IRQ enable/disable bitfield + * @rising_edge: GPIO IRQ rising edge enable/disable bitfield + * @falling_edge: GPIO IRQ falling edge enable/disable bitfield * @clk: clock resource for this driver */ struct xgpio_instance { struct gpio_chip gc; void __iomem *regs; - unsigned int gpio_width[2]; - u32 gpio_state[2]; - u32 gpio_last_irq_read[2]; - u32 gpio_dir[2]; + DECLARE_BITMAP(hw_map, 64); + DECLARE_BITMAP(sw_map, 64); + DECLARE_BITMAP(state, 64); + DECLARE_BITMAP(last_irq_read, 64); + DECLARE_BITMAP(dir, 64); spinlock_t gpio_lock; /* For serializing operations */ int irq; struct irq_chip irqchip; - u32 irq_enable[2]; - u32 irq_rising_edge[2]; - u32 irq_falling_edge[2]; + DECLARE_BITMAP(enable, 64); + DECLARE_BITMAP(rising_edge, 64); + DECLARE_BITMAP(falling_edge, 64); struct clk *clk; }; -static inline int xgpio_index(struct xgpio_instance *chip, int gpio) +static inline int xgpio_from_bit(struct xgpio_instance *chip, int bit) { - if (gpio >= chip->gpio_width[0]) - return 1; + return bitmap_bitremap(bit, chip->hw_map, chip->sw_map, 64); +} - return 0; +static inline int xgpio_to_bit(struct xgpio_instance *chip, int gpio) +{ + return bitmap_bitremap(gpio, chip->sw_map, chip->hw_map, 64); } -static inline int xgpio_regoffset(struct xgpio_instance *chip, int gpio) +static inline u32 xgpio_get_value32(const unsigned long *map, int bit) { - if (xgpio_index(chip, gpio)) - return XGPIO_CHANNEL_OFFSET; + const size_t index = BIT_WORD(bit); + const unsigned long offset = (bit % BITS_PER_LONG) & BIT(5); - return 0; + return (map[index] >> offset) & 0xFFFFFFFFul; +} + +static inline void xgpio_set_value32(unsigned long *map, int bit, u32 v) +{ + const size_t index = BIT_WORD(bit); + const unsigned long offset = (bit % BITS_PER_LONG) & BIT(5); + + map[index] &= ~(0xFFFFFFFFul << offset); + map[index] |= v << offset; +} + +static inline int xgpio_regoffset(struct xgpio_instance *chip, int ch) +{ + switch (ch) { + case 0: + return XGPIO_CHANNEL0_OFFSET; + case 1: + return XGPIO_CHANNEL1_OFFSET; + default: + return -EINVAL; + } } -static inline int xgpio_offset(struct xgpio_instance *chip, int gpio) +static void xgpio_read_ch(struct xgpio_instance *chip, int reg, int bit, unsigned long *a) { - if (xgpio_index(chip, gpio)) - return gpio - chip->gpio_width[0]; + void __iomem *addr = chip->regs + reg + xgpio_regoffset(chip, bit / 32); + xgpio_set_value32(a, bit, xgpio_readreg(addr)); +} + +static void xgpio_write_ch(struct xgpio_instance *chip, int reg, int bit, unsigned long *a) +{ + void __iomem *addr = chip->regs + reg + xgpio_regoffset(chip, bit / 32); + xgpio_writereg(addr, xgpio_get_value32(a, bit)); +} + +static void xgpio_read_ch_all(struct xgpio_instance *chip, int reg, unsigned long *a) +{ + int bit, lastbit = xgpio_to_bit(chip, chip->gc.ngpio - 1); + + for (bit = 0; bit <= lastbit ; bit += 32) + xgpio_read_ch(chip, reg, bit, a); +} + +static void xgpio_write_ch_all(struct xgpio_instance *chip, int reg, unsigned long *a) +{ + int bit, lastbit = xgpio_to_bit(chip, chip->gc.ngpio - 1); - return gpio; + for (bit = 0; bit <= lastbit ; bit += 32) + xgpio_write_ch(chip, reg, bit, a); } /** @@ -109,12 +156,12 @@ static inline int xgpio_offset(struct xgpio_instance *chip, int gpio) static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) { struct xgpio_instance *chip = gpiochip_get_data(gc); - u32 val; + int bit = xgpio_to_bit(chip, gpio); + DECLARE_BITMAP(state, 64); - val = xgpio_readreg(chip->regs + XGPIO_DATA_OFFSET + - xgpio_regoffset(chip, gpio)); + xgpio_read_ch(chip, XGPIO_DATA_OFFSET, bit, state); - return !!(val & BIT(xgpio_offset(chip, gpio))); + return test_bit(bit, state); } /** @@ -130,19 +177,14 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { unsigned long flags; struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, gpio); - int offset = xgpio_offset(chip, gpio); + int bit = xgpio_to_bit(chip, gpio); spin_lock_irqsave(&chip->gpio_lock, flags); /* Write to GPIO signal and set its direction to output */ - if (val) - chip->gpio_state[index] |= BIT(offset); - else - chip->gpio_state[index] &= ~BIT(offset); + __assign_bit(bit, chip->state, val); - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_state[index]); + xgpio_write_ch(chip, XGPIO_DATA_OFFSET, bit, chip->state); spin_unlock_irqrestore(&chip->gpio_lock, flags); } @@ -159,37 +201,22 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, unsigned long *bits) { + DECLARE_BITMAP(hw_mask, 64); + DECLARE_BITMAP(hw_bits, 64); + DECLARE_BITMAP(state, 64); unsigned long flags; struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, 0); - int offset, i; + + bitmap_remap(hw_mask, mask, chip->sw_map, chip->hw_map, 64); + bitmap_remap(hw_bits, bits, chip->sw_map, chip->hw_map, 64); spin_lock_irqsave(&chip->gpio_lock, flags); - /* Write to GPIO signals */ - for (i = 0; i < gc->ngpio; i++) { - if (*mask == 0) - break; - /* Once finished with an index write it out to the register */ - if (index != xgpio_index(chip, i)) { - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + - index * XGPIO_CHANNEL_OFFSET, - chip->gpio_state[index]); - spin_unlock_irqrestore(&chip->gpio_lock, flags); - index = xgpio_index(chip, i); - spin_lock_irqsave(&chip->gpio_lock, flags); - } - if (__test_and_clear_bit(i, mask)) { - offset = xgpio_offset(chip, i); - if (test_bit(i, bits)) - chip->gpio_state[index] |= BIT(offset); - else - chip->gpio_state[index] &= ~BIT(offset); - } - } + bitmap_replace(state, chip->state, hw_bits, hw_mask, 64); + + xgpio_write_ch_all(chip, XGPIO_DATA_OFFSET, state); - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + - index * XGPIO_CHANNEL_OFFSET, chip->gpio_state[index]); + bitmap_copy(chip->state, state, 64); spin_unlock_irqrestore(&chip->gpio_lock, flags); } @@ -207,15 +234,13 @@ static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) { unsigned long flags; struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, gpio); - int offset = xgpio_offset(chip, gpio); + int bit = xgpio_to_bit(chip, gpio); spin_lock_irqsave(&chip->gpio_lock, flags); /* Set the GPIO bit in shadow register and set direction as input */ - chip->gpio_dir[index] |= BIT(offset); - xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_dir[index]); + __set_bit(bit, chip->dir); + xgpio_write_ch(chip, XGPIO_TRI_OFFSET, bit, chip->dir); spin_unlock_irqrestore(&chip->gpio_lock, flags); @@ -238,23 +263,17 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { unsigned long flags; struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, gpio); - int offset = xgpio_offset(chip, gpio); + int bit = xgpio_to_bit(chip, gpio); spin_lock_irqsave(&chip->gpio_lock, flags); /* Write state of GPIO signal */ - if (val) - chip->gpio_state[index] |= BIT(offset); - else - chip->gpio_state[index] &= ~BIT(offset); - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_state[index]); + __assign_bit(bit, chip->state, val); + xgpio_write_ch(chip, XGPIO_DATA_OFFSET, bit, chip->state); /* Clear the GPIO bit in shadow register and set direction as output */ - chip->gpio_dir[index] &= ~BIT(offset); - xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_dir[index]); + __clear_bit(bit, chip->dir); + xgpio_write_ch(chip, XGPIO_TRI_OFFSET, bit, chip->dir); spin_unlock_irqrestore(&chip->gpio_lock, flags); @@ -267,16 +286,8 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) */ static void xgpio_save_regs(struct xgpio_instance *chip) { - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET, chip->gpio_state[0]); - xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET, chip->gpio_dir[0]); - - if (!chip->gpio_width[1]) - return; - - xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + XGPIO_CHANNEL_OFFSET, - chip->gpio_state[1]); - xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET + XGPIO_CHANNEL_OFFSET, - chip->gpio_dir[1]); + xgpio_write_ch_all(chip, XGPIO_DATA_OFFSET, chip->state); + xgpio_write_ch_all(chip, XGPIO_TRI_OFFSET, chip->dir); } static int xgpio_request(struct gpio_chip *chip, unsigned int offset) @@ -302,8 +313,8 @@ static int __maybe_unused xgpio_suspend(struct device *dev) struct irq_data *data = irq_get_irq_data(gpio->irq); if (!data) { - dev_err(dev, "irq_get_irq_data() failed\n"); - return -EINVAL; + dev_dbg(dev, "IRQ not connected\n"); + return pm_runtime_force_suspend(dev); } if (!irqd_is_wakeup_set(data)) @@ -348,8 +359,8 @@ static int __maybe_unused xgpio_resume(struct device *dev) struct irq_data *data = irq_get_irq_data(gpio->irq); if (!data) { - dev_err(dev, "irq_get_irq_data() failed\n"); - return -EINVAL; + dev_dbg(dev, "IRQ not connected\n"); + return pm_runtime_force_resume(dev); } if (!irqd_is_wakeup_set(data)) @@ -391,18 +402,17 @@ static void xgpio_irq_mask(struct irq_data *irq_data) unsigned long flags; struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data); int irq_offset = irqd_to_hwirq(irq_data); - int index = xgpio_index(chip, irq_offset); - int offset = xgpio_offset(chip, irq_offset); + int bit = xgpio_to_bit(chip, irq_offset); + u32 mask = BIT(bit / 32), temp; spin_lock_irqsave(&chip->gpio_lock, flags); - chip->irq_enable[index] &= ~BIT(offset); + __clear_bit(bit, chip->enable); - if (!chip->irq_enable[index]) { + if (xgpio_get_value32(chip->enable, bit) == 0) { /* Disable per channel interrupt */ - u32 temp = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET); - - temp &= ~BIT(index); + temp = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET); + temp &= ~mask; xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, temp); } spin_unlock_irqrestore(&chip->gpio_lock, flags); @@ -417,30 +427,26 @@ static void xgpio_irq_unmask(struct irq_data *irq_data) unsigned long flags; struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data); int irq_offset = irqd_to_hwirq(irq_data); - int index = xgpio_index(chip, irq_offset); - int offset = xgpio_offset(chip, irq_offset); - u32 old_enable = chip->irq_enable[index]; + int bit = xgpio_to_bit(chip, irq_offset); + u32 old_enable = xgpio_get_value32(chip->enable, bit); + u32 mask = BIT(bit / 32), val; spin_lock_irqsave(&chip->gpio_lock, flags); - chip->irq_enable[index] |= BIT(offset); + __set_bit(bit, chip->enable); - if (!old_enable) { + if (old_enable == 0) { /* Clear any existing per-channel interrupts */ - u32 val = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET) & - BIT(index); - - if (val) - xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, val); + val = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET); + val &= mask; + xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, val); /* Update GPIO IRQ read data before enabling interrupt*/ - val = xgpio_readreg(chip->regs + XGPIO_DATA_OFFSET + - index * XGPIO_CHANNEL_OFFSET); - chip->gpio_last_irq_read[index] = val; + xgpio_read_ch(chip, XGPIO_DATA_OFFSET, bit, chip->last_irq_read); /* Enable per channel interrupt */ val = xgpio_readreg(chip->regs + XGPIO_IPIER_OFFSET); - val |= BIT(index); + val |= mask; xgpio_writereg(chip->regs + XGPIO_IPIER_OFFSET, val); } @@ -459,8 +465,7 @@ static int xgpio_set_irq_type(struct irq_data *irq_data, unsigned int type) { struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data); int irq_offset = irqd_to_hwirq(irq_data); - int index = xgpio_index(chip, irq_offset); - int offset = xgpio_offset(chip, irq_offset); + int bit = xgpio_to_bit(chip, irq_offset); /* * The Xilinx GPIO hardware provides a single interrupt status @@ -470,16 +475,16 @@ static int xgpio_set_irq_type(struct irq_data *irq_data, unsigned int type) */ switch (type & IRQ_TYPE_SENSE_MASK) { case IRQ_TYPE_EDGE_BOTH: - chip->irq_rising_edge[index] |= BIT(offset); - chip->irq_falling_edge[index] |= BIT(offset); + __set_bit(bit, chip->rising_edge); + __set_bit(bit, chip->falling_edge); break; case IRQ_TYPE_EDGE_RISING: - chip->irq_rising_edge[index] |= BIT(offset); - chip->irq_falling_edge[index] &= ~BIT(offset); + __set_bit(bit, chip->rising_edge); + __clear_bit(bit, chip->falling_edge); break; case IRQ_TYPE_EDGE_FALLING: - chip->irq_rising_edge[index] &= ~BIT(offset); - chip->irq_falling_edge[index] |= BIT(offset); + __clear_bit(bit, chip->rising_edge); + __set_bit(bit, chip->falling_edge); break; default: return -EINVAL; @@ -496,46 +501,44 @@ static int xgpio_set_irq_type(struct irq_data *irq_data, unsigned int type) static void xgpio_irqhandler(struct irq_desc *desc) { struct xgpio_instance *chip = irq_desc_get_handler_data(desc); + struct gpio_chip *gc = &chip->gc; struct irq_chip *irqchip = irq_desc_get_chip(desc); - u32 num_channels = chip->gpio_width[1] ? 2 : 1; - u32 offset = 0, index; - u32 status = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET); - + DECLARE_BITMAP(rising, 64); + DECLARE_BITMAP(falling, 64); + DECLARE_BITMAP(all, 64); + int irq_offset; + u32 status; + u32 bit; + + status = xgpio_readreg(chip->regs + XGPIO_IPISR_OFFSET); xgpio_writereg(chip->regs + XGPIO_IPISR_OFFSET, status); chained_irq_enter(irqchip, desc); - for (index = 0; index < num_channels; index++) { - if ((status & BIT(index))) { - unsigned long rising_events, falling_events, all_events; - unsigned long flags; - u32 data, bit; - unsigned int irq; - - spin_lock_irqsave(&chip->gpio_lock, flags); - data = xgpio_readreg(chip->regs + XGPIO_DATA_OFFSET + - index * XGPIO_CHANNEL_OFFSET); - rising_events = data & - ~chip->gpio_last_irq_read[index] & - chip->irq_enable[index] & - chip->irq_rising_edge[index]; - falling_events = ~data & - chip->gpio_last_irq_read[index] & - chip->irq_enable[index] & - chip->irq_falling_edge[index]; - dev_dbg(chip->gc.parent, - "IRQ chan %u rising 0x%lx falling 0x%lx\n", - index, rising_events, falling_events); - all_events = rising_events | falling_events; - chip->gpio_last_irq_read[index] = data; - spin_unlock_irqrestore(&chip->gpio_lock, flags); - - for_each_set_bit(bit, &all_events, 32) { - irq = irq_find_mapping(chip->gc.irq.domain, - offset + bit); - generic_handle_irq(irq); - } - } - offset += chip->gpio_width[index]; + + spin_lock(&chip->gpio_lock); + + xgpio_read_ch_all(chip, XGPIO_DATA_OFFSET, all); + + bitmap_complement(rising, chip->last_irq_read, 64); + bitmap_and(rising, rising, all, 64); + bitmap_and(rising, rising, chip->enable, 64); + bitmap_and(rising, rising, chip->rising_edge, 64); + + bitmap_complement(falling, all, 64); + bitmap_and(falling, falling, chip->last_irq_read, 64); + bitmap_and(falling, falling, chip->enable, 64); + bitmap_and(falling, falling, chip->falling_edge, 64); + + bitmap_copy(chip->last_irq_read, all, 64); + bitmap_or(all, rising, falling, 64); + + spin_unlock(&chip->gpio_lock); + + dev_dbg(gc->parent, "IRQ rising %*pb falling %*pb\n", 64, rising, 64, falling); + + for_each_set_bit(bit, all, 64) { + irq_offset = xgpio_from_bit(chip, bit); + generic_handle_irq(irq_find_mapping(gc->irq.domain, irq_offset)); } chained_irq_exit(irqchip, desc); @@ -556,6 +559,9 @@ static int xgpio_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; u32 is_dual = 0; u32 cells = 2; + u32 width[2]; + u32 state[2]; + u32 dir[2]; struct gpio_irq_chip *girq; u32 temp; @@ -565,13 +571,25 @@ static int xgpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, chip); + /* First, check if the device is dual-channel */ + of_property_read_u32(np, "xlnx,is-dual", &is_dual); + + /* Setup defaults */ + memset32(width, 0, ARRAY_SIZE(width)); + memset32(state, 0, ARRAY_SIZE(state)); + memset32(dir, 0xFFFFFFFF, ARRAY_SIZE(dir)); + /* Update GPIO state shadow register with default value */ - if (of_property_read_u32(np, "xlnx,dout-default", &chip->gpio_state[0])) - chip->gpio_state[0] = 0x0; + of_property_read_u32(np, "xlnx,dout-default", &state[0]); + of_property_read_u32(np, "xlnx,dout-default-2", &state[1]); + + bitmap_from_arr32(chip->state, state, 64); /* Update GPIO direction shadow register with default value */ - if (of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir[0])) - chip->gpio_dir[0] = 0xFFFFFFFF; + of_property_read_u32(np, "xlnx,tri-default", &dir[0]); + of_property_read_u32(np, "xlnx,tri-default-2", &dir[1]); + + bitmap_from_arr32(chip->dir, dir, 64); /* Update cells with gpio-cells value */ if (of_property_read_u32(np, "#gpio-cells", &cells)) @@ -586,42 +604,29 @@ static int xgpio_probe(struct platform_device *pdev) * Check device node and parent device node for device width * and assume default width of 32 */ - if (of_property_read_u32(np, "xlnx,gpio-width", &chip->gpio_width[0])) - chip->gpio_width[0] = 32; + if (of_property_read_u32(np, "xlnx,gpio-width", &width[0])) + width[0] = 32; - if (chip->gpio_width[0] > 32) + if (width[0] > 32) return -EINVAL; - spin_lock_init(&chip->gpio_lock); + if (is_dual && of_property_read_u32(np, "xlnx,gpio2-width", &width[1])) + width[1] = 32; - if (of_property_read_u32(np, "xlnx,is-dual", &is_dual)) - is_dual = 0; - - if (is_dual) { - /* Update GPIO state shadow register with default value */ - if (of_property_read_u32(np, "xlnx,dout-default-2", - &chip->gpio_state[1])) - chip->gpio_state[1] = 0x0; - - /* Update GPIO direction shadow register with default value */ - if (of_property_read_u32(np, "xlnx,tri-default-2", - &chip->gpio_dir[1])) - chip->gpio_dir[1] = 0xFFFFFFFF; - - /* - * Check device node and parent device node for device width - * and assume default width of 32 - */ - if (of_property_read_u32(np, "xlnx,gpio2-width", - &chip->gpio_width[1])) - chip->gpio_width[1] = 32; - - if (chip->gpio_width[1] > 32) - return -EINVAL; - } + if (width[1] > 32) + return -EINVAL; + + /* Setup software pin mapping */ + bitmap_set(chip->sw_map, 0, width[0] + width[1]); + + /* Setup hardware pin mapping */ + bitmap_set(chip->hw_map, 0, width[0]); + bitmap_set(chip->hw_map, 32, width[1]); + + spin_lock_init(&chip->gpio_lock); chip->gc.base = -1; - chip->gc.ngpio = chip->gpio_width[0] + chip->gpio_width[1]; + chip->gc.ngpio = bitmap_weight(chip->hw_map, 64); chip->gc.parent = &pdev->dev; chip->gc.direction_input = xgpio_dir_in; chip->gc.direction_output = xgpio_dir_out; diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 3521c1dc3ac0..f0cb8ccd03ed 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -736,6 +736,11 @@ static int __maybe_unused zynq_gpio_suspend(struct device *dev) struct zynq_gpio *gpio = dev_get_drvdata(dev); struct irq_data *data = irq_get_irq_data(gpio->irq); + if (!data) { + dev_err(dev, "irq_get_irq_data() failed\n"); + return -EINVAL; + } + if (!device_may_wakeup(dev)) disable_irq(gpio->irq); @@ -753,6 +758,11 @@ static int __maybe_unused zynq_gpio_resume(struct device *dev) struct irq_data *data = irq_get_irq_data(gpio->irq); int ret; + if (!data) { + dev_err(dev, "irq_get_irq_data() failed\n"); + return -EINVAL; + } + if (!device_may_wakeup(dev)) enable_irq(gpio->irq); @@ -1001,8 +1011,11 @@ err_pm_dis: static int zynq_gpio_remove(struct platform_device *pdev) { struct zynq_gpio *gpio = platform_get_drvdata(pdev); + int ret; - pm_runtime_get_sync(&pdev->dev); + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) + dev_warn(&pdev->dev, "pm_runtime_get_sync() Failed\n"); gpiochip_remove(&gpio->chip); clk_disable_unprepare(gpio->clk); device_set_wakeup_capable(&pdev->dev, 0); @@ -1020,22 +1033,7 @@ static struct platform_driver zynq_gpio_driver = { .remove = zynq_gpio_remove, }; -/** - * zynq_gpio_init - Initial driver registration call - * - * Return: value from platform_driver_register - */ -static int __init zynq_gpio_init(void) -{ - return platform_driver_register(&zynq_gpio_driver); -} -postcore_initcall(zynq_gpio_init); - -static void __exit zynq_gpio_exit(void) -{ - platform_driver_unregister(&zynq_gpio_driver); -} -module_exit(zynq_gpio_exit); +module_platform_driver(zynq_gpio_driver); MODULE_AUTHOR("Xilinx Inc."); MODULE_DESCRIPTION("Zynq GPIO driver"); diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index ae49bb23c6ed..4098bc7f88b7 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -66,9 +66,8 @@ static ssize_t direction_show(struct device *dev, mutex_lock(&data->mutex); gpiod_get_direction(desc); - status = sprintf(buf, "%s\n", - test_bit(FLAG_IS_OUT, &desc->flags) - ? "out" : "in"); + status = sysfs_emit(buf, "%s\n", + test_bit(FLAG_IS_OUT, &desc->flags) ? "out" : "in"); mutex_unlock(&data->mutex); @@ -109,13 +108,9 @@ static ssize_t value_show(struct device *dev, mutex_lock(&data->mutex); status = gpiod_get_value_cansleep(desc); - if (status < 0) - goto err; + if (status >= 0) + status = sysfs_emit(buf, "%zd\n", status); - buf[0] = '0' + status; - buf[1] = '\n'; - status = 2; -err: mutex_unlock(&data->mutex); return status; @@ -249,11 +244,11 @@ static ssize_t edge_show(struct device *dev, mutex_lock(&data->mutex); for (i = 0; i < ARRAY_SIZE(trigger_types); i++) { - if (data->irq_flags == trigger_types[i].flags) { - status = sprintf(buf, "%s\n", trigger_types[i].name); + if (data->irq_flags == trigger_types[i].flags) break; - } } + if (i < ARRAY_SIZE(trigger_types)) + status = sysfs_emit(buf, "%s\n", trigger_types[i].name); mutex_unlock(&data->mutex); @@ -312,10 +307,7 @@ static int gpio_sysfs_set_active_low(struct device *dev, int value) if (!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) == !!value) return 0; - if (value) - set_bit(FLAG_ACTIVE_LOW, &desc->flags); - else - clear_bit(FLAG_ACTIVE_LOW, &desc->flags); + assign_bit(FLAG_ACTIVE_LOW, &desc->flags, value); /* reconfigure poll(2) support if enabled on one edge only */ if (flags == GPIO_IRQF_TRIGGER_FALLING || @@ -336,8 +328,8 @@ static ssize_t active_low_show(struct device *dev, mutex_lock(&data->mutex); - status = sprintf(buf, "%d\n", - !!test_bit(FLAG_ACTIVE_LOW, &desc->flags)); + status = sysfs_emit(buf, "%d\n", + !!test_bit(FLAG_ACTIVE_LOW, &desc->flags)); mutex_unlock(&data->mutex); @@ -415,7 +407,7 @@ static ssize_t base_show(struct device *dev, { const struct gpio_chip *chip = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", chip->base); + return sysfs_emit(buf, "%d\n", chip->base); } static DEVICE_ATTR_RO(base); @@ -424,7 +416,7 @@ static ssize_t label_show(struct device *dev, { const struct gpio_chip *chip = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", chip->label ? : ""); + return sysfs_emit(buf, "%s\n", chip->label ?: ""); } static DEVICE_ATTR_RO(label); @@ -433,7 +425,7 @@ static ssize_t ngpio_show(struct device *dev, { const struct gpio_chip *chip = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", chip->ngpio); + return sysfs_emit(buf, "%u\n", chip->ngpio); } static DEVICE_ATTR_RO(ngpio); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 1427c1be749b..27c07108496d 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2004,9 +2004,6 @@ const char *gpiochip_is_requested(struct gpio_chip *gc, unsigned int offset) { struct gpio_desc *desc; - if (offset >= gc->ngpio) - return NULL; - desc = gpiochip_get_desc(gc, offset); if (IS_ERR(desc)) return NULL; @@ -2543,21 +2540,28 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, while (i < array_size) { struct gpio_chip *gc = desc_array[i]->gdev->chip; - unsigned long fastpath[2 * BITS_TO_LONGS(FASTPATH_NGPIO)]; + DECLARE_BITMAP(fastpath_mask, FASTPATH_NGPIO); + DECLARE_BITMAP(fastpath_bits, FASTPATH_NGPIO); unsigned long *mask, *bits; int first, j; if (likely(gc->ngpio <= FASTPATH_NGPIO)) { - mask = fastpath; + mask = fastpath_mask; + bits = fastpath_bits; } else { - mask = kmalloc_array(2 * BITS_TO_LONGS(gc->ngpio), - sizeof(*mask), - can_sleep ? GFP_KERNEL : GFP_ATOMIC); + gfp_t flags = can_sleep ? GFP_KERNEL : GFP_ATOMIC; + + mask = bitmap_alloc(gc->ngpio, flags); if (!mask) return -ENOMEM; + + bits = bitmap_alloc(gc->ngpio, flags); + if (!bits) { + bitmap_free(mask); + return -ENOMEM; + } } - bits = mask + BITS_TO_LONGS(gc->ngpio); bitmap_zero(mask, gc->ngpio); if (!can_sleep) @@ -2580,8 +2584,10 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, ret = gpio_chip_get_multiple(gc, mask, bits); if (ret) { - if (mask != fastpath) - kfree(mask); + if (mask != fastpath_mask) + bitmap_free(mask); + if (bits != fastpath_bits) + bitmap_free(bits); return ret; } @@ -2601,8 +2607,10 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, j); } - if (mask != fastpath) - kfree(mask); + if (mask != fastpath_mask) + bitmap_free(mask); + if (bits != fastpath_bits) + bitmap_free(bits); } return 0; } @@ -2826,21 +2834,28 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, while (i < array_size) { struct gpio_chip *gc = desc_array[i]->gdev->chip; - unsigned long fastpath[2 * BITS_TO_LONGS(FASTPATH_NGPIO)]; + DECLARE_BITMAP(fastpath_mask, FASTPATH_NGPIO); + DECLARE_BITMAP(fastpath_bits, FASTPATH_NGPIO); unsigned long *mask, *bits; int count = 0; if (likely(gc->ngpio <= FASTPATH_NGPIO)) { - mask = fastpath; + mask = fastpath_mask; + bits = fastpath_bits; } else { - mask = kmalloc_array(2 * BITS_TO_LONGS(gc->ngpio), - sizeof(*mask), - can_sleep ? GFP_KERNEL : GFP_ATOMIC); + gfp_t flags = can_sleep ? GFP_KERNEL : GFP_ATOMIC; + + mask = bitmap_alloc(gc->ngpio, flags); if (!mask) return -ENOMEM; + + bits = bitmap_alloc(gc->ngpio, flags); + if (!bits) { + bitmap_free(mask); + return -ENOMEM; + } } - bits = mask + BITS_TO_LONGS(gc->ngpio); bitmap_zero(mask, gc->ngpio); if (!can_sleep) @@ -2885,8 +2900,10 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, if (count != 0) gpio_chip_set_multiple(gc, mask, bits); - if (mask != fastpath) - kfree(mask); + if (mask != fastpath_mask) + bitmap_free(mask); + if (bits != fastpath_bits) + bitmap_free(bits); } return 0; } |