From a72b8c4a63e2a3375b5d3af4a2b70c172570c354 Mon Sep 17 00:00:00 2001 From: Hoan Tran Date: Tue, 21 Feb 2017 11:32:43 -0800 Subject: [PATCH 01/77] gpio: dwapb: Add support for next generation of X-Gene SoC Next generation of X-Gene SoC's GPIO hardware register map is very similar to DW GPIO. It only differs by a few register addresses. This patch modifies DW GPIO driver to accommodate the difference in a few register addresses. Signed-off-by: Hoan Tran Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-dwapb.c | 91 +++++++++++++++++++++++++++++++-------- 1 file changed, 74 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 9c15ee4ef4e9..53ade0b69f49 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,14 @@ #define GPIO_SWPORT_DR_SIZE (GPIO_SWPORTB_DR - GPIO_SWPORTA_DR) #define GPIO_SWPORT_DDR_SIZE (GPIO_SWPORTB_DDR - GPIO_SWPORTA_DDR) +#define GPIO_REG_OFFSET_V2 1 + +#define GPIO_INTMASK_V2 0x44 +#define GPIO_INTTYPE_LEVEL_V2 0x34 +#define GPIO_INT_POLARITY_V2 0x38 +#define GPIO_INTSTATUS_V2 0x3c +#define GPIO_PORTA_EOI_V2 0x40 + struct dwapb_gpio; #ifdef CONFIG_PM_SLEEP @@ -87,14 +96,41 @@ struct dwapb_gpio { struct dwapb_gpio_port *ports; unsigned int nr_ports; struct irq_domain *domain; + unsigned int flags; }; +static inline u32 gpio_reg_v2_convert(unsigned int offset) +{ + switch (offset) { + case GPIO_INTMASK: + return GPIO_INTMASK_V2; + case GPIO_INTTYPE_LEVEL: + return GPIO_INTTYPE_LEVEL_V2; + case GPIO_INT_POLARITY: + return GPIO_INT_POLARITY_V2; + case GPIO_INTSTATUS: + return GPIO_INTSTATUS_V2; + case GPIO_PORTA_EOI: + return GPIO_PORTA_EOI_V2; + } + + return offset; +} + +static inline u32 gpio_reg_convert(struct dwapb_gpio *gpio, unsigned int offset) +{ + if (gpio->flags & GPIO_REG_OFFSET_V2) + return gpio_reg_v2_convert(offset); + + return offset; +} + static inline u32 dwapb_read(struct dwapb_gpio *gpio, unsigned int offset) { struct gpio_chip *gc = &gpio->ports[0].gc; void __iomem *reg_base = gpio->regs; - return gc->read_reg(reg_base + offset); + return gc->read_reg(reg_base + gpio_reg_convert(gpio, offset)); } static inline void dwapb_write(struct dwapb_gpio *gpio, unsigned int offset, @@ -103,7 +139,7 @@ static inline void dwapb_write(struct dwapb_gpio *gpio, unsigned int offset, struct gpio_chip *gc = &gpio->ports[0].gc; void __iomem *reg_base = gpio->regs; - gc->write_reg(reg_base + offset, val); + gc->write_reg(reg_base + gpio_reg_convert(gpio, offset), val); } static int dwapb_gpio_to_irq(struct gpio_chip *gc, unsigned offset) @@ -348,8 +384,8 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio, ct->chip.irq_disable = dwapb_irq_disable; ct->chip.irq_request_resources = dwapb_irq_reqres; ct->chip.irq_release_resources = dwapb_irq_relres; - ct->regs.ack = GPIO_PORTA_EOI; - ct->regs.mask = GPIO_INTMASK; + ct->regs.ack = gpio_reg_convert(gpio, GPIO_PORTA_EOI); + ct->regs.mask = gpio_reg_convert(gpio, GPIO_INTMASK); ct->type = IRQ_TYPE_LEVEL_MASK; } @@ -532,6 +568,21 @@ dwapb_gpio_get_pdata(struct device *dev) return pdata; } +static const struct of_device_id dwapb_of_match[] = { + { .compatible = "snps,dw-apb-gpio", .data = (void *)0}, + { .compatible = "apm,xgene-gpio-v2", .data = (void *)GPIO_REG_OFFSET_V2}, + { /* Sentinel */ } +}; +MODULE_DEVICE_TABLE(of, dwapb_of_match); + +static const struct acpi_device_id dwapb_acpi_match[] = { + {"HISI0181", 0}, + {"APMC0D07", 0}, + {"APMC0D81", GPIO_REG_OFFSET_V2}, + { } +}; +MODULE_DEVICE_TABLE(acpi, dwapb_acpi_match); + static int dwapb_gpio_probe(struct platform_device *pdev) { unsigned int i; @@ -567,6 +618,25 @@ static int dwapb_gpio_probe(struct platform_device *pdev) if (IS_ERR(gpio->regs)) return PTR_ERR(gpio->regs); + gpio->flags = 0; + if (dev->of_node) { + const struct of_device_id *of_devid; + + of_devid = of_match_device(dwapb_of_match, dev); + if (of_devid) { + if (of_devid->data) + gpio->flags = (uintptr_t)of_devid->data; + } + } else if (has_acpi_companion(dev)) { + const struct acpi_device_id *acpi_id; + + acpi_id = acpi_match_device(dwapb_acpi_match, dev); + if (acpi_id) { + if (acpi_id->driver_data) + gpio->flags = acpi_id->driver_data; + } + } + for (i = 0; i < gpio->nr_ports; i++) { err = dwapb_gpio_add_port(gpio, &pdata->properties[i], i); if (err) @@ -593,19 +663,6 @@ static int dwapb_gpio_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id dwapb_of_match[] = { - { .compatible = "snps,dw-apb-gpio" }, - { /* Sentinel */ } -}; -MODULE_DEVICE_TABLE(of, dwapb_of_match); - -static const struct acpi_device_id dwapb_acpi_match[] = { - {"HISI0181", 0}, - {"APMC0D07", 0}, - { } -}; -MODULE_DEVICE_TABLE(acpi, dwapb_acpi_match); - #ifdef CONFIG_PM_SLEEP static int dwapb_gpio_suspend(struct device *dev) { From ff21378a321f05e8c11265a3bd7622b89df8032e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 28 Feb 2017 17:03:12 +0200 Subject: [PATCH 02/77] gpiolib: Fix spelling of 'successful' Remove extra 'l' in "successfull". Signed-off-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/devres.c | 2 +- drivers/gpio/gpiolib.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c index 7031eea165c9..a75511d1ea5d 100644 --- a/drivers/gpio/devres.c +++ b/drivers/gpio/devres.c @@ -136,7 +136,7 @@ EXPORT_SYMBOL(devm_gpiod_get_index); * GPIO descriptors returned from this function are automatically disposed on * driver detach. * - * On successfull request the GPIO pin is configured in accordance with + * On successful request the GPIO pin is configured in accordance with * provided @flags. */ struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev, diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 8b4d721d6d63..530b1ba984a4 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3326,7 +3326,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_index); * underlying firmware interface and then makes sure that the GPIO * descriptor is requested before it is returned to the caller. * - * On successfull request the GPIO pin is configured in accordance with + * On successful request the GPIO pin is configured in accordance with * provided @dflags. * * In case of error an ERR_PTR() is returned. From 85c73d50e57eb8ad43955fe38714bc5fba1acd92 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 2 Mar 2017 15:48:05 +0200 Subject: [PATCH 03/77] gpio: acpi: Add managed variant of acpi_dev_add_driver_gpios() Introduce device managed variant of acpi_dev_add_driver_gpios() and its counterpart acpi_dev_remove_driver_gpios(). The functions in most cases are used in driver's ->probe() and ->remove() callbacks, that's why it's useful to have managed variant of them. Signed-off-by: Andy Shevchenko Acked-by: Rafael J. Wysocki Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 31 +++++++++++++++++++++++++++++++ include/linux/acpi.h | 11 +++++++++++ 2 files changed, 42 insertions(+) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 9b37a3692b3f..108331de440b 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -362,6 +362,37 @@ int acpi_dev_add_driver_gpios(struct acpi_device *adev, } EXPORT_SYMBOL_GPL(acpi_dev_add_driver_gpios); +static void devm_acpi_dev_release_driver_gpios(struct device *dev, void *res) +{ + acpi_dev_remove_driver_gpios(ACPI_COMPANION(dev)); +} + +int devm_acpi_dev_add_driver_gpios(struct device *dev, + const struct acpi_gpio_mapping *gpios) +{ + void *res; + int ret; + + res = devres_alloc(devm_acpi_dev_release_driver_gpios, 0, GFP_KERNEL); + if (!res) + return -ENOMEM; + + ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev), gpios); + if (ret) { + devres_free(res); + return ret; + } + devres_add(dev, res); + return 0; +} +EXPORT_SYMBOL_GPL(devm_acpi_dev_add_driver_gpios); + +void devm_acpi_dev_remove_driver_gpios(struct device *dev) +{ + WARN_ON(devres_release(dev, devm_acpi_dev_release_driver_gpios, NULL, NULL)); +} +EXPORT_SYMBOL_GPL(devm_acpi_dev_remove_driver_gpios); + static bool acpi_get_driver_gpio_data(struct acpi_device *adev, const char *name, int index, struct acpi_reference_args *args) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 673acda012af..c8eaaad4a9ed 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -952,6 +952,10 @@ static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev) adev->driver_gpios = NULL; } +int devm_acpi_dev_add_driver_gpios(struct device *dev, + const struct acpi_gpio_mapping *gpios); +void devm_acpi_dev_remove_driver_gpios(struct device *dev); + int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index); #else static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev, @@ -961,6 +965,13 @@ static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev, } static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev) {} +static inline int devm_acpi_dev_add_driver_gpios(struct device *dev, + const struct acpi_gpio_mapping *gpios) +{ + return -ENXIO; +} +static inline void devm_acpi_dev_remove_driver_gpios(struct device *dev) {} + static inline int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index) { return -ENXIO; From 22c403676dbbb7c6f186099527af7f065498ef45 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 12 Feb 2017 17:13:55 -0800 Subject: [PATCH 04/77] gpio: return NULL from gpiod_get_optional when GPIOLIB is disabled Given the intent behind gpiod_get_optional() and friends it does not make sense to return -ENOSYS when GPIOLIB is disabled: the driver is expected to work just fine without gpio so let's behave as if gpio was not found. Otherwise we have to special-case -ENOSYS in drivers. Note that there was objection that someone might forget to enable GPIOLIB when dealing with a platform that has device that actually specifies optional gpio and we'll break it. I find this unconvincing as that would have to be the *only GPIO* in the system, which is extremely unlikely. Signed-off-by: Dmitry Torokhov Signed-off-by: Linus Walleij --- Documentation/gpio/consumer.txt | 6 ++++++ include/linux/gpio/consumer.h | 12 ++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Documentation/gpio/consumer.txt b/Documentation/gpio/consumer.txt index 05676fdacfe3..912568baabb9 100644 --- a/Documentation/gpio/consumer.txt +++ b/Documentation/gpio/consumer.txt @@ -70,6 +70,12 @@ instead of -ENOENT if no GPIO has been assigned to the requested function: unsigned int index, enum gpiod_flags flags) +Note that gpio_get*_optional() functions (and their managed variants), unlike +the rest of gpiolib API, also return NULL when gpiolib support is disabled. +This is helpful to driver authors, since they do not need to special case +-ENOSYS return codes. System integrators should however be careful to enable +gpiolib on systems that need it. + For a function using multiple GPIOs all of those can be obtained with one call: struct gpio_descs *gpiod_get_array(struct device *dev, diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 2484b2fcc6eb..13daf08e25bb 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -179,14 +179,14 @@ static inline struct gpio_desc *__must_check gpiod_get_optional(struct device *dev, const char *con_id, enum gpiod_flags flags) { - return ERR_PTR(-ENOSYS); + return NULL; } static inline struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev, const char *con_id, unsigned int index, enum gpiod_flags flags) { - return ERR_PTR(-ENOSYS); + return NULL; } static inline struct gpio_descs *__must_check @@ -200,7 +200,7 @@ static inline struct gpio_descs *__must_check gpiod_get_array_optional(struct device *dev, const char *con_id, enum gpiod_flags flags) { - return ERR_PTR(-ENOSYS); + return NULL; } static inline void gpiod_put(struct gpio_desc *desc) @@ -240,14 +240,14 @@ static inline struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev, const char *con_id, enum gpiod_flags flags) { - return ERR_PTR(-ENOSYS); + return NULL; } static inline struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev, const char *con_id, unsigned int index, enum gpiod_flags flags) { - return ERR_PTR(-ENOSYS); + return NULL; } static inline struct gpio_descs *__must_check @@ -261,7 +261,7 @@ static inline struct gpio_descs *__must_check devm_gpiod_get_array_optional(struct device *dev, const char *con_id, enum gpiod_flags flags) { - return ERR_PTR(-ENOSYS); + return NULL; } static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc) From eddeae073760aa3186e2fa0d14a12794687fa786 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 26 Feb 2017 22:36:58 +0800 Subject: [PATCH 05/77] gpio: exar: Set proper output level in exar_direction_output Current code does not set output level in exar_direction_output, fix it. Also move the direction_output/direction_input code block to avoid forward declaration for exar_set_value(). Signed-off-by: Axel Lin Signed-off-by: Linus Walleij --- drivers/gpio/gpio-exar.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c index 05c8946d6446..081076771217 100644 --- a/drivers/gpio/gpio-exar.c +++ b/drivers/gpio/gpio-exar.c @@ -59,17 +59,6 @@ static int exar_set_direction(struct gpio_chip *chip, int direction, return 0; } -static int exar_direction_output(struct gpio_chip *chip, unsigned int offset, - int value) -{ - return exar_set_direction(chip, 0, offset); -} - -static int exar_direction_input(struct gpio_chip *chip, unsigned int offset) -{ - return exar_set_direction(chip, 1, offset); -} - static int exar_get(struct gpio_chip *chip, unsigned int reg) { struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip); @@ -116,6 +105,18 @@ static void exar_set_value(struct gpio_chip *chip, unsigned int offset, exar_update(chip, addr, value, offset % 8); } +static int exar_direction_output(struct gpio_chip *chip, unsigned int offset, + int value) +{ + exar_set_value(chip, offset, value); + return exar_set_direction(chip, 0, offset); +} + +static int exar_direction_input(struct gpio_chip *chip, unsigned int offset) +{ + return exar_set_direction(chip, 1, offset); +} + static int gpio_exar_probe(struct platform_device *pdev) { struct pci_dev *pcidev = platform_get_drvdata(pdev); From f73b15487acecb52bc028cee7df4fc0d0871fcc8 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 28 Feb 2017 17:48:50 -0800 Subject: [PATCH 06/77] dt-bindings: gpio: Add binding documentation for gpio-thunderx Signed-off-by: David Daney Acked-by: Rob Herring Signed-off-by: Linus Walleij --- .../bindings/gpio/gpio-thunderx.txt | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/gpio-thunderx.txt diff --git a/Documentation/devicetree/bindings/gpio/gpio-thunderx.txt b/Documentation/devicetree/bindings/gpio/gpio-thunderx.txt new file mode 100644 index 000000000000..3f883ae29d11 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-thunderx.txt @@ -0,0 +1,27 @@ +Cavium ThunderX/OCTEON-TX GPIO controller bindings + +Required Properties: +- reg: The controller bus address. +- gpio-controller: Marks the device node as a GPIO controller. +- #gpio-cells: Must be 2. + - First cell is the GPIO pin number relative to the controller. + - Second cell is a standard generic flag bitfield as described in gpio.txt. + +Optional Properties: +- compatible: "cavium,thunder-8890-gpio", unused as PCI driver binding is used. +- interrupt-controller: Marks the device node as an interrupt controller. +- #interrupt-cells: Must be present and have value of 2 if + "interrupt-controller" is present. + - First cell is the GPIO pin number relative to the controller. + - Second cell is triggering flags as defined in interrupts.txt. + +Example: + +gpio_6_0: gpio@6,0 { + compatible = "cavium,thunder-8890-gpio"; + reg = <0x3000 0 0 0 0>; /* DEVFN = 0x30 (6:0) */ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; +}; From 62a7ca0735f47e5799a892daab39be3c67979de9 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Sat, 4 Mar 2017 17:23:29 +0100 Subject: [PATCH 07/77] gpio: mockup: use devm_irq_alloc_descs() Use the resource managed variant of irq_alloc_descs(). This allows us to remove gpio_mockup_remove(). Signed-off-by: Bartosz Golaszewski Reviewed-by: Bamvor Jian Zhang Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mockup.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index 06dac72cb69c..37c2d694687e 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -169,7 +169,7 @@ static int gpio_mockup_irqchip_setup(struct device *dev, struct gpio_chip *gc = &chip->gc; int irq_base, i; - irq_base = irq_alloc_descs(-1, 0, gc->ngpio, 0); + irq_base = devm_irq_alloc_descs(dev, -1, 0, gc->ngpio, 0); if (irq_base < 0) return irq_base; @@ -373,25 +373,11 @@ static int gpio_mockup_probe(struct platform_device *pdev) return 0; } -static int gpio_mockup_remove(struct platform_device *pdev) -{ - struct gpio_mockup_chip *chips; - int i; - - chips = platform_get_drvdata(pdev); - - for (i = 0; i < gpio_mockup_params_nr >> 1; i++) - irq_free_descs(chips[i].gc.irq_base, chips[i].gc.ngpio); - - return 0; -} - static struct platform_driver gpio_mockup_driver = { .driver = { .name = GPIO_MOCKUP_NAME, }, .probe = gpio_mockup_probe, - .remove = gpio_mockup_remove, }; static struct platform_device *pdev; From 9bc81137e8082eaa73f1b116e1df2c75673d64df Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Sat, 4 Mar 2017 17:23:30 +0100 Subject: [PATCH 08/77] gpio: twl4030: use devm_irq_alloc_descs() This driver never frees the irq descriptors it allocates. Fix it by using a resource managed variant of irq_alloc_descs(). Signed-off-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-twl4030.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c index dfcfbba74416..24f388ed46d4 100644 --- a/drivers/gpio/gpio-twl4030.c +++ b/drivers/gpio/gpio-twl4030.c @@ -485,7 +485,8 @@ static int gpio_twl4030_probe(struct platform_device *pdev) goto no_irqs; } - irq_base = irq_alloc_descs(-1, 0, TWL4030_GPIO_MAX, 0); + irq_base = devm_irq_alloc_descs(&pdev->dev, -1, + 0, TWL4030_GPIO_MAX, 0); if (irq_base < 0) { dev_err(&pdev->dev, "Failed to alloc irq_descs\n"); return irq_base; From 2ed36f30139f773e3c99eeca2307b7a6596f4b90 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Sat, 4 Mar 2017 17:23:31 +0100 Subject: [PATCH 09/77] gpio: omap: use devm_irq_alloc_descs() This driver never frees the allocated interrupt descriptors. Fix it by using a resource managed variant of irq_alloc_descs(). Signed-off-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index efc85a279d54..5d6a5744352f 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1085,7 +1085,8 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) * REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop * irq_alloc_descs() since a base IRQ offset will no longer be needed. */ - irq_base = irq_alloc_descs(-1, 0, bank->width, 0); + irq_base = devm_irq_alloc_descs(bank->chip.parent, + -1, 0, bank->width, 0); if (irq_base < 0) { dev_err(bank->chip.parent, "Couldn't allocate IRQ numbers\n"); return -ENODEV; From f57f3e60038358a903d5d867f9cb688e1e8d9142 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Sat, 4 Mar 2017 17:23:32 +0100 Subject: [PATCH 10/77] gpio: pch: use resource management for irqs Use device resource managed variants of irq_alloc_descs() and request_irq() and remove the code manually freeing irq resources. Signed-off-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pch.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index 7c7135da5d4a..71bc6da11337 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -403,7 +403,8 @@ static int pch_gpio_probe(struct pci_dev *pdev, goto err_gpiochip_add; } - irq_base = irq_alloc_descs(-1, 0, gpio_pins[chip->ioh], NUMA_NO_NODE); + irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, + gpio_pins[chip->ioh], NUMA_NO_NODE); if (irq_base < 0) { dev_warn(&pdev->dev, "PCH gpio: Failed to get IRQ base num\n"); chip->irq_base = -1; @@ -416,8 +417,8 @@ static int pch_gpio_probe(struct pci_dev *pdev, iowrite32(msk, &chip->reg->imask); iowrite32(msk, &chip->reg->ien); - ret = request_irq(pdev->irq, pch_gpio_handler, - IRQF_SHARED, KBUILD_MODNAME, chip); + ret = devm_request_irq(&pdev->dev, pdev->irq, pch_gpio_handler, + IRQF_SHARED, KBUILD_MODNAME, chip); if (ret != 0) { dev_err(&pdev->dev, "%s request_irq failed\n", __func__); @@ -430,7 +431,6 @@ end: return 0; err_request_irq: - irq_free_descs(irq_base, gpio_pins[chip->ioh]); gpiochip_remove(&chip->gpio); err_gpiochip_add: @@ -452,12 +452,6 @@ static void pch_gpio_remove(struct pci_dev *pdev) { struct pch_gpio *chip = pci_get_drvdata(pdev); - if (chip->irq_base != -1) { - free_irq(pdev->irq, chip); - - irq_free_descs(chip->irq_base, gpio_pins[chip->ioh]); - } - gpiochip_remove(&chip->gpio); pci_iounmap(pdev, chip->base); pci_release_regions(pdev); From e971ac9a564a4f3fbaeaae111079837928226870 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Sat, 4 Mar 2017 17:23:33 +0100 Subject: [PATCH 11/77] gpio: ml-ioh: use resource management for irqs Use device resource managed variants of irq_alloc_descs() and request_irq() and remove the code manually freeing irq resources. Signed-off-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ml-ioh.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index 796a5a4bc4f5..78896a869fd9 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -459,41 +459,31 @@ static int ioh_gpio_probe(struct pci_dev *pdev, chip = chip_save; for (j = 0; j < 8; j++, chip++) { - irq_base = irq_alloc_descs(-1, IOH_IRQ_BASE, num_ports[j], - NUMA_NO_NODE); + irq_base = devm_irq_alloc_descs(&pdev->dev, -1, IOH_IRQ_BASE, + num_ports[j], NUMA_NO_NODE); if (irq_base < 0) { dev_warn(&pdev->dev, "ml_ioh_gpio: Failed to get IRQ base num\n"); - chip->irq_base = -1; ret = irq_base; - goto err_irq_alloc_descs; + goto err_gpiochip_add; } chip->irq_base = irq_base; ioh_gpio_alloc_generic_chip(chip, irq_base, num_ports[j]); } chip = chip_save; - ret = request_irq(pdev->irq, ioh_gpio_handler, - IRQF_SHARED, KBUILD_MODNAME, chip); + ret = devm_request_irq(&pdev->dev, pdev->irq, ioh_gpio_handler, + IRQF_SHARED, KBUILD_MODNAME, chip); if (ret != 0) { dev_err(&pdev->dev, "%s request_irq failed\n", __func__); - goto err_request_irq; + goto err_gpiochip_add; } pci_set_drvdata(pdev, chip); return 0; -err_request_irq: - chip = chip_save; -err_irq_alloc_descs: - while (--j >= 0) { - chip--; - irq_free_descs(chip->irq_base, num_ports[j]); - } - - chip = chip_save; err_gpiochip_add: while (--i >= 0) { chip--; @@ -524,12 +514,8 @@ static void ioh_gpio_remove(struct pci_dev *pdev) chip_save = chip; - free_irq(pdev->irq, chip); - - for (i = 0; i < 8; i++, chip++) { - irq_free_descs(chip->irq_base, num_ports[i]); + for (i = 0; i < 8; i++, chip++) gpiochip_remove(&chip->gpio); - } chip = chip_save; pci_iounmap(pdev, chip->base); From 31bd86d9834fc1fb5bd00247358754bebabf0639 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Sat, 4 Mar 2017 17:23:34 +0100 Subject: [PATCH 12/77] gpio: xlp: use resource management for irqs Use the resource managed variant of irq_alloc_descs() and remove the code manually freeing allocated interrupt descriptors. Signed-off-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-xlp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-xlp.c b/drivers/gpio/gpio-xlp.c index 4620d050e5a8..7cc82cf82b82 100644 --- a/drivers/gpio/gpio-xlp.c +++ b/drivers/gpio/gpio-xlp.c @@ -404,7 +404,9 @@ static int xlp_gpio_probe(struct platform_device *pdev) /* XLP(MIPS) has fixed range for GPIO IRQs, Vulcan(ARM64) does not */ if (soc_type != GPIO_VARIANT_VULCAN) { - irq_base = irq_alloc_descs(-1, XLP_GPIO_IRQ_BASE, gc->ngpio, 0); + irq_base = devm_irq_alloc_descs(&pdev->dev, -1, + XLP_GPIO_IRQ_BASE, + gc->ngpio, 0); if (irq_base < 0) { dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n"); return irq_base; @@ -415,7 +417,7 @@ static int xlp_gpio_probe(struct platform_device *pdev) err = gpiochip_add_data(gc, priv); if (err < 0) - goto out_free_desc; + return err; err = gpiochip_irqchip_add(gc, &xlp_gpio_irq_chip, irq_base, handle_level_irq, IRQ_TYPE_NONE); @@ -433,8 +435,6 @@ static int xlp_gpio_probe(struct platform_device *pdev) out_gpio_remove: gpiochip_remove(gc); -out_free_desc: - irq_free_descs(irq_base, gc->ngpio); return err; } From bda61a192a512abf8d9962e3d30d6b63be13797a Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Sat, 4 Mar 2017 17:23:35 +0100 Subject: [PATCH 13/77] gpio: pxa: use devm_irq_alloc_descs() This driver never frees the interrupt descriptors it allocates. Fix it by using the resource managed version of irq_alloc_descs(). Signed-off-by: Bartosz Golaszewski Acked-by: Robert Jarzmik Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pxa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 76ac906b4d78..832f3e46ba9f 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -601,7 +601,7 @@ static int pxa_gpio_probe_dt(struct platform_device *pdev, nr_gpios = gpio_id->gpio_nums; pxa_last_gpio = nr_gpios - 1; - irq_base = irq_alloc_descs(-1, 0, nr_gpios, 0); + irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, nr_gpios, 0); if (irq_base < 0) { dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n"); return irq_base; From a1a3c2d551792747f85857a0c18609650d5948d8 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Sat, 4 Mar 2017 17:23:36 +0100 Subject: [PATCH 14/77] gpio: davinci: use devm_irq_alloc_descs() This driver never frees the interrupt descriptors it allocates. Fix it by using the resource managed version of irq_alloc_descs(). Signed-off-by: Bartosz Golaszewski Acked-by: Keerthy Signed-off-by: Linus Walleij --- drivers/gpio/gpio-davinci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 72f49d1e110d..ac173575d3f6 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -483,7 +483,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) clk_prepare_enable(clk); if (!pdata->gpio_unbanked) { - irq = irq_alloc_descs(-1, 0, ngpio, 0); + irq = devm_irq_alloc_descs(dev, -1, 0, ngpio, 0); if (irq < 0) { dev_err(dev, "Couldn't allocate IRQ numbers\n"); return irq; From 74dd9ebffff21295e2276ef4cff695a1324bfedd Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Sat, 4 Mar 2017 17:23:37 +0100 Subject: [PATCH 15/77] gpio: sodaville: use resource management for irqs Use device resource managed variants of irq_alloc_descs() and request_irq() and remove the code manually freeing irq resources. Signed-off-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-sodaville.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c index 7da9e6c4546a..f60da83349ef 100644 --- a/drivers/gpio/gpio-sodaville.c +++ b/drivers/gpio/gpio-sodaville.c @@ -135,7 +135,8 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd, struct irq_chip_type *ct; int ret; - sd->irq_base = irq_alloc_descs(-1, 0, SDV_NUM_PUB_GPIOS, -1); + sd->irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, + SDV_NUM_PUB_GPIOS, -1); if (sd->irq_base < 0) return sd->irq_base; @@ -143,10 +144,11 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd, writel(0, sd->gpio_pub_base + GPIO_INT); writel((1 << 11) - 1, sd->gpio_pub_base + GPSTR); - ret = request_irq(pdev->irq, sdv_gpio_pub_irq_handler, IRQF_SHARED, - "sdv_gpio", sd); + ret = devm_request_irq(&pdev->dev, pdev->irq, + sdv_gpio_pub_irq_handler, IRQF_SHARED, + "sdv_gpio", sd); if (ret) - goto out_free_desc; + return ret; /* * This gpio irq controller latches level irqs. Testing shows that if @@ -155,10 +157,8 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd, */ sd->gc = irq_alloc_generic_chip("sdv-gpio", 1, sd->irq_base, sd->gpio_pub_base, handle_fasteoi_irq); - if (!sd->gc) { - ret = -ENOMEM; - goto out_free_irq; - } + if (!sd->gc) + return -ENOMEM; sd->gc->private = sd; ct = sd->gc->chip_types; @@ -176,16 +176,10 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd, sd->id = irq_domain_add_legacy(pdev->dev.of_node, SDV_NUM_PUB_GPIOS, sd->irq_base, 0, &irq_domain_sdv_ops, sd); - if (!sd->id) { - ret = -ENODEV; - goto out_free_irq; - } + if (!sd->id) + return -ENODEV; + return 0; -out_free_irq: - free_irq(pdev->irq, sd); -out_free_desc: - irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS); - return ret; } static int sdv_gpio_probe(struct pci_dev *pdev, From c553c3c4786b9bfbf46b90ebac9c28192377fc13 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Sat, 4 Mar 2017 17:23:38 +0100 Subject: [PATCH 16/77] gpio: mxc: use devm_irq_alloc_descs() This driver never frees the interrupt descriptors it allocates. Fix it by using the resource managed version of irq_alloc_descs(). Signed-off-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mxc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index c1a1e00b8cb0..3abea3f0b307 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -471,7 +471,7 @@ static int mxc_gpio_probe(struct platform_device *pdev) if (err) goto out_bgio; - irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id()); + irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, 32, numa_node_id()); if (irq_base < 0) { err = irq_base; goto out_bgio; @@ -481,7 +481,7 @@ static int mxc_gpio_probe(struct platform_device *pdev) &irq_domain_simple_ops, NULL); if (!port->domain) { err = -ENODEV; - goto out_irqdesc_free; + goto out_bgio; } /* gpio-mxc can be a generic irq chip */ @@ -495,8 +495,6 @@ static int mxc_gpio_probe(struct platform_device *pdev) out_irqdomain_remove: irq_domain_remove(port->domain); -out_irqdesc_free: - irq_free_descs(irq_base, 32); out_bgio: dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err); return err; From 8514b5439c90f077fadaf981b5f1aec9cde7be76 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Sat, 4 Mar 2017 17:23:39 +0100 Subject: [PATCH 17/77] gpio: mxs: use devm_irq_alloc_descs() This driver never frees the interrupt descriptors it allocates. Fix it by using the resource managed version of irq_alloc_descs(). Signed-off-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mxs.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 2292742eac8f..6ae583f36733 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -328,7 +328,7 @@ static int mxs_gpio_probe(struct platform_device *pdev) /* clear address has to be used to clear IRQSTAT bits */ writel(~0U, port->base + PINCTRL_IRQSTAT(port) + MXS_CLR); - irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id()); + irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, 32, numa_node_id()); if (irq_base < 0) { err = irq_base; goto out_iounmap; @@ -338,7 +338,7 @@ static int mxs_gpio_probe(struct platform_device *pdev) &irq_domain_simple_ops, NULL); if (!port->domain) { err = -ENODEV; - goto out_irqdesc_free; + goto out_iounmap; } /* gpio-mxs can be a generic irq chip */ @@ -370,8 +370,6 @@ static int mxs_gpio_probe(struct platform_device *pdev) out_irqdomain_remove: irq_domain_remove(port->domain); -out_irqdesc_free: - irq_free_descs(irq_base, 32); out_iounmap: iounmap(port->base); return err; From 7ad63c790bc725f60a8baf298be2cdfd1268469d Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Sat, 4 Mar 2017 17:23:40 +0100 Subject: [PATCH 18/77] gpio: sta2x11: use resource management for irqs Use device resource managed variants of irq_alloc_descs() and request_irq() and remove the code manually freeing irq resources. Signed-off-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-sta2x11.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c index 853ca23cad88..39df0620fa38 100644 --- a/drivers/gpio/gpio-sta2x11.c +++ b/drivers/gpio/gpio-sta2x11.c @@ -392,7 +392,8 @@ static int gsta_probe(struct platform_device *dev) gsta_set_config(chip, i, gpio_pdata->pinconfig[i]); /* 384 was used in previous code: be compatible for other drivers */ - err = irq_alloc_descs(-1, 384, GSTA_NR_GPIO, NUMA_NO_NODE); + err = devm_irq_alloc_descs(&dev->dev, -1, 384, + GSTA_NR_GPIO, NUMA_NO_NODE); if (err < 0) { dev_warn(&dev->dev, "sta2x11 gpio: Can't get irq base (%i)\n", -err); @@ -401,29 +402,23 @@ static int gsta_probe(struct platform_device *dev) chip->irq_base = err; gsta_alloc_irq_chip(chip); - err = request_irq(pdev->irq, gsta_gpio_handler, - IRQF_SHARED, KBUILD_MODNAME, chip); + err = devm_request_irq(&dev->dev, pdev->irq, gsta_gpio_handler, + IRQF_SHARED, KBUILD_MODNAME, chip); if (err < 0) { dev_err(&dev->dev, "sta2x11 gpio: Can't request irq (%i)\n", -err); - goto err_free_descs; + 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); - goto err_free_irq; + return err; } platform_set_drvdata(dev, chip); return 0; - -err_free_irq: - free_irq(pdev->irq, chip); -err_free_descs: - irq_free_descs(chip->irq_base, GSTA_NR_GPIO); - return err; } static struct platform_driver sta2x11_gpio_platform_driver = { From 660549e05d6bf7ed7160de51da2948c2f1646f7e Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Tue, 10 Jan 2017 13:51:06 -0500 Subject: [PATCH 19/77] gpio: pc104: Mask PC/104 drivers via PC104 Kconfig option PC/104 drivers should be hidden on machines which do not support PC/104 devices. This patch adds the PC104 Kconfig option as a dependency for the relevant PC/104 device driver Kconfig options. Cc: Linus Walleij Cc: Alexandre Courbot Signed-off-by: William Breathitt Gray Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 05043071fc98..a3b07702de88 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -557,7 +557,7 @@ menu "Port-mapped I/O GPIO drivers" config GPIO_104_DIO_48E tristate "ACCES 104-DIO-48E GPIO support" - depends on ISA_BUS_API + depends on PC104 && ISA_BUS_API select GPIOLIB_IRQCHIP help Enables GPIO support for the ACCES 104-DIO-48E series (104-DIO-48E, @@ -567,7 +567,7 @@ config GPIO_104_DIO_48E config GPIO_104_IDIO_16 tristate "ACCES 104-IDIO-16 GPIO support" - depends on ISA_BUS_API + depends on PC104 && ISA_BUS_API select GPIOLIB_IRQCHIP help Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16, @@ -578,7 +578,7 @@ config GPIO_104_IDIO_16 config GPIO_104_IDI_48 tristate "ACCES 104-IDI-48 GPIO support" - depends on ISA_BUS_API + depends on PC104 && ISA_BUS_API select GPIOLIB_IRQCHIP help Enables GPIO support for the ACCES 104-IDI-48 family (104-IDI-48A, @@ -598,7 +598,7 @@ config GPIO_F7188X config GPIO_GPIO_MM tristate "Diamond Systems GPIO-MM GPIO support" - depends on ISA_BUS_API + depends on PC104 && ISA_BUS_API help Enables GPIO support for the Diamond Systems GPIO-MM and GPIO-MM-12. From 21d01c9c081ab231d6ef9d94ad9345c58b6568c1 Mon Sep 17 00:00:00 2001 From: Julia Cartwright Date: Thu, 9 Mar 2017 10:21:49 -0600 Subject: [PATCH 20/77] gpio: altera: make use of raw_spinlock variants The altera gpio driver currently implements an irq_chip for handling interrupts; due to how irq_chip handling is done, it's necessary for the irq_chip methods to be invoked from hardirq context, even on a a real-time kernel. Because the spinlock_t type becomes a "sleeping" spinlock w/ RT kernels, it is not suitable to be used with irq_chips. A quick audit of the operations under the lock reveal that they do only minimal, bounded work, and are therefore safe to do under a raw spinlock. Signed-off-by: Julia Cartwright Signed-off-by: Linus Walleij --- drivers/gpio/gpio-altera.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c index 5bddbd507ca9..6c08d16ea911 100644 --- a/drivers/gpio/gpio-altera.c +++ b/drivers/gpio/gpio-altera.c @@ -38,7 +38,7 @@ */ struct altera_gpio_chip { struct of_mm_gpio_chip mmchip; - spinlock_t gpio_lock; + raw_spinlock_t gpio_lock; int interrupt_trigger; int mapped_irq; }; @@ -53,12 +53,12 @@ static void altera_gpio_irq_unmask(struct irq_data *d) altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d)); mm_gc = &altera_gc->mmchip; - spin_lock_irqsave(&altera_gc->gpio_lock, flags); + raw_spin_lock_irqsave(&altera_gc->gpio_lock, flags); intmask = readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK); /* Set ALTERA_GPIO_IRQ_MASK bit to unmask */ intmask |= BIT(irqd_to_hwirq(d)); writel(intmask, mm_gc->regs + ALTERA_GPIO_IRQ_MASK); - spin_unlock_irqrestore(&altera_gc->gpio_lock, flags); + raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags); } static void altera_gpio_irq_mask(struct irq_data *d) @@ -71,12 +71,12 @@ static void altera_gpio_irq_mask(struct irq_data *d) altera_gc = gpiochip_get_data(irq_data_get_irq_chip_data(d)); mm_gc = &altera_gc->mmchip; - spin_lock_irqsave(&altera_gc->gpio_lock, flags); + raw_spin_lock_irqsave(&altera_gc->gpio_lock, flags); intmask = readl(mm_gc->regs + ALTERA_GPIO_IRQ_MASK); /* Clear ALTERA_GPIO_IRQ_MASK bit to mask */ intmask &= ~BIT(irqd_to_hwirq(d)); writel(intmask, mm_gc->regs + ALTERA_GPIO_IRQ_MASK); - spin_unlock_irqrestore(&altera_gc->gpio_lock, flags); + raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags); } /** @@ -143,14 +143,14 @@ static void altera_gpio_set(struct gpio_chip *gc, unsigned offset, int value) mm_gc = to_of_mm_gpio_chip(gc); chip = gpiochip_get_data(gc); - spin_lock_irqsave(&chip->gpio_lock, flags); + raw_spin_lock_irqsave(&chip->gpio_lock, flags); data_reg = readl(mm_gc->regs + ALTERA_GPIO_DATA); if (value) data_reg |= BIT(offset); else data_reg &= ~BIT(offset); writel(data_reg, mm_gc->regs + ALTERA_GPIO_DATA); - spin_unlock_irqrestore(&chip->gpio_lock, flags); + raw_spin_unlock_irqrestore(&chip->gpio_lock, flags); } static int altera_gpio_direction_input(struct gpio_chip *gc, unsigned offset) @@ -163,12 +163,12 @@ static int altera_gpio_direction_input(struct gpio_chip *gc, unsigned offset) mm_gc = to_of_mm_gpio_chip(gc); chip = gpiochip_get_data(gc); - spin_lock_irqsave(&chip->gpio_lock, flags); + raw_spin_lock_irqsave(&chip->gpio_lock, flags); /* Set pin as input, assumes software controlled IP */ gpio_ddr = readl(mm_gc->regs + ALTERA_GPIO_DIR); gpio_ddr &= ~BIT(offset); writel(gpio_ddr, mm_gc->regs + ALTERA_GPIO_DIR); - spin_unlock_irqrestore(&chip->gpio_lock, flags); + raw_spin_unlock_irqrestore(&chip->gpio_lock, flags); return 0; } @@ -184,7 +184,7 @@ static int altera_gpio_direction_output(struct gpio_chip *gc, mm_gc = to_of_mm_gpio_chip(gc); chip = gpiochip_get_data(gc); - spin_lock_irqsave(&chip->gpio_lock, flags); + raw_spin_lock_irqsave(&chip->gpio_lock, flags); /* Sets the GPIO value */ data_reg = readl(mm_gc->regs + ALTERA_GPIO_DATA); if (value) @@ -197,7 +197,7 @@ static int altera_gpio_direction_output(struct gpio_chip *gc, gpio_ddr = readl(mm_gc->regs + ALTERA_GPIO_DIR); gpio_ddr |= BIT(offset); writel(gpio_ddr, mm_gc->regs + ALTERA_GPIO_DIR); - spin_unlock_irqrestore(&chip->gpio_lock, flags); + raw_spin_unlock_irqrestore(&chip->gpio_lock, flags); return 0; } @@ -266,7 +266,7 @@ static int altera_gpio_probe(struct platform_device *pdev) if (!altera_gc) return -ENOMEM; - spin_lock_init(&altera_gc->gpio_lock); + raw_spin_lock_init(&altera_gc->gpio_lock); if (of_property_read_u32(node, "altr,ngpio", ®)) /* By default assume maximum ngpio */ From 45897809d518c7a84b215c79b58e4add9b8a1d40 Mon Sep 17 00:00:00 2001 From: Julia Cartwright Date: Thu, 9 Mar 2017 10:21:52 -0600 Subject: [PATCH 21/77] gpio: 104-dio-48e: make use of raw_spinlock variants The 104-dio-48e gpio driver currently implements an irq_chip for handling interrupts; due to how irq_chip handling is done, it's necessary for the irq_chip methods to be invoked from hardirq context, even on a a real-time kernel. Because the spinlock_t type becomes a "sleeping" spinlock w/ RT kernels, it is not suitable to be used with irq_chips. A quick audit of the operations under the lock reveal that they do only minimal, bounded work, and are therefore safe to do under a raw spinlock. Signed-off-by: Julia Cartwright Acked-by: William Breathitt Gray Signed-off-by: Linus Walleij --- drivers/gpio/gpio-104-dio-48e.c | 38 ++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c index 17bd2ab4ebe2..61b50c40b87b 100644 --- a/drivers/gpio/gpio-104-dio-48e.c +++ b/drivers/gpio/gpio-104-dio-48e.c @@ -55,7 +55,7 @@ struct dio48e_gpio { unsigned char io_state[6]; unsigned char out_state[6]; unsigned char control[2]; - spinlock_t lock; + raw_spinlock_t lock; unsigned base; unsigned char irq_mask; }; @@ -78,7 +78,7 @@ static int dio48e_gpio_direction_input(struct gpio_chip *chip, unsigned offset) unsigned long flags; unsigned control; - spin_lock_irqsave(&dio48egpio->lock, flags); + raw_spin_lock_irqsave(&dio48egpio->lock, flags); /* Check if configuring Port C */ if (io_port == 2 || io_port == 5) { @@ -103,7 +103,7 @@ static int dio48e_gpio_direction_input(struct gpio_chip *chip, unsigned offset) control &= ~BIT(7); outb(control, control_addr); - spin_unlock_irqrestore(&dio48egpio->lock, flags); + raw_spin_unlock_irqrestore(&dio48egpio->lock, flags); return 0; } @@ -120,7 +120,7 @@ static int dio48e_gpio_direction_output(struct gpio_chip *chip, unsigned offset, unsigned long flags; unsigned control; - spin_lock_irqsave(&dio48egpio->lock, flags); + raw_spin_lock_irqsave(&dio48egpio->lock, flags); /* Check if configuring Port C */ if (io_port == 2 || io_port == 5) { @@ -153,7 +153,7 @@ static int dio48e_gpio_direction_output(struct gpio_chip *chip, unsigned offset, control &= ~BIT(7); outb(control, control_addr); - spin_unlock_irqrestore(&dio48egpio->lock, flags); + raw_spin_unlock_irqrestore(&dio48egpio->lock, flags); return 0; } @@ -167,17 +167,17 @@ static int dio48e_gpio_get(struct gpio_chip *chip, unsigned offset) unsigned long flags; unsigned port_state; - spin_lock_irqsave(&dio48egpio->lock, flags); + raw_spin_lock_irqsave(&dio48egpio->lock, flags); /* ensure that GPIO is set for input */ if (!(dio48egpio->io_state[port] & mask)) { - spin_unlock_irqrestore(&dio48egpio->lock, flags); + raw_spin_unlock_irqrestore(&dio48egpio->lock, flags); return -EINVAL; } port_state = inb(dio48egpio->base + in_port); - spin_unlock_irqrestore(&dio48egpio->lock, flags); + raw_spin_unlock_irqrestore(&dio48egpio->lock, flags); return !!(port_state & mask); } @@ -190,7 +190,7 @@ static void dio48e_gpio_set(struct gpio_chip *chip, unsigned offset, int value) const unsigned out_port = (port > 2) ? port + 1 : port; unsigned long flags; - spin_lock_irqsave(&dio48egpio->lock, flags); + raw_spin_lock_irqsave(&dio48egpio->lock, flags); if (value) dio48egpio->out_state[port] |= mask; @@ -199,7 +199,7 @@ static void dio48e_gpio_set(struct gpio_chip *chip, unsigned offset, int value) outb(dio48egpio->out_state[port], dio48egpio->base + out_port); - spin_unlock_irqrestore(&dio48egpio->lock, flags); + raw_spin_unlock_irqrestore(&dio48egpio->lock, flags); } static void dio48e_gpio_set_multiple(struct gpio_chip *chip, @@ -225,14 +225,14 @@ static void dio48e_gpio_set_multiple(struct gpio_chip *chip, out_port = (port > 2) ? port + 1 : port; bitmask = mask[BIT_WORD(i)] & bits[BIT_WORD(i)]; - spin_lock_irqsave(&dio48egpio->lock, flags); + raw_spin_lock_irqsave(&dio48egpio->lock, flags); /* update output state data and set device gpio register */ dio48egpio->out_state[port] &= ~mask[BIT_WORD(i)]; dio48egpio->out_state[port] |= bitmask; outb(dio48egpio->out_state[port], dio48egpio->base + out_port); - spin_unlock_irqrestore(&dio48egpio->lock, flags); + raw_spin_unlock_irqrestore(&dio48egpio->lock, flags); /* prepare for next gpio register set */ mask[BIT_WORD(i)] >>= gpio_reg_size; @@ -255,7 +255,7 @@ static void dio48e_irq_mask(struct irq_data *data) if (offset != 19 && offset != 43) return; - spin_lock_irqsave(&dio48egpio->lock, flags); + raw_spin_lock_irqsave(&dio48egpio->lock, flags); if (offset == 19) dio48egpio->irq_mask &= ~BIT(0); @@ -266,7 +266,7 @@ static void dio48e_irq_mask(struct irq_data *data) /* disable interrupts */ inb(dio48egpio->base + 0xB); - spin_unlock_irqrestore(&dio48egpio->lock, flags); + raw_spin_unlock_irqrestore(&dio48egpio->lock, flags); } static void dio48e_irq_unmask(struct irq_data *data) @@ -280,7 +280,7 @@ static void dio48e_irq_unmask(struct irq_data *data) if (offset != 19 && offset != 43) return; - spin_lock_irqsave(&dio48egpio->lock, flags); + raw_spin_lock_irqsave(&dio48egpio->lock, flags); if (!dio48egpio->irq_mask) { /* enable interrupts */ @@ -293,7 +293,7 @@ static void dio48e_irq_unmask(struct irq_data *data) else dio48egpio->irq_mask |= BIT(1); - spin_unlock_irqrestore(&dio48egpio->lock, flags); + raw_spin_unlock_irqrestore(&dio48egpio->lock, flags); } static int dio48e_irq_set_type(struct irq_data *data, unsigned flow_type) @@ -329,11 +329,11 @@ static irqreturn_t dio48e_irq_handler(int irq, void *dev_id) generic_handle_irq(irq_find_mapping(chip->irqdomain, 19 + gpio*24)); - spin_lock(&dio48egpio->lock); + raw_spin_lock(&dio48egpio->lock); outb(0x00, dio48egpio->base + 0xF); - spin_unlock(&dio48egpio->lock); + raw_spin_unlock(&dio48egpio->lock); return IRQ_HANDLED; } @@ -388,7 +388,7 @@ static int dio48e_probe(struct device *dev, unsigned int id) dio48egpio->chip.set_multiple = dio48e_gpio_set_multiple; dio48egpio->base = base[id]; - spin_lock_init(&dio48egpio->lock); + raw_spin_lock_init(&dio48egpio->lock); err = devm_gpiochip_add_data(dev, &dio48egpio->chip, dio48egpio); if (err) { From c69fcea57e9d2b27025235b3205861c3895fa618 Mon Sep 17 00:00:00 2001 From: Julia Cartwright Date: Thu, 9 Mar 2017 10:21:54 -0600 Subject: [PATCH 22/77] gpio: bcm-kona: make use of raw_spinlock variants The bcm-kona gpio driver currently implements an irq_chip for handling interrupts; due to how irq_chip handling is done, it's necessary for the irq_chip methods to be invoked from hardirq context, even on a a real-time kernel. Because the spinlock_t type becomes a "sleeping" spinlock w/ RT kernels, it is not suitable to be used with irq_chips. A quick audit of the operations under the lock reveal that they do only minimal, bounded work, and are therefore safe to do under a raw spinlock. Signed-off-by: Julia Cartwright Signed-off-by: Linus Walleij --- drivers/gpio/gpio-bcm-kona.c | 48 ++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c index 41d0ac142580..dfcf56ee3c61 100644 --- a/drivers/gpio/gpio-bcm-kona.c +++ b/drivers/gpio/gpio-bcm-kona.c @@ -67,7 +67,7 @@ struct bcm_kona_gpio { void __iomem *reg_base; int num_bank; - spinlock_t lock; + raw_spinlock_t lock; struct gpio_chip gpio_chip; struct irq_domain *irq_domain; struct bcm_kona_gpio_bank *banks; @@ -95,13 +95,13 @@ static void bcm_kona_gpio_lock_gpio(struct bcm_kona_gpio *kona_gpio, unsigned long flags; int bank_id = GPIO_BANK(gpio); - spin_lock_irqsave(&kona_gpio->lock, flags); + raw_spin_lock_irqsave(&kona_gpio->lock, flags); val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id)); val |= BIT(gpio); bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val); - spin_unlock_irqrestore(&kona_gpio->lock, flags); + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); } static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio, @@ -111,13 +111,13 @@ static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio, unsigned long flags; int bank_id = GPIO_BANK(gpio); - spin_lock_irqsave(&kona_gpio->lock, flags); + raw_spin_lock_irqsave(&kona_gpio->lock, flags); val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id)); val &= ~BIT(gpio); bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val); - spin_unlock_irqrestore(&kona_gpio->lock, flags); + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); } static int bcm_kona_gpio_get_dir(struct gpio_chip *chip, unsigned gpio) @@ -141,7 +141,7 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value) kona_gpio = gpiochip_get_data(chip); reg_base = kona_gpio->reg_base; - spin_lock_irqsave(&kona_gpio->lock, flags); + raw_spin_lock_irqsave(&kona_gpio->lock, flags); /* this function only applies to output pin */ if (bcm_kona_gpio_get_dir(chip, gpio) == GPIOF_DIR_IN) @@ -154,7 +154,7 @@ static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value) writel(val, reg_base + reg_offset); out: - spin_unlock_irqrestore(&kona_gpio->lock, flags); + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); } static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio) @@ -168,7 +168,7 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio) kona_gpio = gpiochip_get_data(chip); reg_base = kona_gpio->reg_base; - spin_lock_irqsave(&kona_gpio->lock, flags); + raw_spin_lock_irqsave(&kona_gpio->lock, flags); if (bcm_kona_gpio_get_dir(chip, gpio) == GPIOF_DIR_IN) reg_offset = GPIO_IN_STATUS(bank_id); @@ -178,7 +178,7 @@ static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio) /* read the GPIO bank status */ val = readl(reg_base + reg_offset); - spin_unlock_irqrestore(&kona_gpio->lock, flags); + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); /* return the specified bit status */ return !!(val & BIT(bit)); @@ -208,14 +208,14 @@ static int bcm_kona_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) kona_gpio = gpiochip_get_data(chip); reg_base = kona_gpio->reg_base; - spin_lock_irqsave(&kona_gpio->lock, flags); + raw_spin_lock_irqsave(&kona_gpio->lock, flags); val = readl(reg_base + GPIO_CONTROL(gpio)); val &= ~GPIO_GPCTR0_IOTR_MASK; val |= GPIO_GPCTR0_IOTR_CMD_INPUT; writel(val, reg_base + GPIO_CONTROL(gpio)); - spin_unlock_irqrestore(&kona_gpio->lock, flags); + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); return 0; } @@ -232,7 +232,7 @@ static int bcm_kona_gpio_direction_output(struct gpio_chip *chip, kona_gpio = gpiochip_get_data(chip); reg_base = kona_gpio->reg_base; - spin_lock_irqsave(&kona_gpio->lock, flags); + raw_spin_lock_irqsave(&kona_gpio->lock, flags); val = readl(reg_base + GPIO_CONTROL(gpio)); val &= ~GPIO_GPCTR0_IOTR_MASK; @@ -244,7 +244,7 @@ static int bcm_kona_gpio_direction_output(struct gpio_chip *chip, val |= BIT(bit); writel(val, reg_base + reg_offset); - spin_unlock_irqrestore(&kona_gpio->lock, flags); + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); return 0; } @@ -288,7 +288,7 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio, } /* spin lock for read-modify-write of the GPIO register */ - spin_lock_irqsave(&kona_gpio->lock, flags); + raw_spin_lock_irqsave(&kona_gpio->lock, flags); val = readl(reg_base + GPIO_CONTROL(gpio)); val &= ~GPIO_GPCTR0_DBR_MASK; @@ -303,7 +303,7 @@ static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio, writel(val, reg_base + GPIO_CONTROL(gpio)); - spin_unlock_irqrestore(&kona_gpio->lock, flags); + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); return 0; } @@ -347,13 +347,13 @@ static void bcm_kona_gpio_irq_ack(struct irq_data *d) kona_gpio = irq_data_get_irq_chip_data(d); reg_base = kona_gpio->reg_base; - spin_lock_irqsave(&kona_gpio->lock, flags); + raw_spin_lock_irqsave(&kona_gpio->lock, flags); val = readl(reg_base + GPIO_INT_STATUS(bank_id)); val |= BIT(bit); writel(val, reg_base + GPIO_INT_STATUS(bank_id)); - spin_unlock_irqrestore(&kona_gpio->lock, flags); + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); } static void bcm_kona_gpio_irq_mask(struct irq_data *d) @@ -368,13 +368,13 @@ static void bcm_kona_gpio_irq_mask(struct irq_data *d) kona_gpio = irq_data_get_irq_chip_data(d); reg_base = kona_gpio->reg_base; - spin_lock_irqsave(&kona_gpio->lock, flags); + raw_spin_lock_irqsave(&kona_gpio->lock, flags); val = readl(reg_base + GPIO_INT_MASK(bank_id)); val |= BIT(bit); writel(val, reg_base + GPIO_INT_MASK(bank_id)); - spin_unlock_irqrestore(&kona_gpio->lock, flags); + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); } static void bcm_kona_gpio_irq_unmask(struct irq_data *d) @@ -389,13 +389,13 @@ static void bcm_kona_gpio_irq_unmask(struct irq_data *d) kona_gpio = irq_data_get_irq_chip_data(d); reg_base = kona_gpio->reg_base; - spin_lock_irqsave(&kona_gpio->lock, flags); + raw_spin_lock_irqsave(&kona_gpio->lock, flags); val = readl(reg_base + GPIO_INT_MSKCLR(bank_id)); val |= BIT(bit); writel(val, reg_base + GPIO_INT_MSKCLR(bank_id)); - spin_unlock_irqrestore(&kona_gpio->lock, flags); + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); } static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type) @@ -431,14 +431,14 @@ static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type) return -EINVAL; } - spin_lock_irqsave(&kona_gpio->lock, flags); + raw_spin_lock_irqsave(&kona_gpio->lock, flags); val = readl(reg_base + GPIO_CONTROL(gpio)); val &= ~GPIO_GPCTR0_ITR_MASK; val |= lvl_type << GPIO_GPCTR0_ITR_SHIFT; writel(val, reg_base + GPIO_CONTROL(gpio)); - spin_unlock_irqrestore(&kona_gpio->lock, flags); + raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); return 0; } @@ -655,7 +655,7 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev) bank); } - spin_lock_init(&kona_gpio->lock); + raw_spin_lock_init(&kona_gpio->lock); return 0; From a080ce53eea56407779eb7ccf0ff00af0734bcdf Mon Sep 17 00:00:00 2001 From: Julia Cartwright Date: Thu, 9 Mar 2017 10:21:53 -0600 Subject: [PATCH 23/77] gpio: ath79: make use of raw_spinlock variants The ath79 gpio driver currently implements an irq_chip for handling interrupts; due to how irq_chip handling is done, it's necessary for the irq_chip methods to be invoked from hardirq context, even on a a real-time kernel. Because the spinlock_t type becomes a "sleeping" spinlock w/ RT kernels, it is not suitable to be used with irq_chips. A quick audit of the operations under the lock reveal that they do only minimal, bounded work, and are therefore safe to do under a raw spinlock. Signed-off-by: Julia Cartwright Acked-by: Aban Bedel Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ath79.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c index dc37dbe4b46d..f33d4a5fe671 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c @@ -32,7 +32,7 @@ struct ath79_gpio_ctrl { struct gpio_chip gc; void __iomem *base; - spinlock_t lock; + raw_spinlock_t lock; unsigned long both_edges; }; @@ -74,9 +74,9 @@ static void ath79_gpio_irq_unmask(struct irq_data *data) u32 mask = BIT(irqd_to_hwirq(data)); unsigned long flags; - spin_lock_irqsave(&ctrl->lock, flags); + raw_spin_lock_irqsave(&ctrl->lock, flags); ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, mask); - spin_unlock_irqrestore(&ctrl->lock, flags); + raw_spin_unlock_irqrestore(&ctrl->lock, flags); } static void ath79_gpio_irq_mask(struct irq_data *data) @@ -85,9 +85,9 @@ static void ath79_gpio_irq_mask(struct irq_data *data) u32 mask = BIT(irqd_to_hwirq(data)); unsigned long flags; - spin_lock_irqsave(&ctrl->lock, flags); + raw_spin_lock_irqsave(&ctrl->lock, flags); ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0); - spin_unlock_irqrestore(&ctrl->lock, flags); + raw_spin_unlock_irqrestore(&ctrl->lock, flags); } static void ath79_gpio_irq_enable(struct irq_data *data) @@ -96,10 +96,10 @@ static void ath79_gpio_irq_enable(struct irq_data *data) u32 mask = BIT(irqd_to_hwirq(data)); unsigned long flags; - spin_lock_irqsave(&ctrl->lock, flags); + raw_spin_lock_irqsave(&ctrl->lock, flags); ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, mask); ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, mask); - spin_unlock_irqrestore(&ctrl->lock, flags); + raw_spin_unlock_irqrestore(&ctrl->lock, flags); } static void ath79_gpio_irq_disable(struct irq_data *data) @@ -108,10 +108,10 @@ static void ath79_gpio_irq_disable(struct irq_data *data) u32 mask = BIT(irqd_to_hwirq(data)); unsigned long flags; - spin_lock_irqsave(&ctrl->lock, flags); + raw_spin_lock_irqsave(&ctrl->lock, flags); ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_MASK, mask, 0); ath79_gpio_update_bits(ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, 0); - spin_unlock_irqrestore(&ctrl->lock, flags); + raw_spin_unlock_irqrestore(&ctrl->lock, flags); } static int ath79_gpio_irq_set_type(struct irq_data *data, @@ -140,7 +140,7 @@ static int ath79_gpio_irq_set_type(struct irq_data *data, return -EINVAL; } - spin_lock_irqsave(&ctrl->lock, flags); + raw_spin_lock_irqsave(&ctrl->lock, flags); if (flow_type == IRQ_TYPE_EDGE_BOTH) { ctrl->both_edges |= mask; @@ -165,7 +165,7 @@ static int ath79_gpio_irq_set_type(struct irq_data *data, ath79_gpio_update_bits( ctrl, AR71XX_GPIO_REG_INT_ENABLE, mask, mask); - spin_unlock_irqrestore(&ctrl->lock, flags); + raw_spin_unlock_irqrestore(&ctrl->lock, flags); return 0; } @@ -191,7 +191,7 @@ static void ath79_gpio_irq_handler(struct irq_desc *desc) chained_irq_enter(irqchip, desc); - spin_lock_irqsave(&ctrl->lock, flags); + raw_spin_lock_irqsave(&ctrl->lock, flags); pending = ath79_gpio_read(ctrl, AR71XX_GPIO_REG_INT_PENDING); @@ -203,7 +203,7 @@ static void ath79_gpio_irq_handler(struct irq_desc *desc) both_edges, ~state); } - spin_unlock_irqrestore(&ctrl->lock, flags); + raw_spin_unlock_irqrestore(&ctrl->lock, flags); if (pending) { for_each_set_bit(irq, &pending, gc->ngpio) @@ -262,7 +262,7 @@ static int ath79_gpio_probe(struct platform_device *pdev) if (!ctrl->base) return -ENOMEM; - spin_lock_init(&ctrl->lock); + raw_spin_lock_init(&ctrl->lock); err = bgpio_init(&ctrl->gc, &pdev->dev, 4, ctrl->base + AR71XX_GPIO_REG_IN, ctrl->base + AR71XX_GPIO_REG_SET, From f9c56536d50b4c55d42d7fb3396501906f7518fa Mon Sep 17 00:00:00 2001 From: Julia Cartwright Date: Thu, 9 Mar 2017 10:21:55 -0600 Subject: [PATCH 24/77] gpio: etraxfs: make use of raw_spinlock variants The etraxfs gpio driver currently implements an irq_chip for handling interrupts; due to how irq_chip handling is done, it's necessary for the irq_chip methods to be invoked from hardirq context, even on a a real-time kernel. Because the spinlock_t type becomes a "sleeping" spinlock w/ RT kernels, it is not suitable to be used with irq_chips. A quick audit of the operations under the lock reveal that they do only minimal, bounded work, and are therefore safe to do under a raw spinlock. Signed-off-by: Julia Cartwright Signed-off-by: Linus Walleij --- drivers/gpio/gpio-etraxfs.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-etraxfs.c b/drivers/gpio/gpio-etraxfs.c index a254d5b07b94..14c6aac26780 100644 --- a/drivers/gpio/gpio-etraxfs.c +++ b/drivers/gpio/gpio-etraxfs.c @@ -54,7 +54,7 @@ struct etraxfs_gpio_info; struct etraxfs_gpio_block { - spinlock_t lock; + raw_spinlock_t lock; u32 mask; u32 cfg; u32 pins; @@ -233,10 +233,10 @@ static void etraxfs_gpio_irq_mask(struct irq_data *d) struct etraxfs_gpio_block *block = chip->block; unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); - spin_lock(&block->lock); + raw_spin_lock(&block->lock); block->mask &= ~BIT(grpirq); writel(block->mask, block->regs + block->info->rw_intr_mask); - spin_unlock(&block->lock); + raw_spin_unlock(&block->lock); } static void etraxfs_gpio_irq_unmask(struct irq_data *d) @@ -246,10 +246,10 @@ static void etraxfs_gpio_irq_unmask(struct irq_data *d) struct etraxfs_gpio_block *block = chip->block; unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); - spin_lock(&block->lock); + raw_spin_lock(&block->lock); block->mask |= BIT(grpirq); writel(block->mask, block->regs + block->info->rw_intr_mask); - spin_unlock(&block->lock); + raw_spin_unlock(&block->lock); } static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type) @@ -280,11 +280,11 @@ static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type) return -EINVAL; } - spin_lock(&block->lock); + raw_spin_lock(&block->lock); block->cfg &= ~(0x7 << (grpirq * 3)); block->cfg |= (cfg << (grpirq * 3)); writel(block->cfg, block->regs + block->info->rw_intr_cfg); - spin_unlock(&block->lock); + raw_spin_unlock(&block->lock); return 0; } @@ -297,7 +297,7 @@ static int etraxfs_gpio_irq_request_resources(struct irq_data *d) unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); int ret = -EBUSY; - spin_lock(&block->lock); + raw_spin_lock(&block->lock); if (block->group[grpirq]) goto out; @@ -316,7 +316,7 @@ static int etraxfs_gpio_irq_request_resources(struct irq_data *d) } out: - spin_unlock(&block->lock); + raw_spin_unlock(&block->lock); return ret; } @@ -327,10 +327,10 @@ static void etraxfs_gpio_irq_release_resources(struct irq_data *d) struct etraxfs_gpio_block *block = chip->block; unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); - spin_lock(&block->lock); + raw_spin_lock(&block->lock); block->group[grpirq] = 0; gpiochip_unlock_as_irq(&chip->gc, d->hwirq); - spin_unlock(&block->lock); + raw_spin_unlock(&block->lock); } static struct irq_chip etraxfs_gpio_irq_chip = { @@ -391,7 +391,7 @@ static int etraxfs_gpio_probe(struct platform_device *pdev) if (!block) return -ENOMEM; - spin_lock_init(&block->lock); + raw_spin_lock_init(&block->lock); block->regs = regs; block->info = info; From 99b9b45de8808994ea9a176241e52bb6fab71cdd Mon Sep 17 00:00:00 2001 From: Julia Cartwright Date: Thu, 9 Mar 2017 10:21:56 -0600 Subject: [PATCH 25/77] gpio: pl061: make use of raw_spinlock variants The pl061 gpio driver currently implements an irq_chip for handling interrupts; due to how irq_chip handling is done, it's necessary for the irq_chip methods to be invoked from hardirq context, even on a a real-time kernel. Because the spinlock_t type becomes a "sleeping" spinlock w/ RT kernels, it is not suitable to be used with irq_chips. A quick audit of the operations under the lock reveal that they do only minimal, bounded work, and are therefore safe to do under a raw spinlock. Signed-off-by: Julia Cartwright Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pl061.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 0a6bfd2b06e5..3d3d6b6645a7 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -50,7 +50,7 @@ struct pl061_context_save_regs { #endif struct pl061 { - spinlock_t lock; + raw_spinlock_t lock; void __iomem *base; struct gpio_chip gc; @@ -74,11 +74,11 @@ static int pl061_direction_input(struct gpio_chip *gc, unsigned offset) unsigned long flags; unsigned char gpiodir; - spin_lock_irqsave(&pl061->lock, flags); + raw_spin_lock_irqsave(&pl061->lock, flags); gpiodir = readb(pl061->base + GPIODIR); gpiodir &= ~(BIT(offset)); writeb(gpiodir, pl061->base + GPIODIR); - spin_unlock_irqrestore(&pl061->lock, flags); + raw_spin_unlock_irqrestore(&pl061->lock, flags); return 0; } @@ -90,7 +90,7 @@ static int pl061_direction_output(struct gpio_chip *gc, unsigned offset, unsigned long flags; unsigned char gpiodir; - spin_lock_irqsave(&pl061->lock, flags); + raw_spin_lock_irqsave(&pl061->lock, flags); writeb(!!value << offset, pl061->base + (BIT(offset + 2))); gpiodir = readb(pl061->base + GPIODIR); gpiodir |= BIT(offset); @@ -101,7 +101,7 @@ static int pl061_direction_output(struct gpio_chip *gc, unsigned offset, * a gpio pin before configuring it in OUT mode. */ writeb(!!value << offset, pl061->base + (BIT(offset + 2))); - spin_unlock_irqrestore(&pl061->lock, flags); + raw_spin_unlock_irqrestore(&pl061->lock, flags); return 0; } @@ -143,7 +143,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger) } - spin_lock_irqsave(&pl061->lock, flags); + raw_spin_lock_irqsave(&pl061->lock, flags); gpioiev = readb(pl061->base + GPIOIEV); gpiois = readb(pl061->base + GPIOIS); @@ -203,7 +203,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger) writeb(gpioibe, pl061->base + GPIOIBE); writeb(gpioiev, pl061->base + GPIOIEV); - spin_unlock_irqrestore(&pl061->lock, flags); + raw_spin_unlock_irqrestore(&pl061->lock, flags); return 0; } @@ -235,10 +235,10 @@ static void pl061_irq_mask(struct irq_data *d) u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR); u8 gpioie; - spin_lock(&pl061->lock); + raw_spin_lock(&pl061->lock); gpioie = readb(pl061->base + GPIOIE) & ~mask; writeb(gpioie, pl061->base + GPIOIE); - spin_unlock(&pl061->lock); + raw_spin_unlock(&pl061->lock); } static void pl061_irq_unmask(struct irq_data *d) @@ -248,10 +248,10 @@ static void pl061_irq_unmask(struct irq_data *d) u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR); u8 gpioie; - spin_lock(&pl061->lock); + raw_spin_lock(&pl061->lock); gpioie = readb(pl061->base + GPIOIE) | mask; writeb(gpioie, pl061->base + GPIOIE); - spin_unlock(&pl061->lock); + raw_spin_unlock(&pl061->lock); } /** @@ -268,9 +268,9 @@ static void pl061_irq_ack(struct irq_data *d) struct pl061 *pl061 = gpiochip_get_data(gc); u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR); - spin_lock(&pl061->lock); + raw_spin_lock(&pl061->lock); writeb(mask, pl061->base + GPIOIC); - spin_unlock(&pl061->lock); + raw_spin_unlock(&pl061->lock); } static int pl061_irq_set_wake(struct irq_data *d, unsigned int state) @@ -304,7 +304,7 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) if (IS_ERR(pl061->base)) return PTR_ERR(pl061->base); - spin_lock_init(&pl061->lock); + raw_spin_lock_init(&pl061->lock); if (of_property_read_bool(dev->of_node, "gpio-ranges")) { pl061->gc.request = gpiochip_generic_request; pl061->gc.free = gpiochip_generic_free; From a0a584f0e92af068f4308586bad1ca5ea1e28d79 Mon Sep 17 00:00:00 2001 From: Julia Cartwright Date: Thu, 9 Mar 2017 10:21:57 -0600 Subject: [PATCH 26/77] gpio: ws16c48: make use of raw_spinlock variants The ws16c48 gpio driver currently implements an irq_chip for handling interrupts; due to how irq_chip handling is done, it's necessary for the irq_chip methods to be invoked from hardirq context, even on a a real-time kernel. Because the spinlock_t type becomes a "sleeping" spinlock w/ RT kernels, it is not suitable to be used with irq_chips. A quick audit of the operations under the lock reveal that they do only minimal, bounded work, and are therefore safe to do under a raw spinlock. Signed-off-by: Julia Cartwright Acked-by: William Breathitt Gray Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ws16c48.c | 46 ++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/gpio/gpio-ws16c48.c b/drivers/gpio/gpio-ws16c48.c index 901b5ccb032d..87d63695dfcf 100644 --- a/drivers/gpio/gpio-ws16c48.c +++ b/drivers/gpio/gpio-ws16c48.c @@ -51,7 +51,7 @@ struct ws16c48_gpio { struct gpio_chip chip; unsigned char io_state[6]; unsigned char out_state[6]; - spinlock_t lock; + raw_spinlock_t lock; unsigned long irq_mask; unsigned long flow_mask; unsigned base; @@ -73,13 +73,13 @@ static int ws16c48_gpio_direction_input(struct gpio_chip *chip, unsigned offset) const unsigned mask = BIT(offset % 8); unsigned long flags; - spin_lock_irqsave(&ws16c48gpio->lock, flags); + raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); ws16c48gpio->io_state[port] |= mask; ws16c48gpio->out_state[port] &= ~mask; outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port); - spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); return 0; } @@ -92,7 +92,7 @@ static int ws16c48_gpio_direction_output(struct gpio_chip *chip, const unsigned mask = BIT(offset % 8); unsigned long flags; - spin_lock_irqsave(&ws16c48gpio->lock, flags); + raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); ws16c48gpio->io_state[port] &= ~mask; if (value) @@ -101,7 +101,7 @@ static int ws16c48_gpio_direction_output(struct gpio_chip *chip, ws16c48gpio->out_state[port] &= ~mask; outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port); - spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); return 0; } @@ -114,17 +114,17 @@ static int ws16c48_gpio_get(struct gpio_chip *chip, unsigned offset) unsigned long flags; unsigned port_state; - spin_lock_irqsave(&ws16c48gpio->lock, flags); + raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); /* ensure that GPIO is set for input */ if (!(ws16c48gpio->io_state[port] & mask)) { - spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); return -EINVAL; } port_state = inb(ws16c48gpio->base + port); - spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); return !!(port_state & mask); } @@ -136,11 +136,11 @@ static void ws16c48_gpio_set(struct gpio_chip *chip, unsigned offset, int value) const unsigned mask = BIT(offset % 8); unsigned long flags; - spin_lock_irqsave(&ws16c48gpio->lock, flags); + raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); /* ensure that GPIO is set for output */ if (ws16c48gpio->io_state[port] & mask) { - spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); return; } @@ -150,7 +150,7 @@ static void ws16c48_gpio_set(struct gpio_chip *chip, unsigned offset, int value) ws16c48gpio->out_state[port] &= ~mask; outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port); - spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); } static void ws16c48_gpio_set_multiple(struct gpio_chip *chip, @@ -178,14 +178,14 @@ static void ws16c48_gpio_set_multiple(struct gpio_chip *chip, iomask = mask[BIT_WORD(i)] & ~ws16c48gpio->io_state[port]; bitmask = iomask & bits[BIT_WORD(i)]; - spin_lock_irqsave(&ws16c48gpio->lock, flags); + raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); /* update output state data and set device gpio register */ ws16c48gpio->out_state[port] &= ~iomask; ws16c48gpio->out_state[port] |= bitmask; outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port); - spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); /* prepare for next gpio register set */ mask[BIT_WORD(i)] >>= gpio_reg_size; @@ -207,7 +207,7 @@ static void ws16c48_irq_ack(struct irq_data *data) if (port > 2) return; - spin_lock_irqsave(&ws16c48gpio->lock, flags); + raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); port_state = ws16c48gpio->irq_mask >> (8*port); @@ -216,7 +216,7 @@ static void ws16c48_irq_ack(struct irq_data *data) outb(port_state | mask, ws16c48gpio->base + 8 + port); outb(0xC0, ws16c48gpio->base + 7); - spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); } static void ws16c48_irq_mask(struct irq_data *data) @@ -232,7 +232,7 @@ static void ws16c48_irq_mask(struct irq_data *data) if (port > 2) return; - spin_lock_irqsave(&ws16c48gpio->lock, flags); + raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); ws16c48gpio->irq_mask &= ~mask; @@ -240,7 +240,7 @@ static void ws16c48_irq_mask(struct irq_data *data) outb(ws16c48gpio->irq_mask >> (8*port), ws16c48gpio->base + 8 + port); outb(0xC0, ws16c48gpio->base + 7); - spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); } static void ws16c48_irq_unmask(struct irq_data *data) @@ -256,7 +256,7 @@ static void ws16c48_irq_unmask(struct irq_data *data) if (port > 2) return; - spin_lock_irqsave(&ws16c48gpio->lock, flags); + raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); ws16c48gpio->irq_mask |= mask; @@ -264,7 +264,7 @@ static void ws16c48_irq_unmask(struct irq_data *data) outb(ws16c48gpio->irq_mask >> (8*port), ws16c48gpio->base + 8 + port); outb(0xC0, ws16c48gpio->base + 7); - spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); } static int ws16c48_irq_set_type(struct irq_data *data, unsigned flow_type) @@ -280,7 +280,7 @@ static int ws16c48_irq_set_type(struct irq_data *data, unsigned flow_type) if (port > 2) return -EINVAL; - spin_lock_irqsave(&ws16c48gpio->lock, flags); + raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); switch (flow_type) { case IRQ_TYPE_NONE: @@ -292,7 +292,7 @@ static int ws16c48_irq_set_type(struct irq_data *data, unsigned flow_type) ws16c48gpio->flow_mask &= ~mask; break; default: - spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); return -EINVAL; } @@ -300,7 +300,7 @@ static int ws16c48_irq_set_type(struct irq_data *data, unsigned flow_type) outb(ws16c48gpio->flow_mask >> (8*port), ws16c48gpio->base + 8 + port); outb(0xC0, ws16c48gpio->base + 7); - spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); return 0; } @@ -387,7 +387,7 @@ static int ws16c48_probe(struct device *dev, unsigned int id) ws16c48gpio->chip.set_multiple = ws16c48_gpio_set_multiple; ws16c48gpio->base = base[id]; - spin_lock_init(&ws16c48gpio->lock); + raw_spin_lock_init(&ws16c48gpio->lock); err = devm_gpiochip_add_data(dev, &ws16c48gpio->chip, ws16c48gpio); if (err) { From 8c41ab4f0521918452851392ed40ed03923623e2 Mon Sep 17 00:00:00 2001 From: Julia Cartwright Date: Thu, 9 Mar 2017 10:21:58 -0600 Subject: [PATCH 27/77] gpio: zx: make use of raw_spinlock variants The zx gpio driver currently implements an irq_chip for handling interrupts; due to how irq_chip handling is done, it's necessary for the irq_chip methods to be invoked from hardirq context, even on a a real-time kernel. Because the spinlock_t type becomes a "sleeping" spinlock w/ RT kernels, it is not suitable to be used with irq_chips. A quick audit of the operations under the lock reveal that they do only minimal, bounded work, and are therefore safe to do under a raw spinlock. Signed-off-by: Julia Cartwright Signed-off-by: Linus Walleij --- drivers/gpio/gpio-zx.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-zx.c b/drivers/gpio/gpio-zx.c index 93de8be0d885..be3a87da8438 100644 --- a/drivers/gpio/gpio-zx.c +++ b/drivers/gpio/gpio-zx.c @@ -41,7 +41,7 @@ #define ZX_GPIO_NR 16 struct zx_gpio { - spinlock_t lock; + raw_spinlock_t lock; void __iomem *base; struct gpio_chip gc; @@ -56,11 +56,11 @@ static int zx_direction_input(struct gpio_chip *gc, unsigned offset) if (offset >= gc->ngpio) return -EINVAL; - spin_lock_irqsave(&chip->lock, flags); + raw_spin_lock_irqsave(&chip->lock, flags); gpiodir = readw_relaxed(chip->base + ZX_GPIO_DIR); gpiodir &= ~BIT(offset); writew_relaxed(gpiodir, chip->base + ZX_GPIO_DIR); - spin_unlock_irqrestore(&chip->lock, flags); + raw_spin_unlock_irqrestore(&chip->lock, flags); return 0; } @@ -75,7 +75,7 @@ static int zx_direction_output(struct gpio_chip *gc, unsigned offset, if (offset >= gc->ngpio) return -EINVAL; - spin_lock_irqsave(&chip->lock, flags); + raw_spin_lock_irqsave(&chip->lock, flags); gpiodir = readw_relaxed(chip->base + ZX_GPIO_DIR); gpiodir |= BIT(offset); writew_relaxed(gpiodir, chip->base + ZX_GPIO_DIR); @@ -84,7 +84,7 @@ static int zx_direction_output(struct gpio_chip *gc, unsigned offset, writew_relaxed(BIT(offset), chip->base + ZX_GPIO_DO1); else writew_relaxed(BIT(offset), chip->base + ZX_GPIO_DO0); - spin_unlock_irqrestore(&chip->lock, flags); + raw_spin_unlock_irqrestore(&chip->lock, flags); return 0; } @@ -118,7 +118,7 @@ static int zx_irq_type(struct irq_data *d, unsigned trigger) if (offset < 0 || offset >= ZX_GPIO_NR) return -EINVAL; - spin_lock_irqsave(&chip->lock, flags); + raw_spin_lock_irqsave(&chip->lock, flags); gpioiev = readw_relaxed(chip->base + ZX_GPIO_IV); gpiois = readw_relaxed(chip->base + ZX_GPIO_IVE); @@ -151,7 +151,7 @@ static int zx_irq_type(struct irq_data *d, unsigned trigger) writew_relaxed(gpioi_epos, chip->base + ZX_GPIO_IEP); writew_relaxed(gpioi_eneg, chip->base + ZX_GPIO_IEN); writew_relaxed(gpioiev, chip->base + ZX_GPIO_IV); - spin_unlock_irqrestore(&chip->lock, flags); + raw_spin_unlock_irqrestore(&chip->lock, flags); return 0; } @@ -184,12 +184,12 @@ static void zx_irq_mask(struct irq_data *d) u16 mask = BIT(irqd_to_hwirq(d) % ZX_GPIO_NR); u16 gpioie; - spin_lock(&chip->lock); + raw_spin_lock(&chip->lock); gpioie = readw_relaxed(chip->base + ZX_GPIO_IM) | mask; writew_relaxed(gpioie, chip->base + ZX_GPIO_IM); gpioie = readw_relaxed(chip->base + ZX_GPIO_IE) & ~mask; writew_relaxed(gpioie, chip->base + ZX_GPIO_IE); - spin_unlock(&chip->lock); + raw_spin_unlock(&chip->lock); } static void zx_irq_unmask(struct irq_data *d) @@ -199,12 +199,12 @@ static void zx_irq_unmask(struct irq_data *d) u16 mask = BIT(irqd_to_hwirq(d) % ZX_GPIO_NR); u16 gpioie; - spin_lock(&chip->lock); + raw_spin_lock(&chip->lock); gpioie = readw_relaxed(chip->base + ZX_GPIO_IM) & ~mask; writew_relaxed(gpioie, chip->base + ZX_GPIO_IM); gpioie = readw_relaxed(chip->base + ZX_GPIO_IE) | mask; writew_relaxed(gpioie, chip->base + ZX_GPIO_IE); - spin_unlock(&chip->lock); + raw_spin_unlock(&chip->lock); } static struct irq_chip zx_irqchip = { @@ -230,7 +230,7 @@ static int zx_gpio_probe(struct platform_device *pdev) if (IS_ERR(chip->base)) return PTR_ERR(chip->base); - spin_lock_init(&chip->lock); + raw_spin_lock_init(&chip->lock); if (of_property_read_bool(dev->of_node, "gpio-ranges")) { chip->gc.request = gpiochip_generic_request; chip->gc.free = gpiochip_generic_free; From 529f75d8ca214aa52ed609d1a909bbe3a71504bf Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Sun, 12 Mar 2017 11:14:28 +0000 Subject: [PATCH 28/77] gpio: xlp: Update for ARCH_THUNDER2 ARCH_VULCAN arm64 platform (for Broadcom Vulcan ARM64 processors) has been discontinued. Cavium's ThunderX2 CN99XX (ARCH_THUNDER2) will be the next revision of this platform. Update compile dependencies and ACPI ID to reflect this change. Signed-off-by: Jayachandran C [Drop depreciation of ARCH_VULCAN] Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 2 +- drivers/gpio/gpio-xlp.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index a3b07702de88..a386240c5921 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -505,7 +505,7 @@ config GPIO_XILINX config GPIO_XLP tristate "Netlogic XLP GPIO support" - depends on OF_GPIO && (CPU_XLP || ARCH_VULCAN || COMPILE_TEST) + depends on OF_GPIO && (CPU_XLP || ARCH_VULCAN || ARCH_THUNDER2 || COMPILE_TEST) select GPIOLIB_IRQCHIP help This driver provides support for GPIO interface on Netlogic XLP MIPS64 diff --git a/drivers/gpio/gpio-xlp.c b/drivers/gpio/gpio-xlp.c index 7cc82cf82b82..d857e1d8e731 100644 --- a/drivers/gpio/gpio-xlp.c +++ b/drivers/gpio/gpio-xlp.c @@ -441,6 +441,7 @@ out_gpio_remove: #ifdef CONFIG_ACPI static const struct acpi_device_id xlp_gpio_acpi_match[] = { { "BRCM9006", GPIO_VARIANT_VULCAN }, + { "CAV9006", GPIO_VARIANT_VULCAN }, {}, }; MODULE_DEVICE_TABLE(acpi, xlp_gpio_acpi_match); From 4ed55016d763325887461d43d0aec4010adcab65 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 20 Feb 2017 18:15:46 +0200 Subject: [PATCH 29/77] gpio: acpi: Don't return 0 on acpi_gpio_count() It's unusual to have error checking like (ret <= 0) in cases when counting GPIO resources. In case when it's mandatory we propagate the error (-ENOENT), otherwise we don't use the result. This makes consistent behaviour across all possible variants called in gpiod_count(). Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 108331de440b..a5b84d40e60c 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -1098,7 +1098,7 @@ int acpi_gpio_count(struct device *dev, const char *con_id) break; } } - if (count >= 0) + if (count > 0) break; } @@ -1114,7 +1114,7 @@ int acpi_gpio_count(struct device *dev, const char *con_id) if (crs_count > 0) count = crs_count; } - return count; + return count ? count : -ENOENT; } struct acpi_crs_lookup { From 4033d4a4f5236b01200010bf38928347af75d86e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 20 Feb 2017 18:15:47 +0200 Subject: [PATCH 30/77] gpio: of: Don't return 0 on dt_gpio_count() It's unusual to have error checking like (ret <= 0) in cases when counting GPIO resources. In case when it's mandatory we propagate the error (-ENOENT), otherwise we don't use the result. This makes consistent behaviour across all possible variants called in gpiod_count(). Signed-off-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 530b1ba984a4..c788b55dfe85 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3122,10 +3122,10 @@ static int dt_gpio_count(struct device *dev, const char *con_id) gpio_suffixes[i]); ret = of_gpio_named_count(dev->of_node, propname); - if (ret >= 0) + if (ret > 0) break; } - return ret; + return ret ? ret : -ENOENT; } static int platform_gpio_count(struct device *dev, const char *con_id) From 562e7a4032d1ff33e283d7ba1d5f10fe7ea96669 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 20 Feb 2017 18:15:48 +0200 Subject: [PATCH 31/77] platform/x86: surface3_button: Propagate error from gpiod_count() Since gpiod_count() does not return 0 anymore, we don't need to shadow its error code and would safely propagate to the user. While here, replace second parameter by NULL in order to prevent side effects on _DSD enabled firmware. Cc: Benjamin Tissoires Signed-off-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/platform/x86/surface3_button.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/surface3_button.c b/drivers/platform/x86/surface3_button.c index 8bfd7f613d36..57f51476bb65 100644 --- a/drivers/platform/x86/surface3_button.c +++ b/drivers/platform/x86/surface3_button.c @@ -196,9 +196,10 @@ static int surface3_button_probe(struct i2c_client *client, strlen(SURFACE_BUTTON_OBJ_NAME))) return -ENODEV; - if (gpiod_count(dev, KBUILD_MODNAME) <= 0) { + error = gpiod_count(dev, NULL); + if (error < 0) { dev_dbg(dev, "no GPIO attached, ignoring...\n"); - return -ENODEV; + return error; } priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); From c5097538c86a60c655f7fac33dfd565d22909dae Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 20 Feb 2017 18:15:49 +0200 Subject: [PATCH 32/77] Input: soc_button_array - Propagate error from gpiod_count() Since gpiod_count() does not return 0 anymore, we don't need to shadow its error code and would safely propagate to the user. While here, replace second parameter by NULL in order to prevent side effects on _DSD enabled firmware. Cc: Benjamin Tissoires Signed-off-by: Andy Shevchenko Acked-by: Dmitry Torokhov Signed-off-by: Linus Walleij --- drivers/input/misc/soc_button_array.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c index ddb2f22fca7a..c3b8e1fb4699 100644 --- a/drivers/input/misc/soc_button_array.c +++ b/drivers/input/misc/soc_button_array.c @@ -169,9 +169,10 @@ static int soc_button_probe(struct platform_device *pdev) button_info = (struct soc_button_info *)id->driver_data; - if (gpiod_count(dev, KBUILD_MODNAME) <= 0) { + error = gpiod_count(dev, NULL); + if (error < 0) { dev_dbg(dev, "no GPIO attached, ignoring...\n"); - return -ENODEV; + return error; } priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); From 6798d7271cb44ba8354356a389047d84058a7828 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 13 Mar 2017 23:04:21 +0100 Subject: [PATCH 33/77] gpio: acpi: Ignore -EPROBE_DEFER for unselected gpioints When acpi_dev_gpio_irq_get gets called with an index of say 2, it should not care if acpi_get_gpiod for index 0 or 1 returns -EPROBE_DEFER. This allows drivers which request a gpioint with index > 0 to function if there is no gpiochip driver (loaded) for gpioints with a lower index. Signed-off-by: Hans de Goede Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index a5b84d40e60c..56a6b1be3a17 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -684,20 +684,24 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index) { int idx, i; unsigned int irq_flags; - int ret = -ENOENT; for (i = 0, idx = 0; idx <= index; i++) { struct acpi_gpio_info info; struct gpio_desc *desc; desc = acpi_get_gpiod_by_index(adev, NULL, i, &info); - if (IS_ERR(desc)) { - ret = PTR_ERR(desc); - break; - } - if (info.gpioint && idx++ == index) { - int irq = gpiod_to_irq(desc); + /* Ignore -EPROBE_DEFER, it only matters if idx matches */ + if (IS_ERR(desc) && PTR_ERR(desc) != -EPROBE_DEFER) + return PTR_ERR(desc); + + if (info.gpioint && idx++ == index) { + int irq; + + if (IS_ERR(desc)) + return PTR_ERR(desc); + + irq = gpiod_to_irq(desc); if (irq < 0) return irq; @@ -713,7 +717,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index) } } - return ret; + return -ENOENT; } EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_get); From 7077f4cc1efc998dbaf9b516c7acf8f1397ccf22 Mon Sep 17 00:00:00 2001 From: Ralph Sennhauser Date: Thu, 16 Mar 2017 07:33:56 +0100 Subject: [PATCH 34/77] gpio: mvebu: checkpatch: block comment fixes Fix issues in block comments reported by checkpatch. Signed-off-by: Ralph Sennhauser Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mvebu.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index a649556ac3ca..a2351f34c8b2 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -62,9 +62,11 @@ #define GPIO_EDGE_MASK_MV78200_OFF(cpu) ((cpu) ? 0x30 : 0x18) #define GPIO_LEVEL_MASK_MV78200_OFF(cpu) ((cpu) ? 0x34 : 0x1C) -/* The Armada XP has per-CPU registers for interrupt cause, interrupt +/* + * The Armada XP has per-CPU registers for interrupt cause, interrupt * mask and interrupt level mask. Those are relative to the - * percpu_membase. */ + * percpu_membase. + */ #define GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu) ((cpu) * 0x4) #define GPIO_EDGE_MASK_ARMADAXP_OFF(cpu) (0x10 + (cpu) * 0x4) #define GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu) (0x20 + (cpu) * 0x4) @@ -239,8 +241,10 @@ static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin) int ret; u32 u; - /* Check with the pinctrl driver whether this pin is usable as - * an input GPIO */ + /* + * Check with the pinctrl driver whether this pin is usable as + * an input GPIO + */ ret = pinctrl_gpio_direction_input(chip->base + pin); if (ret) return ret; @@ -262,8 +266,10 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin, int ret; u32 u; - /* Check with the pinctrl driver whether this pin is usable as - * an output GPIO */ + /* + * Check with the pinctrl driver whether this pin is usable as + * an output GPIO + */ ret = pinctrl_gpio_direction_output(chip->base + pin); if (ret) return ret; @@ -712,8 +718,10 @@ static int mvebu_gpio_probe(struct platform_device *pdev) if (IS_ERR(mvchip->membase)) return PTR_ERR(mvchip->membase); - /* The Armada XP has a second range of registers for the - * per-CPU registers */ + /* + * The Armada XP has a second range of registers for the + * per-CPU registers + */ if (soc_variant == MVEBU_GPIO_SOC_VARIANT_ARMADAXP) { res = platform_get_resource(pdev, IORESOURCE_MEM, 1); mvchip->percpu_membase = devm_ioremap_resource(&pdev->dev, From 899c37edfedbe1a732ecb7619748f9839227ede5 Mon Sep 17 00:00:00 2001 From: Ralph Sennhauser Date: Thu, 16 Mar 2017 07:33:57 +0100 Subject: [PATCH 35/77] gpio: mvebu: start multiline block comments with blank line While this isn't an issue according to checkpatch two styles are used. Add a blank line to the block comments missing a blank line at the start so multiline block comments look the same across the file. Signed-off-by: Ralph Sennhauser Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mvebu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index a2351f34c8b2..80b1d5206605 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -788,7 +788,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev) goto err_domain; } - /* NOTE: The common accessors cannot be used because of the percpu + /* + * NOTE: The common accessors cannot be used because of the percpu * access to the mask registers */ gc = irq_get_domain_generic_chip(mvchip->domain, 0); @@ -809,7 +810,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev) ct->handler = handle_edge_irq; ct->chip.name = mvchip->chip.label; - /* Setup the interrupt handlers. Each chip can have up to 4 + /* + * Setup the interrupt handlers. Each chip can have up to 4 * interrupt handlers, with each handler dealing with 8 GPIO * pins. */ From d276de70d2e43c71827d8a253cb72a8b3d012e67 Mon Sep 17 00:00:00 2001 From: Ralph Sennhauser Date: Thu, 16 Mar 2017 07:33:58 +0100 Subject: [PATCH 36/77] gpio: mvebu: checkpatch: unsigned int fixes Use unsigned int instead of plain unsigned as reported by checkpatch. Signed-off-by: Ralph Sennhauser Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mvebu.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 80b1d5206605..a9522f4c1ebd 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -187,7 +187,7 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip) * Functions implementing the gpio_chip methods */ -static void mvebu_gpio_set(struct gpio_chip *chip, unsigned pin, int value) +static void mvebu_gpio_set(struct gpio_chip *chip, unsigned int pin, int value) { struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip); unsigned long flags; @@ -203,7 +203,7 @@ static void mvebu_gpio_set(struct gpio_chip *chip, unsigned pin, int value) spin_unlock_irqrestore(&mvchip->lock, flags); } -static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin) +static int mvebu_gpio_get(struct gpio_chip *chip, unsigned int pin) { struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip); u32 u; @@ -218,7 +218,8 @@ static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin) return (u >> pin) & 1; } -static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value) +static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned int pin, + int value) { struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip); unsigned long flags; @@ -234,7 +235,7 @@ static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value) spin_unlock_irqrestore(&mvchip->lock, flags); } -static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin) +static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned int pin) { struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip); unsigned long flags; @@ -258,7 +259,7 @@ static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin) return 0; } -static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin, +static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned int pin, int value) { struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip); @@ -286,7 +287,7 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin, return 0; } -static int mvebu_gpio_to_irq(struct gpio_chip *chip, unsigned pin) +static int mvebu_gpio_to_irq(struct gpio_chip *chip, unsigned int pin) { struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip); return irq_create_mapping(mvchip->domain, pin); From 163ad364cc8d77236f68acff6ab3c23ff96b1a36 Mon Sep 17 00:00:00 2001 From: Ralph Sennhauser Date: Thu, 16 Mar 2017 07:33:59 +0100 Subject: [PATCH 37/77] gpio: mvebu: checkpatch: whitespace fixes Fix whitespace errors reported by checkpatch. Signed-off-by: Ralph Sennhauser Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mvebu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index a9522f4c1ebd..1933e6394919 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -290,6 +290,7 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned int pin, static int mvebu_gpio_to_irq(struct gpio_chip *chip, unsigned int pin) { struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip); + return irq_create_mapping(mvchip->domain, pin); } From f4c240ca4b15af938d9043b93826201dd8bdf0fb Mon Sep 17 00:00:00 2001 From: Ralph Sennhauser Date: Thu, 16 Mar 2017 07:34:00 +0100 Subject: [PATCH 38/77] gpio: mvebu: extra whitespace fixes Fix whitespace errors missed by checkpatch. Signed-off-by: Ralph Sennhauser Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mvebu.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 1933e6394919..d9aa77b70c99 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -87,12 +87,12 @@ struct mvebu_gpio_chip { int soc_variant; /* Used to preserve GPIO registers across suspend/resume */ - u32 out_reg; - u32 io_conf_reg; - u32 blink_en_reg; - u32 in_pol_reg; - u32 edge_mask_regs[4]; - u32 level_mask_regs[4]; + u32 out_reg; + u32 io_conf_reg; + u32 blink_en_reg; + u32 in_pol_reg; + u32 edge_mask_regs[4]; + u32 level_mask_regs[4]; }; /* @@ -186,7 +186,6 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip) /* * Functions implementing the gpio_chip methods */ - static void mvebu_gpio_set(struct gpio_chip *chip, unsigned int pin, int value) { struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip); From f07708c43b37842fcc28faf2404a78c085aab140 Mon Sep 17 00:00:00 2001 From: Ralph Sennhauser Date: Thu, 16 Mar 2017 07:34:01 +0100 Subject: [PATCH 39/77] gpio: mvebu: let the compiler inline A modern compiler should know better when to inline, so drop the inline keywords. Signed-off-by: Ralph Sennhauser Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mvebu.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index d9aa77b70c99..029f43cc4943 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -99,35 +99,32 @@ struct mvebu_gpio_chip { * Functions returning addresses of individual registers for a given * GPIO controller. */ -static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip) +static void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip) { return mvchip->membase + GPIO_OUT_OFF; } -static inline void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip) +static void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip) { return mvchip->membase + GPIO_BLINK_EN_OFF; } -static inline void __iomem * -mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip) +static void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip) { return mvchip->membase + GPIO_IO_CONF_OFF; } -static inline void __iomem *mvebu_gpioreg_in_pol(struct mvebu_gpio_chip *mvchip) +static void __iomem *mvebu_gpioreg_in_pol(struct mvebu_gpio_chip *mvchip) { return mvchip->membase + GPIO_IN_POL_OFF; } -static inline void __iomem * -mvebu_gpioreg_data_in(struct mvebu_gpio_chip *mvchip) +static void __iomem *mvebu_gpioreg_data_in(struct mvebu_gpio_chip *mvchip) { return mvchip->membase + GPIO_DATA_IN_OFF; } -static inline void __iomem * -mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip) +static void __iomem *mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip) { int cpu; @@ -144,8 +141,7 @@ mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip) } } -static inline void __iomem * -mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvchip) +static void __iomem *mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvchip) { int cpu; From 32d9617234f53d7fef18ec94d9bcfc805bb9df16 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 13 Mar 2017 00:28:13 +0100 Subject: [PATCH 40/77] gpio: gemini: augment DT bindings The DT bindings assumed that this IP block was coming from Cortina Systems, which turns out not to be true. It is a standard IP block from Faraday Technology and also used in the Moxa moxart SoC. We augment the bindings to cover all existing parts and rename it after the IP block. This involves deleting the old Moxa bindings that now are contained in this binding. Cc: devicetree@vger.kernel.org Cc: Jonas Jensen Acked-by: Rob Herring Signed-off-by: Linus Walleij --- ...,gemini-gpio.txt => faraday,ftgpio010.txt} | 9 ++++++--- .../bindings/gpio/moxa,moxart-gpio.txt | 19 ------------------- 2 files changed, 6 insertions(+), 22 deletions(-) rename Documentation/devicetree/bindings/gpio/{cortina,gemini-gpio.txt => faraday,ftgpio010.txt} (70%) delete mode 100644 Documentation/devicetree/bindings/gpio/moxa,moxart-gpio.txt diff --git a/Documentation/devicetree/bindings/gpio/cortina,gemini-gpio.txt b/Documentation/devicetree/bindings/gpio/faraday,ftgpio010.txt similarity index 70% rename from Documentation/devicetree/bindings/gpio/cortina,gemini-gpio.txt rename to Documentation/devicetree/bindings/gpio/faraday,ftgpio010.txt index 5c9246c054e5..d04236558619 100644 --- a/Documentation/devicetree/bindings/gpio/cortina,gemini-gpio.txt +++ b/Documentation/devicetree/bindings/gpio/faraday,ftgpio010.txt @@ -1,8 +1,11 @@ -Cortina Systems Gemini GPIO Controller +Faraday Technology FTGPIO010 GPIO Controller Required properties: -- compatible : Must be "cortina,gemini-gpio" +- compatible : Should be one of + "cortina,gemini-gpio", "faraday,ftgpio010" + "moxa,moxart-gpio", "faraday,ftgpio010" + "faraday,ftgpio010" - reg : Should contain registers location and length - interrupts : Should contain the interrupt line for the GPIO block - gpio-controller : marks this as a GPIO controller @@ -14,7 +17,7 @@ Required properties: Example: gpio@4d000000 { - compatible = "cortina,gemini-gpio"; + compatible = "cortina,gemini-gpio", "faraday,ftgpio010"; reg = <0x4d000000 0x100>; interrupts = <22 IRQ_TYPE_LEVEL_HIGH>; gpio-controller; diff --git a/Documentation/devicetree/bindings/gpio/moxa,moxart-gpio.txt b/Documentation/devicetree/bindings/gpio/moxa,moxart-gpio.txt deleted file mode 100644 index f8e8f185a3db..000000000000 --- a/Documentation/devicetree/bindings/gpio/moxa,moxart-gpio.txt +++ /dev/null @@ -1,19 +0,0 @@ -MOXA ART GPIO Controller - -Required properties: - -- #gpio-cells : Should be 2, The first cell is the pin number, - the second cell is used to specify polarity: - 0 = active high - 1 = active low -- compatible : Must be "moxa,moxart-gpio" -- reg : Should contain registers location and length - -Example: - - gpio: gpio@98700000 { - gpio-controller; - #gpio-cells = <2>; - compatible = "moxa,moxart-gpio"; - reg = <0x98700000 0xC>; - }; From 9d3a15aaaec41252ad7c6592305264e52a801be7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 13 Mar 2017 00:28:16 +0100 Subject: [PATCH 41/77] gpio: gemini: rename to match Faraday IP The Gemini driver is actually a driver for the Faraday Technology FTGPIO010 IP block. We rename the driver and the Kconfig symbol and put in a a new compatible string for the Moxa ART SoC that is also using this IP block. Tested-by: Jonas Jensen Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 7 +- drivers/gpio/Makefile | 2 +- .../gpio/{gpio-gemini.c => gpio-ftgpio010.c} | 72 ++++++++++--------- 3 files changed, 44 insertions(+), 37 deletions(-) rename drivers/gpio/{gpio-gemini.c => gpio-ftgpio010.c} (73%) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index a386240c5921..2c3f6390b44b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -204,14 +204,15 @@ config GPIO_GE_FPGA and write pin state) for GPIO implemented in a number of GE single board computers. -config GPIO_GEMINI - bool "Gemini GPIO" +config GPIO_FTGPIO010 + bool "Faraday FTGPIO010 GPIO" depends on ARCH_GEMINI depends on OF_GPIO select GPIO_GENERIC select GPIOLIB_IRQCHIP help - Support for common GPIOs found in Cortina systems Gemini platforms. + Support for common GPIOs from the Faraday FTGPIO010 IP core, found in + Cortina systems Gemini platforms, Moxa ART and others. config GPIO_GENERIC_PLATFORM tristate "Generic memory-mapped GPIO controller support (MMIO platform device)" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index becb96c724fe..4b904fec8273 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -48,8 +48,8 @@ obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o obj-$(CONFIG_GPIO_ETRAXFS) += gpio-etraxfs.o obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o +obj-$(CONFIG_GPIO_FTGPIO010) += gpio-ftgpio010.o obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o -obj-$(CONFIG_GPIO_GEMINI) += gpio-gemini.o obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o diff --git a/drivers/gpio/gpio-gemini.c b/drivers/gpio/gpio-ftgpio010.c similarity index 73% rename from drivers/gpio/gpio-gemini.c rename to drivers/gpio/gpio-ftgpio010.c index 962485163b7f..e9386f8b67f5 100644 --- a/drivers/gpio/gpio-gemini.c +++ b/drivers/gpio/gpio-ftgpio010.c @@ -1,5 +1,5 @@ /* - * Gemini gpiochip and interrupt routines + * Faraday Technolog FTGPIO010 gpiochip and interrupt routines * Copyright (C) 2017 Linus Walleij * * Based on arch/arm/mach-gemini/gpio.c: @@ -35,28 +35,28 @@ #define GPIO_DEBOUNCE_PRESCALE 0x44 /** - * struct gemini_gpio - Gemini GPIO state container + * struct ftgpio_gpio - Gemini GPIO state container * @dev: containing device for this instance * @gc: gpiochip for this instance */ -struct gemini_gpio { +struct ftgpio_gpio { struct device *dev; struct gpio_chip gc; void __iomem *base; }; -static void gemini_gpio_ack_irq(struct irq_data *d) +static void ftgpio_gpio_ack_irq(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct gemini_gpio *g = gpiochip_get_data(gc); + struct ftgpio_gpio *g = gpiochip_get_data(gc); writel(BIT(irqd_to_hwirq(d)), g->base + GPIO_INT_CLR); } -static void gemini_gpio_mask_irq(struct irq_data *d) +static void ftgpio_gpio_mask_irq(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct gemini_gpio *g = gpiochip_get_data(gc); + struct ftgpio_gpio *g = gpiochip_get_data(gc); u32 val; val = readl(g->base + GPIO_INT_EN); @@ -64,10 +64,10 @@ static void gemini_gpio_mask_irq(struct irq_data *d) writel(val, g->base + GPIO_INT_EN); } -static void gemini_gpio_unmask_irq(struct irq_data *d) +static void ftgpio_gpio_unmask_irq(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct gemini_gpio *g = gpiochip_get_data(gc); + struct ftgpio_gpio *g = gpiochip_get_data(gc); u32 val; val = readl(g->base + GPIO_INT_EN); @@ -75,10 +75,10 @@ static void gemini_gpio_unmask_irq(struct irq_data *d) writel(val, g->base + GPIO_INT_EN); } -static int gemini_gpio_set_irq_type(struct irq_data *d, unsigned int type) +static int ftgpio_gpio_set_irq_type(struct irq_data *d, unsigned int type) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); - struct gemini_gpio *g = gpiochip_get_data(gc); + struct ftgpio_gpio *g = gpiochip_get_data(gc); u32 mask = BIT(irqd_to_hwirq(d)); u32 reg_both, reg_level, reg_type; @@ -123,23 +123,23 @@ static int gemini_gpio_set_irq_type(struct irq_data *d, unsigned int type) writel(reg_level, g->base + GPIO_INT_LEVEL); writel(reg_both, g->base + GPIO_INT_BOTH_EDGE); - gemini_gpio_ack_irq(d); + ftgpio_gpio_ack_irq(d); return 0; } -static struct irq_chip gemini_gpio_irqchip = { - .name = "GPIO", - .irq_ack = gemini_gpio_ack_irq, - .irq_mask = gemini_gpio_mask_irq, - .irq_unmask = gemini_gpio_unmask_irq, - .irq_set_type = gemini_gpio_set_irq_type, +static struct irq_chip ftgpio_gpio_irqchip = { + .name = "FTGPIO010", + .irq_ack = ftgpio_gpio_ack_irq, + .irq_mask = ftgpio_gpio_mask_irq, + .irq_unmask = ftgpio_gpio_unmask_irq, + .irq_set_type = ftgpio_gpio_set_irq_type, }; -static void gemini_gpio_irq_handler(struct irq_desc *desc) +static void ftgpio_gpio_irq_handler(struct irq_desc *desc) { struct gpio_chip *gc = irq_desc_get_handler_data(desc); - struct gemini_gpio *g = gpiochip_get_data(gc); + struct ftgpio_gpio *g = gpiochip_get_data(gc); struct irq_chip *irqchip = irq_desc_get_chip(desc); int offset; unsigned long stat; @@ -155,11 +155,11 @@ static void gemini_gpio_irq_handler(struct irq_desc *desc) chained_irq_exit(irqchip, desc); } -static int gemini_gpio_probe(struct platform_device *pdev) +static int ftgpio_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct resource *res; - struct gemini_gpio *g; + struct ftgpio_gpio *g; int irq; int ret; @@ -189,7 +189,7 @@ static int gemini_gpio_probe(struct platform_device *pdev) dev_err(dev, "unable to init generic GPIO\n"); return ret; } - g->gc.label = "Gemini"; + g->gc.label = "FTGPIO010"; g->gc.base = -1; g->gc.parent = dev; g->gc.owner = THIS_MODULE; @@ -204,33 +204,39 @@ static int gemini_gpio_probe(struct platform_device *pdev) writel(0x0, g->base + GPIO_INT_MASK); writel(~0x0, g->base + GPIO_INT_CLR); - ret = gpiochip_irqchip_add(&g->gc, &gemini_gpio_irqchip, + ret = gpiochip_irqchip_add(&g->gc, &ftgpio_gpio_irqchip, 0, handle_bad_irq, IRQ_TYPE_NONE); if (ret) { dev_info(dev, "could not add irqchip\n"); return ret; } - gpiochip_set_chained_irqchip(&g->gc, &gemini_gpio_irqchip, - irq, gemini_gpio_irq_handler); + gpiochip_set_chained_irqchip(&g->gc, &ftgpio_gpio_irqchip, + irq, ftgpio_gpio_irq_handler); - dev_info(dev, "Gemini GPIO @%p registered\n", g->base); + dev_info(dev, "FTGPIO010 @%p registered\n", g->base); return 0; } -static const struct of_device_id gemini_gpio_of_match[] = { +static const struct of_device_id ftgpio_gpio_of_match[] = { { .compatible = "cortina,gemini-gpio", }, + { + .compatible = "moxa,moxart-gpio", + }, + { + .compatible = "faraday,ftgpio010", + }, {}, }; -static struct platform_driver gemini_gpio_driver = { +static struct platform_driver ftgpio_gpio_driver = { .driver = { - .name = "gemini-gpio", - .of_match_table = of_match_ptr(gemini_gpio_of_match), + .name = "ftgpio010-gpio", + .of_match_table = of_match_ptr(ftgpio_gpio_of_match), }, - .probe = gemini_gpio_probe, + .probe = ftgpio_gpio_probe, }; -builtin_platform_driver(gemini_gpio_driver); +builtin_platform_driver(ftgpio_gpio_driver); From d8307c09206b35a9526bfdf076c9f516c0b5e6f1 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 13 Mar 2017 00:28:17 +0100 Subject: [PATCH 42/77] gpio: moxart: Switch to using the FTGPIO010 driver This just deletes the Moxa ART driver and replaces it with the more versatile Faraday FTGPIO010 driver. Make this default on for ARCH_GEMINI and ARCH_MOXART so we do not get Kconfig glitches. Tested-by: Jonas Jensen Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 10 +---- drivers/gpio/Makefile | 1 - drivers/gpio/gpio-moxart.c | 84 -------------------------------------- 3 files changed, 1 insertion(+), 94 deletions(-) delete mode 100644 drivers/gpio/gpio-moxart.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 2c3f6390b44b..d6e3cfd54848 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -206,10 +206,10 @@ config GPIO_GE_FPGA config GPIO_FTGPIO010 bool "Faraday FTGPIO010 GPIO" - depends on ARCH_GEMINI depends on OF_GPIO select GPIO_GENERIC select GPIOLIB_IRQCHIP + default (ARCH_GEMINI || ARCH_MOXART) help Support for common GPIOs from the Faraday FTGPIO010 IP core, found in Cortina systems Gemini platforms, Moxa ART and others. @@ -309,14 +309,6 @@ config GPIO_MOCKUP tools/testing/selftests/gpio/gpio-mockup.sh. Reference the usage in it. -config GPIO_MOXART - bool "MOXART GPIO support" - depends on ARCH_MOXART || COMPILE_TEST - select GPIO_GENERIC - help - Select this option to enable GPIO driver for - MOXA ART SoC devices. - config GPIO_MPC5200 def_bool y depends on PPC_MPC52xx diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 4b904fec8273..bd995dc2a84a 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -80,7 +80,6 @@ obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o -obj-$(CONFIG_GPIO_MOXART) += gpio-moxart.o obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c deleted file mode 100644 index d58d38906ba6..000000000000 --- a/drivers/gpio/gpio-moxart.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * MOXA ART SoCs GPIO driver. - * - * Copyright (C) 2013 Jonas Jensen - * - * Jonas Jensen - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define GPIO_DATA_OUT 0x00 -#define GPIO_DATA_IN 0x04 -#define GPIO_PIN_DIRECTION 0x08 - -static int moxart_gpio_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct resource *res; - struct gpio_chip *gc; - void __iomem *base; - int ret; - - gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); - if (!gc) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(dev, res); - if (IS_ERR(base)) - return PTR_ERR(base); - - ret = bgpio_init(gc, dev, 4, base + GPIO_DATA_IN, - base + GPIO_DATA_OUT, NULL, - base + GPIO_PIN_DIRECTION, NULL, - BGPIOF_READ_OUTPUT_REG_SET); - if (ret) { - dev_err(&pdev->dev, "bgpio_init failed\n"); - return ret; - } - - gc->label = "moxart-gpio"; - gc->request = gpiochip_generic_request; - gc->free = gpiochip_generic_free; - gc->base = 0; - gc->owner = THIS_MODULE; - - ret = devm_gpiochip_add_data(dev, gc, NULL); - if (ret) { - dev_err(dev, "%s: gpiochip_add failed\n", - dev->of_node->full_name); - return ret; - } - - return ret; -} - -static const struct of_device_id moxart_gpio_match[] = { - { .compatible = "moxa,moxart-gpio" }, - { } -}; - -static struct platform_driver moxart_gpio_driver = { - .driver = { - .name = "moxart-gpio", - .of_match_table = moxart_gpio_match, - }, - .probe = moxart_gpio_probe, -}; -builtin_platform_driver(moxart_gpio_driver); From b8c90199b51aa59da06e1a82a22ba11e69bd8150 Mon Sep 17 00:00:00 2001 From: Nathan Sullivan Date: Tue, 14 Mar 2017 11:13:22 -0500 Subject: [PATCH 43/77] gpio: mmio: add support for NI 169445 NAND GPIO The GPIO-based NAND controller on National Instruments 169445 hardware exposes a set of simple lines for the control signals. Signed-off-by: Nathan Sullivan Signed-off-by: Linus Walleij --- .../bindings/gpio/ni,169445-nand-gpio.txt | 38 +++++++++++++++++++ drivers/gpio/gpio-mmio.c | 1 + 2 files changed, 39 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/ni,169445-nand-gpio.txt diff --git a/Documentation/devicetree/bindings/gpio/ni,169445-nand-gpio.txt b/Documentation/devicetree/bindings/gpio/ni,169445-nand-gpio.txt new file mode 100644 index 000000000000..ca2f8c745a27 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/ni,169445-nand-gpio.txt @@ -0,0 +1,38 @@ +Bindings for the National Instruments 169445 GPIO NAND controller + +The 169445 GPIO NAND controller has two memory mapped GPIO registers, one +for input (the ready signal) and one for output (control signals). It is +intended to be used with the GPIO NAND driver. + +Required properties: + - compatible: should be "ni,169445-nand-gpio" + - reg-names: must contain + "dat" - data register + - reg: address + size pairs describing the GPIO register sets; + order must correspond with the order of entries in reg-names + - #gpio-cells: must be set to 2. The first cell is the pin number and + the second cell is used to specify the gpio polarity: + 0 = active high + 1 = active low + - gpio-controller: Marks the device node as a gpio controller. + +Optional properties: + - no-output: disables driving output on the pins + +Examples: + gpio1: nand-gpio-out@1f300010 { + compatible = "ni,169445-nand-gpio"; + reg = <0x1f300010 0x4>; + reg-names = "dat"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio2: nand-gpio-in@1f300014 { + compatible = "ni,169445-nand-gpio"; + reg = <0x1f300014 0x4>; + reg-names = "dat"; + gpio-controller; + #gpio-cells = <2>; + no-output; + }; diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c index d7d03ad052d0..f7da40e46c55 100644 --- a/drivers/gpio/gpio-mmio.c +++ b/drivers/gpio/gpio-mmio.c @@ -575,6 +575,7 @@ static void __iomem *bgpio_map(struct platform_device *pdev, static const struct of_device_id bgpio_of_match[] = { { .compatible = "brcm,bcm6345-gpio" }, { .compatible = "wd,mbl-gpio" }, + { .compatible = "ni,169445-nand-gpio" }, { } }; MODULE_DEVICE_TABLE(of, bgpio_of_match); From d2cabc4a23f8dea6caf51279777d511c7d8a5045 Mon Sep 17 00:00:00 2001 From: Ralph Sennhauser Date: Fri, 17 Mar 2017 18:44:06 +0100 Subject: [PATCH 44/77] gpio: mvebu: use BIT macro instead of bit shifting Use the BIT macro instead of explicitly shifting bits for some added clarity. Signed-off-by: Ralph Sennhauser Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mvebu.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 029f43cc4943..fae4db684398 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -45,6 +45,7 @@ #include #include #include +#include /* * GPIO unit register offsets. @@ -191,9 +192,9 @@ static void mvebu_gpio_set(struct gpio_chip *chip, unsigned int pin, int value) spin_lock_irqsave(&mvchip->lock, flags); u = readl_relaxed(mvebu_gpioreg_out(mvchip)); if (value) - u |= 1 << pin; + u |= BIT(pin); else - u &= ~(1 << pin); + u &= ~BIT(pin); writel_relaxed(u, mvebu_gpioreg_out(mvchip)); spin_unlock_irqrestore(&mvchip->lock, flags); } @@ -203,7 +204,7 @@ static int mvebu_gpio_get(struct gpio_chip *chip, unsigned int pin) struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip); u32 u; - if (readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin)) { + if (readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & BIT(pin)) { u = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) ^ readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); } else { @@ -223,9 +224,9 @@ static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned int pin, spin_lock_irqsave(&mvchip->lock, flags); u = readl_relaxed(mvebu_gpioreg_blink(mvchip)); if (value) - u |= 1 << pin; + u |= BIT(pin); else - u &= ~(1 << pin); + u &= ~BIT(pin); writel_relaxed(u, mvebu_gpioreg_blink(mvchip)); spin_unlock_irqrestore(&mvchip->lock, flags); } @@ -247,7 +248,7 @@ static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned int pin) spin_lock_irqsave(&mvchip->lock, flags); u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)); - u |= 1 << pin; + u |= BIT(pin); writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip)); spin_unlock_irqrestore(&mvchip->lock, flags); @@ -275,7 +276,7 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned int pin, spin_lock_irqsave(&mvchip->lock, flags); u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)); - u &= ~(1 << pin); + u &= ~BIT(pin); writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip)); spin_unlock_irqrestore(&mvchip->lock, flags); @@ -392,7 +393,7 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type) pin = d->hwirq; - u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin); + u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & BIT(pin); if (!u) return -EINVAL; @@ -412,13 +413,13 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type) case IRQ_TYPE_EDGE_RISING: case IRQ_TYPE_LEVEL_HIGH: u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); - u &= ~(1 << pin); + u &= ~BIT(pin); writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip)); break; case IRQ_TYPE_EDGE_FALLING: case IRQ_TYPE_LEVEL_LOW: u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); - u |= 1 << pin; + u |= BIT(pin); writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip)); break; case IRQ_TYPE_EDGE_BOTH: { @@ -431,10 +432,10 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type) * set initial polarity based on current input level */ u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); - if (v & (1 << pin)) - u |= 1 << pin; /* falling */ + if (v & BIT(pin)) + u |= BIT(pin); /* falling */ else - u &= ~(1 << pin); /* rising */ + u &= ~BIT(pin); /* rising */ writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip)); break; } @@ -464,7 +465,7 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc) irq = irq_find_mapping(mvchip->domain, i); - if (!(cause & (1 << i))) + if (!(cause & BIT(i))) continue; type = irq_get_trigger_type(irq); @@ -473,7 +474,7 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc) u32 polarity; polarity = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); - polarity ^= 1 << i; + polarity ^= BIT(i); writel_relaxed(polarity, mvebu_gpioreg_in_pol(mvchip)); } @@ -510,7 +511,7 @@ static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) if (!label) continue; - msk = 1 << i; + msk = BIT(i); is_out = !(io_conf & msk); seq_printf(s, " gpio-%-3d (%-20.20s)", chip->base + i, label); From 66e57192319bdd5cc469288267764c6353c4f621 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 22 Mar 2017 16:11:11 +0200 Subject: [PATCH 45/77] gpio: pca953x: Introduce a long awaited ->get_direction() Introduce ->get_direction() callback for the driver. Signed-off-by: Andy Shevchenko [Removed use of GPIOF_DIR* flags] Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index d44232aadb6c..782d9adb55b9 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -363,6 +363,21 @@ exit: mutex_unlock(&chip->i2c_lock); } +static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off) +{ + struct pca953x_chip *chip = gpiochip_get_data(gc); + u32 reg_val; + int ret; + + mutex_lock(&chip->i2c_lock); + ret = pca953x_read_single(chip, chip->regs->direction, ®_val, off); + mutex_unlock(&chip->i2c_lock); + if (ret < 0) + return ret; + + return !!(reg_val & (1u << (off % BANK_SZ))); +} + static void pca953x_gpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, unsigned long *bits) { @@ -408,6 +423,7 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) gc->direction_output = pca953x_gpio_direction_output; gc->get = pca953x_gpio_get_value; gc->set = pca953x_gpio_set_value; + gc->get_direction = pca953x_gpio_get_direction; gc->set_multiple = pca953x_gpio_set_multiple; gc->can_sleep = true; From b413d7a01c1ade52864a1923a3b329a2281bf69e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 22 Mar 2017 16:11:12 +0200 Subject: [PATCH 46/77] gpio: pca953x: Sort headers alphabetically For sake of better maintenance sort the headers by alphabetical order. Signed-off-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 782d9adb55b9..51c9d9cfd742 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -11,18 +11,19 @@ * the Free Software Foundation; version 2 of the License. */ -#include -#include +#include #include #include -#include #include -#include -#include -#include +#include +#include +#include #include -#include +#include #include +#include + +#include #define PCA953X_INPUT 0 #define PCA953X_OUTPUT 1 From 96530b3777a7852222ca5ffa5eb20afed1be13bf Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 22 Mar 2017 16:11:13 +0200 Subject: [PATCH 47/77] gpio: pca953x: Expand comment for "reset" GPIO in ACPI case GPIO ACPI library is going to be stricter about resources, thus, expand comment regarding "reset" GPIO resource in this driver to clarify its usage in ACPI case. Signed-off-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 51c9d9cfd742..b9373785ccf5 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -777,7 +777,13 @@ static int pca953x_probe(struct i2c_client *client, chip->gpio_start = -1; irq_base = 0; - /* See if we need to de-assert a reset pin */ + /* + * See if we need to de-assert a reset pin. + * + * There is no known ACPI-enabled platforms that are + * using "reset" GPIO. Otherwise any of those platform + * must use _DSD method with corresponding property. + */ reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(reset_gpio)) From 4a56e413b50c11df35e6c6909312ce7418848b37 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 22 Mar 2017 16:08:07 +0200 Subject: [PATCH 48/77] usb: dwc3: pci: Switch to devm_acpi_dev_add_driver_gpios() Switch to use managed variant of acpi_dev_add_driver_gpios() to simplify error path and fix potentially wrong assignment if ->probe() fails. While here, add a debug message in case assignment fails to allow user see the cause of a potential issue. Signed-off-by: Andy Shevchenko Acked-by: Felipe Balbi Signed-off-by: Linus Walleij --- drivers/usb/dwc3/dwc3-pci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index cce0a220b6b0..a15ec71d0423 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -125,8 +125,10 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc) if (pdev->device == PCI_DEVICE_ID_INTEL_BYT) { struct gpio_desc *gpio; - acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev), + ret = devm_acpi_dev_add_driver_gpios(&pdev->dev, acpi_dwc3_byt_gpios); + if (ret) + dev_dbg(&pdev->dev, "failed to add mapping table\n"); /* * These GPIOs will turn on the USB2 PHY. Note that we have to @@ -242,7 +244,6 @@ static void dwc3_pci_remove(struct pci_dev *pci) device_init_wakeup(&pci->dev, false); pm_runtime_get(&pci->dev); - acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pci->dev)); platform_device_unregister(dwc->dwc3); } From 7477e137dcfdf259123815d0e0b02738840ea71e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 23 Mar 2017 14:56:32 +0200 Subject: [PATCH 49/77] gpio: merrifield: Don't use GPIOF_DIR_IN / GPIOF_DIR_OUT The mentioned flags are dedicated solely for consumer API. Replace them by explicit values. Signed-off-by: Andy Shevchenko [Made a !bang clamp to (0,1) instead of infix ? operator] Signed-off-by: Linus Walleij --- drivers/gpio/gpio-merrifield.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c index f40088d268c1..9dbdc3672f5e 100644 --- a/drivers/gpio/gpio-merrifield.c +++ b/drivers/gpio/gpio-merrifield.c @@ -166,7 +166,7 @@ static int mrfld_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) { void __iomem *gpdr = gpio_reg(chip, offset, GPDR); - return (readl(gpdr) & BIT(offset % 32)) ? GPIOF_DIR_OUT : GPIOF_DIR_IN; + return !(readl(gpdr) & BIT(offset % 32)); } static int mrfld_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset, From 9dd4819ed58a7f1702d5ba737507d0fef96e68c8 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 31 Aug 2016 08:49:44 +0100 Subject: [PATCH 50/77] gpio: sa1100: use sa11x0_gpio_set_wake() Use sa11x0_gpio_set_wake() to set the PWER register, as provided by Dmitry some time back. Signed-off-by: Russell King Signed-off-by: Linus Walleij --- drivers/gpio/gpio-sa1100.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-sa1100.c b/drivers/gpio/gpio-sa1100.c index 8d8ee0ebf14c..fb9d52a57d78 100644 --- a/drivers/gpio/gpio-sa1100.c +++ b/drivers/gpio/gpio-sa1100.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -73,6 +74,7 @@ static struct gpio_chip sa1100_gpio_chip = { static int GPIO_IRQ_rising_edge; static int GPIO_IRQ_falling_edge; static int GPIO_IRQ_mask; +static int GPIO_IRQ_wake; static int sa1100_gpio_type(struct irq_data *d, unsigned int type) { @@ -131,11 +133,14 @@ static void sa1100_gpio_unmask(struct irq_data *d) static int sa1100_gpio_wake(struct irq_data *d, unsigned int on) { - if (on) - PWER |= BIT(d->hwirq); - else - PWER &= ~BIT(d->hwirq); - return 0; + int ret = sa11x0_gpio_set_wake(d->hwirq, on); + if (!ret) { + if (on) + GPIO_IRQ_wake |= BIT(d->hwirq); + else + GPIO_IRQ_wake &= ~BIT(d->hwirq); + } + return ret; } /* @@ -201,8 +206,8 @@ static int sa1100_gpio_suspend(void) /* * Set the appropriate edges for wakeup. */ - GRER = PWER & GPIO_IRQ_rising_edge; - GFER = PWER & GPIO_IRQ_falling_edge; + GRER = GPIO_IRQ_wake & GPIO_IRQ_rising_edge; + GFER = GPIO_IRQ_wake & GPIO_IRQ_falling_edge; /* * Clear any pending GPIO interrupts. From 07242b248119a9388a67975aa7fae7c23afc7a07 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 31 Aug 2016 08:49:44 +0100 Subject: [PATCH 51/77] gpio: sa1100: convert to use IO accessors Use IO accessors to access the SA1100 registers rather than accessing them directly. Signed-off-by: Russell King Signed-off-by: Linus Walleij --- drivers/gpio/gpio-sa1100.c | 201 +++++++++++++++++++++++-------------- 1 file changed, 125 insertions(+), 76 deletions(-) diff --git a/drivers/gpio/gpio-sa1100.c b/drivers/gpio/gpio-sa1100.c index fb9d52a57d78..bad0169524c9 100644 --- a/drivers/gpio/gpio-sa1100.c +++ b/drivers/gpio/gpio-sa1100.c @@ -16,54 +16,85 @@ #include #include +struct sa1100_gpio_chip { + struct gpio_chip chip; + void __iomem *membase; + int irqbase; + u32 irqmask; + u32 irqrising; + u32 irqfalling; + u32 irqwake; +}; + +#define sa1100_gpio_chip(x) container_of(x, struct sa1100_gpio_chip, chip) + +enum { + R_GPLR = 0x00, + R_GPDR = 0x04, + R_GPSR = 0x08, + R_GPCR = 0x0c, + R_GRER = 0x10, + R_GFER = 0x14, + R_GEDR = 0x18, + R_GAFR = 0x1c, +}; + static int sa1100_gpio_get(struct gpio_chip *chip, unsigned offset) { - return !!(GPLR & GPIO_GPIO(offset)); + return readl_relaxed(sa1100_gpio_chip(chip)->membase + R_GPLR) & + BIT(offset); } static void sa1100_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - if (value) - GPSR = GPIO_GPIO(offset); - else - GPCR = GPIO_GPIO(offset); + int reg = value ? R_GPSR : R_GPCR; + + writel_relaxed(BIT(offset), sa1100_gpio_chip(chip)->membase + reg); } static int sa1100_direction_input(struct gpio_chip *chip, unsigned offset) { + void __iomem *gpdr = sa1100_gpio_chip(chip)->membase + R_GPDR; unsigned long flags; local_irq_save(flags); - GPDR &= ~GPIO_GPIO(offset); + writel_relaxed(readl_relaxed(gpdr) & ~BIT(offset), gpdr); local_irq_restore(flags); + return 0; } static int sa1100_direction_output(struct gpio_chip *chip, unsigned offset, int value) { + void __iomem *gpdr = sa1100_gpio_chip(chip)->membase + R_GPDR; unsigned long flags; local_irq_save(flags); sa1100_gpio_set(chip, offset, value); - GPDR |= GPIO_GPIO(offset); + writel_relaxed(readl_relaxed(gpdr) | BIT(offset), gpdr); local_irq_restore(flags); + return 0; } static int sa1100_to_irq(struct gpio_chip *chip, unsigned offset) { - return IRQ_GPIO0 + offset; + return sa1100_gpio_chip(chip)->irqbase + offset; } -static struct gpio_chip sa1100_gpio_chip = { - .label = "gpio", - .direction_input = sa1100_direction_input, - .direction_output = sa1100_direction_output, - .set = sa1100_gpio_set, - .get = sa1100_gpio_get, - .to_irq = sa1100_to_irq, - .base = 0, - .ngpio = GPIO_MAX + 1, +static struct sa1100_gpio_chip sa1100_gpio_chip = { + .chip = { + .label = "gpio", + .direction_input = sa1100_direction_input, + .direction_output = sa1100_direction_output, + .set = sa1100_gpio_set, + .get = sa1100_gpio_get, + .to_irq = sa1100_to_irq, + .base = 0, + .ngpio = GPIO_MAX + 1, + }, + .membase = (void *)&GPLR, + .irqbase = IRQ_GPIO0, }; /* @@ -71,34 +102,39 @@ static struct gpio_chip sa1100_gpio_chip = { * IRQs are generated on Falling-Edge, Rising-Edge, or both. * Use this instead of directly setting GRER/GFER. */ -static int GPIO_IRQ_rising_edge; -static int GPIO_IRQ_falling_edge; -static int GPIO_IRQ_mask; -static int GPIO_IRQ_wake; +static void sa1100_update_edge_regs(struct sa1100_gpio_chip *sgc) +{ + void *base = sgc->membase; + u32 grer, gfer; + + grer = sgc->irqrising & sgc->irqmask; + gfer = sgc->irqfalling & sgc->irqmask; + + writel_relaxed(grer, base + R_GRER); + writel_relaxed(gfer, base + R_GFER); +} static int sa1100_gpio_type(struct irq_data *d, unsigned int type) { - unsigned int mask; - - mask = BIT(d->hwirq); + struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d); + unsigned int mask = BIT(d->hwirq); if (type == IRQ_TYPE_PROBE) { - if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask) + if ((sgc->irqrising | sgc->irqfalling) & mask) return 0; type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; } if (type & IRQ_TYPE_EDGE_RISING) - GPIO_IRQ_rising_edge |= mask; + sgc->irqrising |= mask; else - GPIO_IRQ_rising_edge &= ~mask; + sgc->irqrising &= ~mask; if (type & IRQ_TYPE_EDGE_FALLING) - GPIO_IRQ_falling_edge |= mask; + sgc->irqfalling |= mask; else - GPIO_IRQ_falling_edge &= ~mask; + sgc->irqfalling &= ~mask; - GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask; - GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; + sa1100_update_edge_regs(sgc); return 0; } @@ -108,37 +144,40 @@ static int sa1100_gpio_type(struct irq_data *d, unsigned int type) */ static void sa1100_gpio_ack(struct irq_data *d) { - GEDR = BIT(d->hwirq); + struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d); + + writel_relaxed(BIT(d->hwirq), sgc->membase + R_GEDR); } static void sa1100_gpio_mask(struct irq_data *d) { + struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d); unsigned int mask = BIT(d->hwirq); - GPIO_IRQ_mask &= ~mask; + sgc->irqmask &= ~mask; - GRER &= ~mask; - GFER &= ~mask; + sa1100_update_edge_regs(sgc); } static void sa1100_gpio_unmask(struct irq_data *d) { + struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d); unsigned int mask = BIT(d->hwirq); - GPIO_IRQ_mask |= mask; + sgc->irqmask |= mask; - GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask; - GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; + sa1100_update_edge_regs(sgc); } static int sa1100_gpio_wake(struct irq_data *d, unsigned int on) { + struct sa1100_gpio_chip *sgc = irq_data_get_irq_chip_data(d); int ret = sa11x0_gpio_set_wake(d->hwirq, on); if (!ret) { if (on) - GPIO_IRQ_wake |= BIT(d->hwirq); + sgc->irqwake |= BIT(d->hwirq); else - GPIO_IRQ_wake &= ~BIT(d->hwirq); + sgc->irqwake &= ~BIT(d->hwirq); } return ret; } @@ -158,8 +197,10 @@ static struct irq_chip sa1100_gpio_irq_chip = { static int sa1100_gpio_irqdomain_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq) { - irq_set_chip_and_handler(irq, &sa1100_gpio_irq_chip, - handle_edge_irq); + struct sa1100_gpio_chip *sgc = d->host_data; + + irq_set_chip_data(irq, sgc); + irq_set_chip_and_handler(irq, &sa1100_gpio_irq_chip, handle_edge_irq); irq_set_probe(irq); return 0; @@ -179,17 +220,19 @@ static struct irq_domain *sa1100_gpio_irqdomain; */ static void sa1100_gpio_handler(struct irq_desc *desc) { + struct sa1100_gpio_chip *sgc = irq_desc_get_handler_data(desc); unsigned int irq, mask; + void __iomem *gedr = sgc->membase + R_GEDR; - mask = GEDR; + mask = readl_relaxed(gedr); do { /* * clear down all currently active IRQ sources. * We will be processing them all. */ - GEDR = mask; + writel_relaxed(mask, gedr); - irq = IRQ_GPIO0; + irq = sgc->irqbase; do { if (mask & 1) generic_handle_irq(irq); @@ -197,30 +240,32 @@ static void sa1100_gpio_handler(struct irq_desc *desc) irq++; } while (mask); - mask = GEDR; + mask = readl_relaxed(gedr); } while (mask); } static int sa1100_gpio_suspend(void) { + struct sa1100_gpio_chip *sgc = &sa1100_gpio_chip; + /* * Set the appropriate edges for wakeup. */ - GRER = GPIO_IRQ_wake & GPIO_IRQ_rising_edge; - GFER = GPIO_IRQ_wake & GPIO_IRQ_falling_edge; + writel_relaxed(sgc->irqwake & sgc->irqrising, sgc->membase + R_GRER); + writel_relaxed(sgc->irqwake & sgc->irqfalling, sgc->membase + R_GFER); /* * Clear any pending GPIO interrupts. */ - GEDR = GEDR; + writel_relaxed(readl_relaxed(sgc->membase + R_GEDR), + sgc->membase + R_GEDR); return 0; } static void sa1100_gpio_resume(void) { - GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask; - GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; + sa1100_update_edge_regs(&sa1100_gpio_chip); } static struct syscore_ops sa1100_gpio_syscore_ops = { @@ -236,36 +281,40 @@ static int __init sa1100_gpio_init_devicefs(void) device_initcall(sa1100_gpio_init_devicefs); +static const int sa1100_gpio_irqs[] __initconst = { + /* Install handlers for GPIO 0-10 edge detect interrupts */ + IRQ_GPIO0_SC, + IRQ_GPIO1_SC, + IRQ_GPIO2_SC, + IRQ_GPIO3_SC, + IRQ_GPIO4_SC, + IRQ_GPIO5_SC, + IRQ_GPIO6_SC, + IRQ_GPIO7_SC, + IRQ_GPIO8_SC, + IRQ_GPIO9_SC, + IRQ_GPIO10_SC, + /* Install handler for GPIO 11-27 edge detect interrupts */ + IRQ_GPIO11_27, +}; + void __init sa1100_init_gpio(void) { - /* clear all GPIO edge detects */ - GFER = 0; - GRER = 0; - GEDR = -1; + struct sa1100_gpio_chip *sgc = &sa1100_gpio_chip; + int i; - gpiochip_add_data(&sa1100_gpio_chip, NULL); + /* clear all GPIO edge detects */ + writel_relaxed(0, sgc->membase + R_GFER); + writel_relaxed(0, sgc->membase + R_GRER); + writel_relaxed(-1, sgc->membase + R_GEDR); + + gpiochip_add_data(&sa1100_gpio_chip.chip, NULL); sa1100_gpio_irqdomain = irq_domain_add_simple(NULL, 28, IRQ_GPIO0, - &sa1100_gpio_irqdomain_ops, NULL); - - /* - * Install handlers for GPIO 0-10 edge detect interrupts - */ - irq_set_chained_handler(IRQ_GPIO0_SC, sa1100_gpio_handler); - irq_set_chained_handler(IRQ_GPIO1_SC, sa1100_gpio_handler); - irq_set_chained_handler(IRQ_GPIO2_SC, sa1100_gpio_handler); - irq_set_chained_handler(IRQ_GPIO3_SC, sa1100_gpio_handler); - irq_set_chained_handler(IRQ_GPIO4_SC, sa1100_gpio_handler); - irq_set_chained_handler(IRQ_GPIO5_SC, sa1100_gpio_handler); - irq_set_chained_handler(IRQ_GPIO6_SC, sa1100_gpio_handler); - irq_set_chained_handler(IRQ_GPIO7_SC, sa1100_gpio_handler); - irq_set_chained_handler(IRQ_GPIO8_SC, sa1100_gpio_handler); - irq_set_chained_handler(IRQ_GPIO9_SC, sa1100_gpio_handler); - irq_set_chained_handler(IRQ_GPIO10_SC, sa1100_gpio_handler); - /* - * Install handler for GPIO 11-27 edge detect interrupts - */ - irq_set_chained_handler(IRQ_GPIO11_27, sa1100_gpio_handler); + &sa1100_gpio_irqdomain_ops, sgc); + for (i = 0; i < ARRAY_SIZE(sa1100_gpio_irqs); i++) + irq_set_chained_handler_and_data(sa1100_gpio_irqs[i], + sa1100_gpio_handler, sgc); } From c65d1fd350fa28de79e86e18ef73b902a67c791a Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 31 Aug 2016 08:49:44 +0100 Subject: [PATCH 52/77] gpio: sa1100: implement get_direction method Allow gpiolib to read back the current IO direction configuration by implementing the .get_direction callback. This, in part, allows debugfs to report the complete true hardware state rather than the software state. Signed-off-by: Russell King Signed-off-by: Linus Walleij --- drivers/gpio/gpio-sa1100.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpio/gpio-sa1100.c b/drivers/gpio/gpio-sa1100.c index bad0169524c9..249f433aa62d 100644 --- a/drivers/gpio/gpio-sa1100.c +++ b/drivers/gpio/gpio-sa1100.c @@ -52,6 +52,13 @@ static void sa1100_gpio_set(struct gpio_chip *chip, unsigned offset, int value) writel_relaxed(BIT(offset), sa1100_gpio_chip(chip)->membase + reg); } +static int sa1100_get_direction(struct gpio_chip *chip, unsigned offset) +{ + void __iomem *gpdr = sa1100_gpio_chip(chip)->membase + R_GPDR; + + return !(readl_relaxed(gpdr) & BIT(offset)); +} + static int sa1100_direction_input(struct gpio_chip *chip, unsigned offset) { void __iomem *gpdr = sa1100_gpio_chip(chip)->membase + R_GPDR; @@ -85,6 +92,7 @@ static int sa1100_to_irq(struct gpio_chip *chip, unsigned offset) static struct sa1100_gpio_chip sa1100_gpio_chip = { .chip = { .label = "gpio", + .get_direction = sa1100_get_direction, .direction_input = sa1100_direction_input, .direction_output = sa1100_direction_output, .set = sa1100_gpio_set, From 380639c7cc786ec663e43eb3896ccf9172a46900 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 31 Aug 2016 08:49:44 +0100 Subject: [PATCH 53/77] gpio: add generic single-register fixed-direction GPIO driver Add a simple, generic, single register fixed-direction GPIO driver. This is able to support a single register with a mixture of inputs and outputs. This is different from gpio-mmio and gpio-74xx-mmio: * gpio-mmio doesn't allow a fixed direction, it assumes there is always a direction register. * gpio-74xx-mmio only supports all-in or all-out setups * gpio-74xx-mmio is DT only, this needs to support legacy too * they don't double-read when getting the GPIO value, as required by some implementations that this driver supports * we need to always do 32-bit reads, which bgpio doesn't guarantee * the current output state may not be readable from the hardware register - reading may reflect input status but not output status. Signed-off-by: Russell King Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 6 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-reg.c | 164 ++++++++++++++++++++++++++++++++++ include/linux/gpio/gpio-reg.h | 12 +++ 4 files changed, 183 insertions(+) create mode 100644 drivers/gpio/gpio-reg.c create mode 100644 include/linux/gpio/gpio-reg.h diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index d6e3cfd54848..63ceed246b6f 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -380,6 +380,12 @@ config GPIO_RCAR help Say yes here to support GPIO on Renesas R-Car SoCs. +config GPIO_REG + bool + help + A 32-bit single register GPIO fixed in/out implementation. This + can be used to represent any register as a set of GPIO signals. + config GPIO_SPEAR_SPICS bool "ST SPEAr13xx SPI Chip Select as GPIO support" depends on PLAT_SPEAR diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index bd995dc2a84a..095598e856ca 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -98,6 +98,7 @@ obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o +obj-$(CONFIG_GPIO_REG) += gpio-reg.o obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o obj-$(CONFIG_GPIO_SCH) += gpio-sch.o obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o diff --git a/drivers/gpio/gpio-reg.c b/drivers/gpio/gpio-reg.c new file mode 100644 index 000000000000..209f73695a47 --- /dev/null +++ b/drivers/gpio/gpio-reg.c @@ -0,0 +1,164 @@ +/* + * gpio-reg: single register individually fixed-direction GPIOs + * + * Copyright (C) 2016 Russell King + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + */ +#include +#include +#include +#include +#include + +struct gpio_reg { + struct gpio_chip gc; + spinlock_t lock; + u32 direction; + u32 out; + void __iomem *reg; +}; + +#define to_gpio_reg(x) container_of(x, struct gpio_reg, gc) + +static int gpio_reg_get_direction(struct gpio_chip *gc, unsigned offset) +{ + struct gpio_reg *r = to_gpio_reg(gc); + + return r->direction & BIT(offset) ? 1 : 0; +} + +static int gpio_reg_direction_output(struct gpio_chip *gc, unsigned offset, + int value) +{ + struct gpio_reg *r = to_gpio_reg(gc); + + if (r->direction & BIT(offset)) + return -ENOTSUPP; + + gc->set(gc, offset, value); + return 0; +} + +static int gpio_reg_direction_input(struct gpio_chip *gc, unsigned offset) +{ + struct gpio_reg *r = to_gpio_reg(gc); + + return r->direction & BIT(offset) ? 0 : -ENOTSUPP; +} + +static void gpio_reg_set(struct gpio_chip *gc, unsigned offset, int value) +{ + struct gpio_reg *r = to_gpio_reg(gc); + unsigned long flags; + u32 val, mask = BIT(offset); + + spin_lock_irqsave(&r->lock, flags); + val = r->out; + if (value) + val |= mask; + else + val &= ~mask; + r->out = val; + writel_relaxed(val, r->reg); + spin_unlock_irqrestore(&r->lock, flags); +} + +static int gpio_reg_get(struct gpio_chip *gc, unsigned offset) +{ + struct gpio_reg *r = to_gpio_reg(gc); + u32 val, mask = BIT(offset); + + if (r->direction & mask) { + /* + * double-read the value, some registers latch after the + * first read. + */ + readl_relaxed(r->reg); + val = readl_relaxed(r->reg); + } else { + val = r->out; + } + return !!(val & mask); +} + +static void 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; + + spin_lock_irqsave(&r->lock, flags); + r->out = (r->out & ~*mask) | (*bits & *mask); + writel_relaxed(r->out, r->reg); + spin_unlock_irqrestore(&r->lock, flags); +} + +/** + * gpio_reg_init - add a fixed in/out register as gpio + * @dev: optional struct device associated with this register + * @base: start gpio number, or -1 to allocate + * @num: number of GPIOs, maximum 32 + * @label: GPIO chip label + * @direction: bitmask of fixed direction, one per GPIO signal, 1 = in + * @def_out: initial GPIO output value + * @names: array of %num strings describing each GPIO signal + * + * Add a single-register GPIO device containing up to 32 GPIO signals, + * where each GPIO has a fixed input or output configuration. Only + * input GPIOs are assumed to be readable from the register, and only + * then after a double-read. Output values are assumed not to be + * readable. + */ +struct gpio_chip *gpio_reg_init(struct device *dev, void __iomem *reg, + int base, int num, const char *label, u32 direction, u32 def_out, + const char *const *names) +{ + struct gpio_reg *r; + int ret; + + if (dev) + r = devm_kzalloc(dev, sizeof(*r), GFP_KERNEL); + else + r = kzalloc(sizeof(*r), GFP_KERNEL); + + if (!r) + return ERR_PTR(-ENOMEM); + + spin_lock_init(&r->lock); + + r->gc.label = label; + 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.get = gpio_reg_get; + r->gc.set_multiple = gpio_reg_set_multiple; + r->gc.base = base; + r->gc.ngpio = num; + r->gc.names = names; + r->direction = direction; + r->out = def_out; + r->reg = reg; + + if (dev) + ret = devm_gpiochip_add_data(dev, &r->gc, r); + else + ret = gpiochip_add_data(&r->gc, r); + + return ret ? ERR_PTR(ret) : &r->gc; +} + +int gpio_reg_resume(struct gpio_chip *gc) +{ + struct gpio_reg *r = to_gpio_reg(gc); + unsigned long flags; + + spin_lock_irqsave(&r->lock, flags); + writel_relaxed(r->out, r->reg); + spin_unlock_irqrestore(&r->lock, flags); + + return 0; +} diff --git a/include/linux/gpio/gpio-reg.h b/include/linux/gpio/gpio-reg.h new file mode 100644 index 000000000000..0352bec7319a --- /dev/null +++ b/include/linux/gpio/gpio-reg.h @@ -0,0 +1,12 @@ +#ifndef GPIO_REG_H +#define GPIO_REG_H + +struct device; + +struct gpio_chip *gpio_reg_init(struct device *dev, void __iomem *reg, + int base, int num, const char *label, u32 direction, u32 def_out, + const char *const *names); + +int gpio_reg_resume(struct gpio_chip *gc); + +#endif From 0e3cb6ee386f384a9131f0c7db52a0a961d2ded9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 2 Sep 2016 12:05:56 +0100 Subject: [PATCH 54/77] gpio: gpio-reg: add irq mapping for gpio-reg users Add support for mapping gpio-reg gpios to interrupts. This may be a non-linear mapping - some gpios in the register may not even have corresponding interrupts associated with them, so we need to pass an array. Signed-off-by: Russell King Signed-off-by: Linus Walleij --- drivers/gpio/gpio-reg.c | 25 +++++++++++++++++++++++-- include/linux/gpio/gpio-reg.h | 3 ++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-reg.c b/drivers/gpio/gpio-reg.c index 209f73695a47..e85903eddc68 100644 --- a/drivers/gpio/gpio-reg.c +++ b/drivers/gpio/gpio-reg.c @@ -19,6 +19,8 @@ struct gpio_reg { u32 direction; u32 out; void __iomem *reg; + struct irq_domain *irqdomain; + const int *irqs; }; #define to_gpio_reg(x) container_of(x, struct gpio_reg, gc) @@ -96,6 +98,17 @@ static void gpio_reg_set_multiple(struct gpio_chip *gc, unsigned long *mask, spin_unlock_irqrestore(&r->lock, flags); } +static int gpio_reg_to_irq(struct gpio_chip *gc, unsigned offset) +{ + struct gpio_reg *r = to_gpio_reg(gc); + int irq = r->irqs[offset]; + + if (irq >= 0 && r->irqdomain) + irq = irq_find_mapping(r->irqdomain, irq); + + return irq; +} + /** * gpio_reg_init - add a fixed in/out register as gpio * @dev: optional struct device associated with this register @@ -104,7 +117,12 @@ static void gpio_reg_set_multiple(struct gpio_chip *gc, unsigned long *mask, * @label: GPIO chip label * @direction: bitmask of fixed direction, one per GPIO signal, 1 = in * @def_out: initial GPIO output value - * @names: array of %num strings describing each GPIO signal + * @names: array of %num strings describing each GPIO signal or %NULL + * @irqdom: irq domain or %NULL + * @irqs: array of %num ints describing the interrupt mapping for each + * GPIO signal, or %NULL. If @irqdom is %NULL, then this + * describes the Linux interrupt number, otherwise it describes + * the hardware interrupt number in the specified irq domain. * * Add a single-register GPIO device containing up to 32 GPIO signals, * where each GPIO has a fixed input or output configuration. Only @@ -114,7 +132,7 @@ static void gpio_reg_set_multiple(struct gpio_chip *gc, unsigned long *mask, */ struct gpio_chip *gpio_reg_init(struct device *dev, void __iomem *reg, int base, int num, const char *label, u32 direction, u32 def_out, - const char *const *names) + const char *const *names, struct irq_domain *irqdom, const int *irqs) { struct gpio_reg *r; int ret; @@ -136,12 +154,15 @@ struct gpio_chip *gpio_reg_init(struct device *dev, void __iomem *reg, r->gc.set = gpio_reg_set; r->gc.get = gpio_reg_get; r->gc.set_multiple = gpio_reg_set_multiple; + if (irqs) + r->gc.to_irq = gpio_reg_to_irq; r->gc.base = base; r->gc.ngpio = num; r->gc.names = names; r->direction = direction; r->out = def_out; r->reg = reg; + r->irqs = irqs; if (dev) ret = devm_gpiochip_add_data(dev, &r->gc, r); diff --git a/include/linux/gpio/gpio-reg.h b/include/linux/gpio/gpio-reg.h index 0352bec7319a..90e0b9060e6d 100644 --- a/include/linux/gpio/gpio-reg.h +++ b/include/linux/gpio/gpio-reg.h @@ -2,10 +2,11 @@ #define GPIO_REG_H struct device; +struct irq_domain; struct gpio_chip *gpio_reg_init(struct device *dev, void __iomem *reg, int base, int num, const char *label, u32 direction, u32 def_out, - const char *const *names); + const char *const *names, struct irq_domain *irqdom, const int *irqs); int gpio_reg_resume(struct gpio_chip *gc); From 3906e8089af3225a0a22c12cc3cf10be4630976e Mon Sep 17 00:00:00 2001 From: Julia Cartwright Date: Tue, 21 Mar 2017 17:43:08 -0500 Subject: [PATCH 55/77] gpio: 104-idio-16: make use of raw_spinlock variants The 104-idio-16 gpio driver currently implements an irq_chip for handling interrupts; due to how irq_chip handling is done, it's necessary for the irq_chip methods to be invoked from hardirq context, even on a a real-time kernel. Because the spinlock_t type becomes a "sleeping" spinlock w/ RT kernels, it is not suitable to be used with irq_chips. A quick audit of the operations under the lock reveal that they do only minimal, bounded work, and are therefore safe to do under a raw spinlock. Signed-off-by: Julia Cartwright Acked-by: William Breathitt Gray Signed-off-by: Linus Walleij --- drivers/gpio/gpio-104-idio-16.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-16.c index 7053cf736648..5281e1cedb01 100644 --- a/drivers/gpio/gpio-104-idio-16.c +++ b/drivers/gpio/gpio-104-idio-16.c @@ -50,7 +50,7 @@ MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers"); */ struct idio_16_gpio { struct gpio_chip chip; - spinlock_t lock; + raw_spinlock_t lock; unsigned long irq_mask; unsigned base; unsigned out_state; @@ -99,7 +99,7 @@ static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value) if (offset > 15) return; - spin_lock_irqsave(&idio16gpio->lock, flags); + raw_spin_lock_irqsave(&idio16gpio->lock, flags); if (value) idio16gpio->out_state |= mask; @@ -111,7 +111,7 @@ static void idio_16_gpio_set(struct gpio_chip *chip, unsigned offset, int value) else outb(idio16gpio->out_state, idio16gpio->base); - spin_unlock_irqrestore(&idio16gpio->lock, flags); + raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); } static void idio_16_gpio_set_multiple(struct gpio_chip *chip, @@ -120,7 +120,7 @@ static void idio_16_gpio_set_multiple(struct gpio_chip *chip, struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); unsigned long flags; - spin_lock_irqsave(&idio16gpio->lock, flags); + raw_spin_lock_irqsave(&idio16gpio->lock, flags); idio16gpio->out_state &= ~*mask; idio16gpio->out_state |= *mask & *bits; @@ -130,7 +130,7 @@ static void idio_16_gpio_set_multiple(struct gpio_chip *chip, if ((*mask >> 8) & 0xFF) outb(idio16gpio->out_state >> 8, idio16gpio->base + 4); - spin_unlock_irqrestore(&idio16gpio->lock, flags); + raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); } static void idio_16_irq_ack(struct irq_data *data) @@ -147,11 +147,11 @@ static void idio_16_irq_mask(struct irq_data *data) idio16gpio->irq_mask &= ~mask; if (!idio16gpio->irq_mask) { - spin_lock_irqsave(&idio16gpio->lock, flags); + raw_spin_lock_irqsave(&idio16gpio->lock, flags); outb(0, idio16gpio->base + 2); - spin_unlock_irqrestore(&idio16gpio->lock, flags); + raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); } } @@ -166,11 +166,11 @@ static void idio_16_irq_unmask(struct irq_data *data) idio16gpio->irq_mask |= mask; if (!prev_irq_mask) { - spin_lock_irqsave(&idio16gpio->lock, flags); + raw_spin_lock_irqsave(&idio16gpio->lock, flags); inb(idio16gpio->base + 2); - spin_unlock_irqrestore(&idio16gpio->lock, flags); + raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); } } @@ -201,11 +201,11 @@ static irqreturn_t idio_16_irq_handler(int irq, void *dev_id) for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio) generic_handle_irq(irq_find_mapping(chip->irqdomain, gpio)); - spin_lock(&idio16gpio->lock); + raw_spin_lock(&idio16gpio->lock); outb(0, idio16gpio->base + 1); - spin_unlock(&idio16gpio->lock); + raw_spin_unlock(&idio16gpio->lock); return IRQ_HANDLED; } @@ -249,7 +249,7 @@ static int idio_16_probe(struct device *dev, unsigned int id) idio16gpio->base = base[id]; idio16gpio->out_state = 0xFFFF; - spin_lock_init(&idio16gpio->lock); + raw_spin_lock_init(&idio16gpio->lock); err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio); if (err) { From ea38ce081d155534494bac5df2bb0d343fb1679b Mon Sep 17 00:00:00 2001 From: Julia Cartwright Date: Tue, 21 Mar 2017 17:43:09 -0500 Subject: [PATCH 56/77] gpio: pci-idio-16: make use of raw_spinlock variants The pci-idio-16 gpio driver currently implements an irq_chip for handling interrupts; due to how irq_chip handling is done, it's necessary for the irq_chip methods to be invoked from hardirq context, even on a a real-time kernel. Because the spinlock_t type becomes a "sleeping" spinlock w/ RT kernels, it is not suitable to be used with irq_chips. A quick audit of the operations under the lock reveal that they do only minimal, bounded work, and are therefore safe to do under a raw spinlock. Signed-off-by: Julia Cartwright Acked-by: William Breathitt Gray Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pci-idio-16.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/gpio-pci-idio-16.c b/drivers/gpio/gpio-pci-idio-16.c index 269ab628634b..7de4f6a2cb49 100644 --- a/drivers/gpio/gpio-pci-idio-16.c +++ b/drivers/gpio/gpio-pci-idio-16.c @@ -59,7 +59,7 @@ struct idio_16_gpio_reg { */ struct idio_16_gpio { struct gpio_chip chip; - spinlock_t lock; + raw_spinlock_t lock; struct idio_16_gpio_reg __iomem *reg; unsigned long irq_mask; }; @@ -121,7 +121,7 @@ static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset, } else base = &idio16gpio->reg->out0_7; - spin_lock_irqsave(&idio16gpio->lock, flags); + raw_spin_lock_irqsave(&idio16gpio->lock, flags); if (value) out_state = ioread8(base) | mask; @@ -130,7 +130,7 @@ static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset, iowrite8(out_state, base); - spin_unlock_irqrestore(&idio16gpio->lock, flags); + raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); } static void idio_16_gpio_set_multiple(struct gpio_chip *chip, @@ -140,7 +140,7 @@ static void idio_16_gpio_set_multiple(struct gpio_chip *chip, unsigned long flags; unsigned int out_state; - spin_lock_irqsave(&idio16gpio->lock, flags); + raw_spin_lock_irqsave(&idio16gpio->lock, flags); /* process output lines 0-7 */ if (*mask & 0xFF) { @@ -160,7 +160,7 @@ static void idio_16_gpio_set_multiple(struct gpio_chip *chip, iowrite8(out_state, &idio16gpio->reg->out8_15); } - spin_unlock_irqrestore(&idio16gpio->lock, flags); + raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); } static void idio_16_irq_ack(struct irq_data *data) @@ -177,11 +177,11 @@ static void idio_16_irq_mask(struct irq_data *data) idio16gpio->irq_mask &= ~mask; if (!idio16gpio->irq_mask) { - spin_lock_irqsave(&idio16gpio->lock, flags); + raw_spin_lock_irqsave(&idio16gpio->lock, flags); iowrite8(0, &idio16gpio->reg->irq_ctl); - spin_unlock_irqrestore(&idio16gpio->lock, flags); + raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); } } @@ -196,11 +196,11 @@ static void idio_16_irq_unmask(struct irq_data *data) idio16gpio->irq_mask |= mask; if (!prev_irq_mask) { - spin_lock_irqsave(&idio16gpio->lock, flags); + raw_spin_lock_irqsave(&idio16gpio->lock, flags); ioread8(&idio16gpio->reg->irq_ctl); - spin_unlock_irqrestore(&idio16gpio->lock, flags); + raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); } } @@ -229,11 +229,11 @@ static irqreturn_t idio_16_irq_handler(int irq, void *dev_id) struct gpio_chip *const chip = &idio16gpio->chip; int gpio; - spin_lock(&idio16gpio->lock); + raw_spin_lock(&idio16gpio->lock); irq_status = ioread8(&idio16gpio->reg->irq_status); - spin_unlock(&idio16gpio->lock); + raw_spin_unlock(&idio16gpio->lock); /* Make sure our device generated IRQ */ if (!(irq_status & 0x3) || !(irq_status & 0x4)) @@ -242,12 +242,12 @@ static irqreturn_t idio_16_irq_handler(int irq, void *dev_id) for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio) generic_handle_irq(irq_find_mapping(chip->irqdomain, gpio)); - spin_lock(&idio16gpio->lock); + raw_spin_lock(&idio16gpio->lock); /* Clear interrupt */ iowrite8(0, &idio16gpio->reg->in0_7); - spin_unlock(&idio16gpio->lock); + raw_spin_unlock(&idio16gpio->lock); return IRQ_HANDLED; } @@ -302,7 +302,7 @@ static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id) idio16gpio->chip.set = idio_16_gpio_set; idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple; - spin_lock_init(&idio16gpio->lock); + raw_spin_lock_init(&idio16gpio->lock); err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio); if (err) { From e1e37d6c4a78bb6fb9b67115f497337cb38de503 Mon Sep 17 00:00:00 2001 From: Julia Cartwright Date: Tue, 21 Mar 2017 17:43:07 -0500 Subject: [PATCH 57/77] gpio: 104-idi-48: make use of raw_spinlock variants The 104-idi-48 gpio driver currently implements an irq_chip for handling interrupts; due to how irq_chip handling is done, it's necessary for the irq_chip methods to be invoked from hardirq context, even on a a real-time kernel. Because the spinlock_t type becomes a "sleeping" spinlock w/ RT kernels, it is not suitable to be used with irq_chips. A quick audit of the operations under the lock reveal that they do only minimal, bounded work, and are therefore safe to do under a raw spinlock. Signed-off-by: Julia Cartwright Acked-by: William Breathitt Gray Signed-off-by: Linus Walleij --- drivers/gpio/gpio-104-idi-48.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c index 568375a7ebc2..337c048168d8 100644 --- a/drivers/gpio/gpio-104-idi-48.c +++ b/drivers/gpio/gpio-104-idi-48.c @@ -51,7 +51,7 @@ MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line numbers"); */ struct idi_48_gpio { struct gpio_chip chip; - spinlock_t lock; + raw_spinlock_t lock; spinlock_t ack_lock; unsigned char irq_mask[6]; unsigned base; @@ -112,11 +112,12 @@ static void idi_48_irq_mask(struct irq_data *data) if (!idi48gpio->irq_mask[boundary]) { idi48gpio->cos_enb &= ~BIT(boundary); - spin_lock_irqsave(&idi48gpio->lock, flags); + raw_spin_lock_irqsave(&idi48gpio->lock, flags); outb(idi48gpio->cos_enb, idi48gpio->base + 7); - spin_unlock_irqrestore(&idi48gpio->lock, flags); + raw_spin_unlock_irqrestore(&idi48gpio->lock, + flags); } return; @@ -145,11 +146,12 @@ static void idi_48_irq_unmask(struct irq_data *data) if (!prev_irq_mask) { idi48gpio->cos_enb |= BIT(boundary); - spin_lock_irqsave(&idi48gpio->lock, flags); + raw_spin_lock_irqsave(&idi48gpio->lock, flags); outb(idi48gpio->cos_enb, idi48gpio->base + 7); - spin_unlock_irqrestore(&idi48gpio->lock, flags); + raw_spin_unlock_irqrestore(&idi48gpio->lock, + flags); } return; @@ -186,11 +188,11 @@ static irqreturn_t idi_48_irq_handler(int irq, void *dev_id) spin_lock(&idi48gpio->ack_lock); - spin_lock(&idi48gpio->lock); + raw_spin_lock(&idi48gpio->lock); cos_status = inb(idi48gpio->base + 7); - spin_unlock(&idi48gpio->lock); + raw_spin_unlock(&idi48gpio->lock); /* IRQ Status (bit 6) is active low (0 = IRQ generated by device) */ if (cos_status & BIT(6)) { @@ -256,7 +258,7 @@ static int idi_48_probe(struct device *dev, unsigned int id) idi48gpio->chip.get = idi_48_gpio_get; idi48gpio->base = base[id]; - spin_lock_init(&idi48gpio->lock); + raw_spin_lock_init(&idi48gpio->lock); spin_lock_init(&idi48gpio->ack_lock); err = devm_gpiochip_add_data(dev, &idi48gpio->chip, idi48gpio); From 11598d1740500e3c1848122f3e77ab017aa38b77 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 5 Apr 2017 16:50:46 +0100 Subject: [PATCH 58/77] gpio: arizona: Correct handling for reading input GPIOs The GPIO register is cached since all the configuration resides within it, however, this means for input GPIOs the driver will not return the actual state but the last value written to the register cache. To correct this in the case of reading an input GPIO resume the CODEC and drop the cache for the input register to ensure an actual hardware read takes place. Signed-off-by: Charles Keepax Signed-off-by: Linus Walleij --- drivers/gpio/gpio-arizona.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c index 1f91557717a6..60b3102279f3 100644 --- a/drivers/gpio/gpio-arizona.c +++ b/drivers/gpio/gpio-arizona.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -41,13 +42,38 @@ static int arizona_gpio_get(struct gpio_chip *chip, unsigned offset) { struct arizona_gpio *arizona_gpio = gpiochip_get_data(chip); struct arizona *arizona = arizona_gpio->arizona; - unsigned int val; + unsigned int reg, val; int ret; - ret = regmap_read(arizona->regmap, ARIZONA_GPIO1_CTRL + offset, &val); + reg = ARIZONA_GPIO1_CTRL + offset; + ret = regmap_read(arizona->regmap, reg, &val); if (ret < 0) return ret; + /* Resume to read actual registers for input pins */ + if (!(val & ARIZONA_GPN_DIR)) { + ret = pm_runtime_get_sync(chip->parent); + if (ret < 0) { + dev_err(chip->parent, "Failed to resume: %d\n", ret); + return ret; + } + + /* Register is cached, drop it to ensure a physical read */ + ret = regcache_drop_region(arizona->regmap, reg, reg); + if (ret < 0) { + dev_err(chip->parent, "Failed to drop cache: %d\n", + ret); + return ret; + } + + ret = regmap_read(arizona->regmap, reg, &val); + if (ret < 0) + return ret; + + pm_runtime_mark_last_busy(chip->parent); + pm_runtime_put_autosuspend(chip->parent); + } + if (val & ARIZONA_GPN_LVL) return 1; else From 4c0facddb7d88c78c8bd977c16faa647f079ccda Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 6 Apr 2017 19:05:52 +0530 Subject: [PATCH 59/77] gpio: core: Decouple open drain/source flag with active low/high Currently, the GPIO interface is said to Open Drain if it is Single Ended and active LOW. Similarly, it is said as Open Source if it is Single Ended and active HIGH. The active HIGH/LOW is used in the interface for setting the pin state to HIGH or LOW when enabling/disabling the interface. In Open Drain interface, pin is set to HIGH by putting pin in high impedance and LOW by driving to the LOW. In Open Source interface, pin is set to HIGH by driving pin to HIGH and set to LOW by putting pin in high impedance. With above, the Open Drain/Source is unrelated to the active LOW/HIGH in interface. There is interface where the enable/disable of interface is ether active LOW or HIGH but it is Open Drain type. Hence decouple the Open Drain with Single Ended + Active LOW and Open Source with Single Ended + Active HIGH. Adding different flag for the Open Drain/Open Source which is valid only when Single ended flag is enabled. Signed-off-by: Laxman Dewangan Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 2 +- drivers/gpio/gpiolib.c | 4 +++- include/dt-bindings/gpio/gpio.h | 12 ++++++++---- include/linux/of_gpio.h | 1 + 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 975b9f6cf408..b13b7c7c335f 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -147,7 +147,7 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, *flags |= GPIO_ACTIVE_LOW; if (of_flags & OF_GPIO_SINGLE_ENDED) { - if (of_flags & OF_GPIO_ACTIVE_LOW) + if (of_flags & OF_GPIO_OPEN_DRAIN) *flags |= GPIO_OPEN_DRAIN; else *flags |= GPIO_OPEN_SOURCE; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c788b55dfe85..d11eb2abfced 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3340,6 +3340,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, unsigned long lflags = 0; bool active_low = false; bool single_ended = false; + bool open_drain = false; int ret; if (!fwnode) @@ -3353,6 +3354,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, if (!IS_ERR(desc)) { active_low = flags & OF_GPIO_ACTIVE_LOW; single_ended = flags & OF_GPIO_SINGLE_ENDED; + open_drain = flags & OF_GPIO_OPEN_DRAIN; } } else if (is_acpi_node(fwnode)) { struct acpi_gpio_info info; @@ -3373,7 +3375,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, lflags |= GPIO_ACTIVE_LOW; if (single_ended) { - if (active_low) + if (open_drain) lflags |= GPIO_OPEN_DRAIN; else lflags |= GPIO_OPEN_SOURCE; diff --git a/include/dt-bindings/gpio/gpio.h b/include/dt-bindings/gpio/gpio.h index c673d2c87c60..b4f54da694eb 100644 --- a/include/dt-bindings/gpio/gpio.h +++ b/include/dt-bindings/gpio/gpio.h @@ -17,11 +17,15 @@ #define GPIO_PUSH_PULL 0 #define GPIO_SINGLE_ENDED 2 +/* Bit 2 express Open drain or open source */ +#define GPIO_LINE_OPEN_SOURCE 0 +#define GPIO_LINE_OPEN_DRAIN 4 + /* - * Open Drain/Collector is the combination of single-ended active low, - * Open Source/Emitter is the combination of single-ended active high. + * Open Drain/Collector is the combination of single-ended open drain interface. + * Open Source/Emitter is the combination of single-ended open source interface. */ -#define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_ACTIVE_LOW) -#define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_ACTIVE_HIGH) +#define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_DRAIN) +#define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_SOURCE) #endif diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h index 3f87ea5b8bee..1e089d5a182b 100644 --- a/include/linux/of_gpio.h +++ b/include/linux/of_gpio.h @@ -30,6 +30,7 @@ struct device_node; enum of_gpio_flags { OF_GPIO_ACTIVE_LOW = 0x1, OF_GPIO_SINGLE_ENDED = 0x2, + OF_GPIO_OPEN_DRAIN = 0x4, }; #ifdef CONFIG_OF_GPIO From d69843e416d315123aea4831c3a7dfb299526681 Mon Sep 17 00:00:00 2001 From: Marty Plummer Date: Thu, 6 Apr 2017 19:42:06 -0500 Subject: [PATCH 60/77] gpio: f7188x: Add F71889A GPIO support. Add F71889A GPIO support. Fintek F71889A is a SuperIO. It contains HWMON/GPIO/Serial Ports. Datasheet: http://www.alldatasheet.com/datasheet-pdf/pdf/459076/FINTEK/F71889A.html Its virtually identical to the F71889F superio as far as gpios go. One oddity is GPIO2 at index 0xD0; the datasheet only lists gpio's 7-5, but it logically seems that it should continue down to 0. I'm not sure if the driver can handle gpios that are shifted away from index 0 as it currently stands. Signed-off-by: Marty Plummer Signed-off-by: Linus Walleij --- drivers/gpio/gpio-f7188x.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c index 56bd76c33767..c013ff5deb70 100644 --- a/drivers/gpio/gpio-f7188x.c +++ b/drivers/gpio/gpio-f7188x.c @@ -37,14 +37,16 @@ #define SIO_F71869A_ID 0x1007 /* F71869A chipset ID */ #define SIO_F71882_ID 0x0541 /* F71882 chipset ID */ #define SIO_F71889_ID 0x0909 /* F71889 chipset ID */ +#define SIO_F71889A_ID 0x1005 /* F71889A chipset ID */ #define SIO_F81866_ID 0x1010 /* F81866 chipset ID */ -enum chips { f71869, f71869a, f71882fg, f71889f, f81866 }; +enum chips { f71869, f71869a, f71882fg, f71889a, f71889f, f81866 }; static const char * const f7188x_names[] = { "f71869", "f71869a", "f71882fg", + "f71889a", "f71889f", "f81866", }; @@ -187,6 +189,17 @@ static struct f7188x_gpio_bank f71882_gpio_bank[] = { F7188X_GPIO_BANK(40, 4, 0xB0), }; +static struct f7188x_gpio_bank f71889a_gpio_bank[] = { + F7188X_GPIO_BANK(0, 7, 0xF0), + F7188X_GPIO_BANK(10, 7, 0xE0), + F7188X_GPIO_BANK(20, 8, 0xD0), + F7188X_GPIO_BANK(30, 8, 0xC0), + F7188X_GPIO_BANK(40, 8, 0xB0), + F7188X_GPIO_BANK(50, 5, 0xA0), + F7188X_GPIO_BANK(60, 8, 0x90), + F7188X_GPIO_BANK(70, 8, 0x80), +}; + static struct f7188x_gpio_bank f71889_gpio_bank[] = { F7188X_GPIO_BANK(0, 7, 0xF0), F7188X_GPIO_BANK(10, 7, 0xE0), @@ -382,6 +395,9 @@ static int f7188x_gpio_probe(struct platform_device *pdev) data->nr_bank = ARRAY_SIZE(f71882_gpio_bank); data->bank = f71882_gpio_bank; break; + case f71889a: + data->nr_bank = ARRAY_SIZE(f71889a_gpio_bank); + data->bank = f71889a_gpio_bank; case f71889f: data->nr_bank = ARRAY_SIZE(f71889_gpio_bank); data->bank = f71889_gpio_bank; @@ -443,6 +459,9 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio) case SIO_F71882_ID: sio->type = f71882fg; break; + case SIO_F71889A_ID: + sio->type = f71889a; + break; case SIO_F71889_ID: sio->type = f71889f; break; @@ -538,6 +557,6 @@ static void __exit f7188x_gpio_exit(void) } module_exit(f7188x_gpio_exit); -MODULE_DESCRIPTION("GPIO driver for Super-I/O chips F71869, F71869A, F71882FG, F71889F and F81866"); +MODULE_DESCRIPTION("GPIO driver for Super-I/O chips F71869, F71869A, F71882FG, F71889A, F71889F and F81866"); MODULE_AUTHOR("Simon Guinot "); MODULE_LICENSE("GPL"); From 6f79309acc32b025064a496dbfcd4c70c557294e Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 3 Apr 2017 18:05:21 +0200 Subject: [PATCH 61/77] gpio: Use unsigned int for interrupt numbers Interrupt numbers are never negative, zero serves as the special invalid value. Signed-off-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 6 +++--- include/linux/gpio/driver.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index d11eb2abfced..1d1fa7248d63 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1522,7 +1522,7 @@ static bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip, */ static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gpiochip, struct irq_chip *irqchip, - int parent_irq, + unsigned int parent_irq, irq_flow_handler_t parent_handler) { unsigned int offset; @@ -1571,7 +1571,7 @@ static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gpiochip, */ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, struct irq_chip *irqchip, - int parent_irq, + unsigned int parent_irq, irq_flow_handler_t parent_handler) { gpiochip_set_cascaded_irqchip(gpiochip, irqchip, parent_irq, @@ -1588,7 +1588,7 @@ EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip); */ void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip, struct irq_chip *irqchip, - int parent_irq) + unsigned int parent_irq) { if (!gpiochip->irq_nested) { chip_err(gpiochip, "tried to nest a chained gpiochip\n"); diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 846f3b989480..393582867afd 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -168,7 +168,7 @@ struct gpio_chip { unsigned int irq_base; irq_flow_handler_t irq_handler; unsigned int irq_default_type; - int irq_chained_parent; + unsigned int irq_chained_parent; bool irq_nested; bool irq_need_valid_mask; unsigned long *irq_valid_mask; @@ -244,12 +244,12 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev, void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, struct irq_chip *irqchip, - int parent_irq, + unsigned int parent_irq, irq_flow_handler_t parent_handler); void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip, struct irq_chip *irqchip, - int parent_irq); + unsigned int parent_irq); int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip, struct irq_chip *irqchip, From 757642f9a584e893f3f4e50c99b674ee8a3ed363 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Fri, 14 Apr 2017 17:40:52 +0200 Subject: [PATCH 62/77] gpio: mvebu: Add limited PWM support Armada 370/XP devices can 'blink' GPIO lines with a configurable on and off period. This can be modelled as a PWM. However, there are only two sets of PWM configuration registers for all the GPIO lines. This driver simply allows a single GPIO line per GPIO chip of 32 lines to be used as a PWM. Attempts to use more return EBUSY. Due to the interleaving of registers it is not simple to separate the PWM driver from the GPIO driver. Thus the GPIO driver has been extended with a PWM driver. Signed-off-by: Andrew Lunn URL: https://patchwork.ozlabs.org/patch/427287/ URL: https://patchwork.ozlabs.org/patch/427295/ [Ralph Sennhauser: * Port forward * Merge PWM portion into gpio-mvebu.c * Switch to atomic PWM API * Add new compatible string marvell,armada-370-xp-gpio * Update and merge documentation patch * Update MAINTAINERS] Signed-off-by: Ralph Sennhauser Tested-by: Andrew Lunn Acked-by: Thierry Reding Acked-by: Rob Herring Signed-off-by: Linus Walleij --- .../devicetree/bindings/gpio/gpio-mvebu.txt | 32 ++ MAINTAINERS | 2 + drivers/gpio/gpio-mvebu.c | 327 +++++++++++++++++- 3 files changed, 349 insertions(+), 12 deletions(-) diff --git a/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt b/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt index a6f3bec1da7d..42c3bb2d53e8 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt @@ -38,6 +38,24 @@ Required properties: - #gpio-cells: Should be two. The first cell is the pin number. The second cell is reserved for flags, unused at the moment. +Optional properties: + +In order to use the GPIO lines in PWM mode, some additional optional +properties are required. Only Armada 370 and XP support these properties. + +- compatible: Must contain "marvell,armada-370-xp-gpio" + +- reg: an additional register set is needed, for the GPIO Blink + Counter on/off registers. + +- reg-names: Must contain an entry "pwm" corresponding to the + additional register range needed for PWM operation. + +- #pwm-cells: Should be two. The first cell is the GPIO line number. The + second cell is the period in nanoseconds. + +- clocks: Must be a phandle to the clock for the GPIO controller. + Example: gpio0: gpio@d0018100 { @@ -51,3 +69,17 @@ Example: #interrupt-cells = <2>; interrupts = <16>, <17>, <18>, <19>; }; + + gpio1: gpio@18140 { + compatible = "marvell,armada-370-xp-gpio"; + reg = <0x18140 0x40>, <0x181c8 0x08>; + reg-names = "gpio", "pwm"; + ngpios = <17>; + gpio-controller; + #gpio-cells = <2>; + #pwm-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <87>, <88>, <89>; + clocks = <&coreclk 0>; + }; diff --git a/MAINTAINERS b/MAINTAINERS index c265a5fe4848..d09295681f68 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10212,6 +10212,8 @@ F: include/linux/pwm.h F: drivers/pwm/ F: drivers/video/backlight/pwm_bl.c F: include/linux/pwm_backlight.h +F: drivers/gpio/gpio-mvebu.c +F: Documentation/devicetree/bindings/gpio/gpio-mvebu.txt PXA2xx/PXA3xx SUPPORT M: Daniel Mack diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index fae4db684398..19a92efabbef 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -42,22 +42,34 @@ #include #include #include +#include #include #include #include +#include #include +#include "gpiolib.h" + /* * GPIO unit register offsets. */ -#define GPIO_OUT_OFF 0x0000 -#define GPIO_IO_CONF_OFF 0x0004 -#define GPIO_BLINK_EN_OFF 0x0008 -#define GPIO_IN_POL_OFF 0x000c -#define GPIO_DATA_IN_OFF 0x0010 -#define GPIO_EDGE_CAUSE_OFF 0x0014 -#define GPIO_EDGE_MASK_OFF 0x0018 -#define GPIO_LEVEL_MASK_OFF 0x001c +#define GPIO_OUT_OFF 0x0000 +#define GPIO_IO_CONF_OFF 0x0004 +#define GPIO_BLINK_EN_OFF 0x0008 +#define GPIO_IN_POL_OFF 0x000c +#define GPIO_DATA_IN_OFF 0x0010 +#define GPIO_EDGE_CAUSE_OFF 0x0014 +#define GPIO_EDGE_MASK_OFF 0x0018 +#define GPIO_LEVEL_MASK_OFF 0x001c +#define GPIO_BLINK_CNT_SELECT_OFF 0x0020 + +/* + * PWM register offsets. + */ +#define PWM_BLINK_ON_DURATION_OFF 0x0 +#define PWM_BLINK_OFF_DURATION_OFF 0x4 + /* The MV78200 has per-CPU registers for edge mask and level mask */ #define GPIO_EDGE_MASK_MV78200_OFF(cpu) ((cpu) ? 0x30 : 0x18) @@ -78,6 +90,20 @@ #define MVEBU_MAX_GPIO_PER_BANK 32 +struct mvebu_pwm { + void __iomem *membase; + unsigned long clk_rate; + struct gpio_desc *gpiod; + struct pwm_chip chip; + spinlock_t lock; + struct mvebu_gpio_chip *mvchip; + + /* Used to preserve GPIO/PWM registers across suspend/resume */ + u32 blink_select; + u32 blink_on_duration; + u32 blink_off_duration; +}; + struct mvebu_gpio_chip { struct gpio_chip chip; spinlock_t lock; @@ -87,6 +113,10 @@ struct mvebu_gpio_chip { struct irq_domain *domain; int soc_variant; + /* Used for PWM support */ + struct clk *clk; + struct mvebu_pwm *mvpwm; + /* Used to preserve GPIO registers across suspend/resume */ u32 out_reg; u32 io_conf_reg; @@ -110,6 +140,12 @@ static void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip) return mvchip->membase + GPIO_BLINK_EN_OFF; } +static void __iomem *mvebu_gpioreg_blink_counter_select(struct mvebu_gpio_chip + *mvchip) +{ + return mvchip->membase + GPIO_BLINK_CNT_SELECT_OFF; +} + static void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip) { return mvchip->membase + GPIO_IO_CONF_OFF; @@ -180,6 +216,20 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip) } } +/* + * Functions returning addresses of individual registers for a given + * PWM controller. + */ +static void __iomem *mvebu_pwmreg_blink_on_duration(struct mvebu_pwm *mvpwm) +{ + return mvpwm->membase + PWM_BLINK_ON_DURATION_OFF; +} + +static void __iomem *mvebu_pwmreg_blink_off_duration(struct mvebu_pwm *mvpwm) +{ + return mvpwm->membase + PWM_BLINK_OFF_DURATION_OFF; +} + /* * Functions implementing the gpio_chip methods */ @@ -484,6 +534,246 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc) chained_irq_exit(chip, desc); } +/* + * Functions implementing the pwm_chip methods + */ +static struct mvebu_pwm *to_mvebu_pwm(struct pwm_chip *chip) +{ + return container_of(chip, struct mvebu_pwm, chip); +} + +static int mvebu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); + struct mvebu_gpio_chip *mvchip = mvpwm->mvchip; + struct gpio_desc *desc; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&mvpwm->lock, flags); + + if (mvpwm->gpiod) { + ret = -EBUSY; + } else { + desc = gpio_to_desc(mvchip->chip.base + pwm->hwpwm); + if (!desc) { + ret = -ENODEV; + goto out; + } + + ret = gpiod_request(desc, "mvebu-pwm"); + if (ret) + goto out; + + ret = gpiod_direction_output(desc, 0); + if (ret) { + gpiod_free(desc); + goto out; + } + + mvpwm->gpiod = desc; + } +out: + spin_unlock_irqrestore(&mvpwm->lock, flags); + return ret; +} + +static void mvebu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); + unsigned long flags; + + spin_lock_irqsave(&mvpwm->lock, flags); + gpiod_free(mvpwm->gpiod); + mvpwm->gpiod = NULL; + spin_unlock_irqrestore(&mvpwm->lock, flags); +} + +static void mvebu_pwm_get_state(struct pwm_chip *chip, + struct pwm_device *pwm, + struct pwm_state *state) { + + struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); + struct mvebu_gpio_chip *mvchip = mvpwm->mvchip; + unsigned long long val; + unsigned long flags; + u32 u; + + spin_lock_irqsave(&mvpwm->lock, flags); + + val = (unsigned long long) + readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm)); + val *= NSEC_PER_SEC; + do_div(val, mvpwm->clk_rate); + if (val > UINT_MAX) + state->duty_cycle = UINT_MAX; + else if (val) + state->duty_cycle = val; + else + state->duty_cycle = 1; + + val = (unsigned long long) + readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm)); + val *= NSEC_PER_SEC; + do_div(val, mvpwm->clk_rate); + if (val < state->duty_cycle) { + state->period = 1; + } else { + val -= state->duty_cycle; + if (val > UINT_MAX) + state->period = UINT_MAX; + else if (val) + state->period = val; + else + state->period = 1; + } + + u = readl_relaxed(mvebu_gpioreg_blink(mvchip)); + if (u) + state->enabled = true; + else + state->enabled = false; + + spin_unlock_irqrestore(&mvpwm->lock, flags); +} + +static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) +{ + struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip); + struct mvebu_gpio_chip *mvchip = mvpwm->mvchip; + unsigned long long val; + unsigned long flags; + unsigned int on, off; + + val = (unsigned long long) mvpwm->clk_rate * state->duty_cycle; + do_div(val, NSEC_PER_SEC); + if (val > UINT_MAX) + return -EINVAL; + if (val) + on = val; + else + on = 1; + + val = (unsigned long long) mvpwm->clk_rate * + (state->period - state->duty_cycle); + do_div(val, NSEC_PER_SEC); + if (val > UINT_MAX) + return -EINVAL; + if (val) + off = val; + else + off = 1; + + spin_lock_irqsave(&mvpwm->lock, flags); + + writel_relaxed(on, mvebu_pwmreg_blink_on_duration(mvpwm)); + writel_relaxed(off, mvebu_pwmreg_blink_off_duration(mvpwm)); + if (state->enabled) + mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 1); + else + mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 0); + + spin_unlock_irqrestore(&mvpwm->lock, flags); + + return 0; +} + +static const struct pwm_ops mvebu_pwm_ops = { + .request = mvebu_pwm_request, + .free = mvebu_pwm_free, + .get_state = mvebu_pwm_get_state, + .apply = mvebu_pwm_apply, + .owner = THIS_MODULE, +}; + +static void __maybe_unused mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip) +{ + struct mvebu_pwm *mvpwm = mvchip->mvpwm; + + mvpwm->blink_select = + readl_relaxed(mvebu_gpioreg_blink_counter_select(mvchip)); + mvpwm->blink_on_duration = + readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm)); + mvpwm->blink_off_duration = + readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm)); +} + +static void __maybe_unused mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip) +{ + struct mvebu_pwm *mvpwm = mvchip->mvpwm; + + writel_relaxed(mvpwm->blink_select, + mvebu_gpioreg_blink_counter_select(mvchip)); + writel_relaxed(mvpwm->blink_on_duration, + mvebu_pwmreg_blink_on_duration(mvpwm)); + writel_relaxed(mvpwm->blink_off_duration, + mvebu_pwmreg_blink_off_duration(mvpwm)); +} + +static int mvebu_pwm_probe(struct platform_device *pdev, + struct mvebu_gpio_chip *mvchip, + int id) +{ + struct device *dev = &pdev->dev; + struct mvebu_pwm *mvpwm; + struct resource *res; + u32 set; + + if (!of_device_is_compatible(mvchip->chip.of_node, + "marvell,armada-370-xp-gpio")) + return 0; + + if (IS_ERR(mvchip->clk)) + return PTR_ERR(mvchip->clk); + + /* + * There are only two sets of PWM configuration registers for + * all the GPIO lines on those SoCs which this driver reserves + * for the first two GPIO chips. So if the resource is missing + * we can't treat it as an error. + */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwm"); + if (!res) + return 0; + + /* + * Use set A for lines of GPIO chip with id 0, B for GPIO chip + * with id 1. Don't allow further GPIO chips to be used for PWM. + */ + if (id == 0) + set = 0; + else if (id == 1) + set = U32_MAX; + else + return -EINVAL; + writel_relaxed(0, mvebu_gpioreg_blink_counter_select(mvchip)); + + mvpwm = devm_kzalloc(dev, sizeof(struct mvebu_pwm), GFP_KERNEL); + if (!mvpwm) + return -ENOMEM; + mvchip->mvpwm = mvpwm; + mvpwm->mvchip = mvchip; + + mvpwm->membase = devm_ioremap_resource(dev, res); + if (IS_ERR(mvpwm->membase)) + return PTR_ERR(mvpwm->membase); + + mvpwm->clk_rate = clk_get_rate(mvchip->clk); + if (!mvpwm->clk_rate) { + dev_err(dev, "failed to get clock rate\n"); + return -EINVAL; + } + + mvpwm->chip.dev = dev; + mvpwm->chip.ops = &mvebu_pwm_ops; + mvpwm->chip.npwm = mvchip->chip.ngpio; + + spin_lock_init(&mvpwm->lock); + + return pwmchip_add(&mvpwm->chip); +} + #ifdef CONFIG_DEBUG_FS #include @@ -554,6 +844,10 @@ static const struct of_device_id mvebu_gpio_of_match[] = { .compatible = "marvell,armadaxp-gpio", .data = (void *) MVEBU_GPIO_SOC_VARIANT_ARMADAXP, }, + { + .compatible = "marvell,armada-370-xp-gpio", + .data = (void *) MVEBU_GPIO_SOC_VARIANT_ORION, + }, { /* sentinel */ }, @@ -600,6 +894,9 @@ static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state) BUG(); } + if (IS_ENABLED(CONFIG_PWM)) + mvebu_pwm_suspend(mvchip); + return 0; } @@ -643,6 +940,9 @@ static int mvebu_gpio_resume(struct platform_device *pdev) BUG(); } + if (IS_ENABLED(CONFIG_PWM)) + mvebu_pwm_resume(mvchip); + return 0; } @@ -654,7 +954,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) struct resource *res; struct irq_chip_generic *gc; struct irq_chip_type *ct; - struct clk *clk; unsigned int ngpios; bool have_irqs; int soc_variant; @@ -688,10 +987,10 @@ static int mvebu_gpio_probe(struct platform_device *pdev) return id; } - clk = devm_clk_get(&pdev->dev, NULL); + mvchip->clk = devm_clk_get(&pdev->dev, NULL); /* Not all SoCs require a clock.*/ - if (!IS_ERR(clk)) - clk_prepare_enable(clk); + if (!IS_ERR(mvchip->clk)) + clk_prepare_enable(mvchip->clk); mvchip->soc_variant = soc_variant; mvchip->chip.label = dev_name(&pdev->dev); @@ -822,6 +1121,10 @@ static int mvebu_gpio_probe(struct platform_device *pdev) mvchip); } + /* Armada 370/XP has simple PWM support for GPIO lines */ + if (IS_ENABLED(CONFIG_PWM)) + return mvebu_pwm_probe(pdev, mvchip, id); + return 0; err_domain: From cea956551f1f0edb2d64a0320785705e400ae5f1 Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Fri, 7 Apr 2017 22:28:59 +0930 Subject: [PATCH 63/77] gpio: aspeed: dt: Fix description alignment in bindings document Signed-off-by: Andrew Jeffery Acked-by: Rob Herring Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/gpio/gpio-aspeed.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt b/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt index 393bb2ed8a77..6f30b9a048da 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt @@ -17,7 +17,7 @@ Required properties: Optional properties: -- interrupt-parent : The parent interrupt controller, optional if inherited +- interrupt-parent : The parent interrupt controller, optional if inherited The gpio and interrupt properties are further described in their respective bindings documentation: From 9d7163f5167fa60e71071ab6dcb60da0f7230beb Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Fri, 7 Apr 2017 22:29:00 +0930 Subject: [PATCH 64/77] gpio: aspeed: dt: Add optional clocks property We need a reference to the HPLL to calculate debounce cycles. If the clocks property is not supplied in the GPIO node then the consumer should deny any debounce requests. Signed-off-by: Andrew Jeffery Acked-by: Rob Herring Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/gpio/gpio-aspeed.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt b/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt index 6f30b9a048da..c756afa88cc6 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt @@ -18,6 +18,7 @@ Required properties: Optional properties: - interrupt-parent : The parent interrupt controller, optional if inherited +- clocks : A phandle to the HPLL clock node for debounce timings The gpio and interrupt properties are further described in their respective bindings documentation: From 5ae4cb94b3133d00857bb2909dae779782db40cb Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Fri, 7 Apr 2017 22:29:01 +0930 Subject: [PATCH 65/77] gpio: aspeed: Add debounce support Each GPIO in the Aspeed GPIO controller can choose one of four input debounce states: to disable debouncing for an input, or select from one of three programmable debounce timer values. Each GPIO in a four-bank-set is assigned one bit in each of two debounce configuration registers dedicated to the set, and selects a debounce state by configuring the two bits to select one of the four options. The limitation on debounce timer values is managed by mapping offsets onto a configured timer value and keeping count of the number of users a timer has. Timer values are configured on a first-come-first-served basis. A small twist in the hardware design is that the debounce configuration register numbering is reversed with respect to the binary representation of the debounce timer of interest (i.e. debounce register 1 represents bit 1, and debounce register 2 represents bit 0 of the timer numbering). Tested on an AST2500EVB with additional inspection under QEMU's romulus-bmc machine. Signed-off-by: Andrew Jeffery Signed-off-by: Linus Walleij --- drivers/gpio/gpio-aspeed.c | 281 ++++++++++++++++++++++++++++++++++++- 1 file changed, 276 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index fb16cc771c0d..3327a48df862 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -9,14 +9,18 @@ * 2 of the License, or (at your option) any later version. */ -#include -#include +#include +#include +#include +#include #include #include -#include -#include -#include +#include +#include #include +#include +#include +#include struct aspeed_bank_props { unsigned int bank; @@ -29,59 +33,85 @@ struct aspeed_gpio_config { const struct aspeed_bank_props *props; }; +/* + * @offset_timer: Maps an offset to an @timer_users index, or zero if disabled + * @timer_users: Tracks the number of users for each timer + * + * The @timer_users has four elements but the first element is unused. This is + * to simplify accounting and indexing, as a zero value in @offset_timer + * represents disabled debouncing for the GPIO. Any other value for an element + * of @offset_timer is used as an index into @timer_users. This behaviour of + * the zero value aligns with the behaviour of zero built from the timer + * configuration registers (i.e. debouncing is disabled). + */ struct aspeed_gpio { struct gpio_chip chip; spinlock_t lock; void __iomem *base; int irq; const struct aspeed_gpio_config *config; + + u8 *offset_timer; + unsigned int timer_users[4]; + struct clk *clk; }; struct aspeed_gpio_bank { uint16_t val_regs; uint16_t irq_regs; + uint16_t debounce_regs; const char names[4][3]; }; +static const int debounce_timers[4] = { 0x00, 0x50, 0x54, 0x58 }; + static const struct aspeed_gpio_bank aspeed_gpio_banks[] = { { .val_regs = 0x0000, .irq_regs = 0x0008, + .debounce_regs = 0x0040, .names = { "A", "B", "C", "D" }, }, { .val_regs = 0x0020, .irq_regs = 0x0028, + .debounce_regs = 0x0048, .names = { "E", "F", "G", "H" }, }, { .val_regs = 0x0070, .irq_regs = 0x0098, + .debounce_regs = 0x00b0, .names = { "I", "J", "K", "L" }, }, { .val_regs = 0x0078, .irq_regs = 0x00e8, + .debounce_regs = 0x0100, .names = { "M", "N", "O", "P" }, }, { .val_regs = 0x0080, .irq_regs = 0x0118, + .debounce_regs = 0x0130, .names = { "Q", "R", "S", "T" }, }, { .val_regs = 0x0088, .irq_regs = 0x0148, + .debounce_regs = 0x0160, .names = { "U", "V", "W", "X" }, }, { .val_regs = 0x01E0, .irq_regs = 0x0178, + .debounce_regs = 0x0190, .names = { "Y", "Z", "AA", "AB" }, }, { .val_regs = 0x01E8, .irq_regs = 0x01A8, + .debounce_regs = 0x01c0, .names = { "AC", "", "", "" }, }, }; @@ -99,6 +129,13 @@ static const struct aspeed_gpio_bank aspeed_gpio_banks[] = { #define GPIO_IRQ_TYPE2 0x0c #define GPIO_IRQ_STATUS 0x10 +#define GPIO_DEBOUNCE_SEL1 0x00 +#define GPIO_DEBOUNCE_SEL2 0x04 + +#define _GPIO_SET_DEBOUNCE(t, o, i) ((!!((t) & BIT(i))) << GPIO_OFFSET(o)) +#define GPIO_SET_DEBOUNCE1(t, o) _GPIO_SET_DEBOUNCE(t, o, 1) +#define GPIO_SET_DEBOUNCE2(t, o) _GPIO_SET_DEBOUNCE(t, o, 0) + static const struct aspeed_gpio_bank *to_bank(unsigned int offset) { unsigned int bank = GPIO_BANK(offset); @@ -144,6 +181,7 @@ static inline bool have_input(struct aspeed_gpio *gpio, unsigned int offset) } #define have_irq(g, o) have_input((g), (o)) +#define have_debounce(g, o) have_input((g), (o)) static inline bool have_output(struct aspeed_gpio *gpio, unsigned int offset) { @@ -506,6 +544,227 @@ static void aspeed_gpio_free(struct gpio_chip *chip, unsigned int offset) pinctrl_free_gpio(chip->base + offset); } +static inline void __iomem *bank_debounce_reg(struct aspeed_gpio *gpio, + const struct aspeed_gpio_bank *bank, + unsigned int reg) +{ + return gpio->base + bank->debounce_regs + reg; +} + +static int usecs_to_cycles(struct aspeed_gpio *gpio, unsigned long usecs, + u32 *cycles) +{ + u64 rate; + u64 n; + u32 r; + + rate = clk_get_rate(gpio->clk); + if (!rate) + return -ENOTSUPP; + + n = rate * usecs; + r = do_div(n, 1000000); + + if (n >= U32_MAX) + return -ERANGE; + + /* At least as long as the requested time */ + *cycles = n + (!!r); + + return 0; +} + +/* Call under gpio->lock */ +static int register_allocated_timer(struct aspeed_gpio *gpio, + unsigned int offset, unsigned int timer) +{ + if (WARN(gpio->offset_timer[offset] != 0, + "Offset %d already allocated timer %d\n", + offset, gpio->offset_timer[offset])) + return -EINVAL; + + if (WARN(gpio->timer_users[timer] == UINT_MAX, + "Timer user count would overflow\n")) + return -EPERM; + + gpio->offset_timer[offset] = timer; + gpio->timer_users[timer]++; + + return 0; +} + +/* Call under gpio->lock */ +static int unregister_allocated_timer(struct aspeed_gpio *gpio, + unsigned int offset) +{ + if (WARN(gpio->offset_timer[offset] == 0, + "No timer allocated to offset %d\n", offset)) + return -EINVAL; + + if (WARN(gpio->timer_users[gpio->offset_timer[offset]] == 0, + "No users recorded for timer %d\n", + gpio->offset_timer[offset])) + return -EINVAL; + + gpio->timer_users[gpio->offset_timer[offset]]--; + gpio->offset_timer[offset] = 0; + + return 0; +} + +/* Call under gpio->lock */ +static inline bool timer_allocation_registered(struct aspeed_gpio *gpio, + unsigned int offset) +{ + return gpio->offset_timer[offset] > 0; +} + +/* Call under gpio->lock */ +static void configure_timer(struct aspeed_gpio *gpio, unsigned int offset, + unsigned int timer) +{ + const struct aspeed_gpio_bank *bank = to_bank(offset); + const u32 mask = GPIO_BIT(offset); + void __iomem *addr; + u32 val; + + addr = bank_debounce_reg(gpio, bank, GPIO_DEBOUNCE_SEL1); + val = ioread32(addr); + iowrite32((val & ~mask) | GPIO_SET_DEBOUNCE1(timer, offset), addr); + + addr = bank_debounce_reg(gpio, bank, GPIO_DEBOUNCE_SEL2); + val = ioread32(addr); + iowrite32((val & ~mask) | GPIO_SET_DEBOUNCE2(timer, offset), addr); +} + +static int enable_debounce(struct gpio_chip *chip, unsigned int offset, + unsigned long usecs) +{ + struct aspeed_gpio *gpio = gpiochip_get_data(chip); + u32 requested_cycles; + unsigned long flags; + int rc; + int i; + + rc = usecs_to_cycles(gpio, usecs, &requested_cycles); + if (rc < 0) { + dev_warn(chip->parent, "Failed to convert %luus to cycles at %luHz: %d\n", + usecs, clk_get_rate(gpio->clk), rc); + return rc; + } + + spin_lock_irqsave(&gpio->lock, flags); + + if (timer_allocation_registered(gpio, offset)) { + rc = unregister_allocated_timer(gpio, offset); + if (rc < 0) + goto out; + } + + /* Try to find a timer already configured for the debounce period */ + for (i = 1; i < ARRAY_SIZE(debounce_timers); i++) { + u32 cycles; + + cycles = ioread32(gpio->base + debounce_timers[i]); + if (requested_cycles == cycles) + break; + } + + if (i == ARRAY_SIZE(debounce_timers)) { + int j; + + /* + * As there are no timers configured for the requested debounce + * period, find an unused timer instead + */ + for (j = 1; j < ARRAY_SIZE(gpio->timer_users); j++) { + if (gpio->timer_users[j] == 0) + break; + } + + if (j == ARRAY_SIZE(gpio->timer_users)) { + dev_warn(chip->parent, + "Debounce timers exhausted, cannot debounce for period %luus\n", + usecs); + + rc = -EPERM; + + /* + * We already adjusted the accounting to remove @offset + * as a user of its previous timer, so also configure + * the hardware so @offset has timers disabled for + * consistency. + */ + configure_timer(gpio, offset, 0); + goto out; + } + + i = j; + + iowrite32(requested_cycles, gpio->base + debounce_timers[i]); + } + + if (WARN(i == 0, "Cannot register index of disabled timer\n")) { + rc = -EINVAL; + goto out; + } + + register_allocated_timer(gpio, offset, i); + configure_timer(gpio, offset, i); + +out: + spin_unlock_irqrestore(&gpio->lock, flags); + + return rc; +} + +static int disable_debounce(struct gpio_chip *chip, unsigned int offset) +{ + struct aspeed_gpio *gpio = gpiochip_get_data(chip); + unsigned long flags; + int rc; + + spin_lock_irqsave(&gpio->lock, flags); + + rc = unregister_allocated_timer(gpio, offset); + if (!rc) + configure_timer(gpio, offset, 0); + + spin_unlock_irqrestore(&gpio->lock, flags); + + return rc; +} + +static int set_debounce(struct gpio_chip *chip, unsigned int offset, + unsigned long usecs) +{ + struct aspeed_gpio *gpio = gpiochip_get_data(chip); + + if (!have_debounce(gpio, offset)) + return -ENOTSUPP; + + if (usecs) + return enable_debounce(chip, offset, usecs); + + return disable_debounce(chip, offset); +} + +static int aspeed_gpio_set_config(struct gpio_chip *chip, unsigned int offset, + unsigned long config) +{ + unsigned long param = pinconf_to_config_param(config); + u32 arg = pinconf_to_config_argument(config); + + if (param == PIN_CONFIG_INPUT_DEBOUNCE) + return set_debounce(chip, offset, arg); + else if (param == PIN_CONFIG_BIAS_DISABLE || + param == PIN_CONFIG_BIAS_PULL_DOWN || + param == PIN_CONFIG_DRIVE_STRENGTH) + return pinctrl_gpio_set_config(offset, config); + + return -ENOTSUPP; +} + /* * Any banks not specified in a struct aspeed_bank_props array are assumed to * have the properties: @@ -565,8 +824,16 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) if (!gpio_id) return -EINVAL; + gpio->clk = of_clk_get(pdev->dev.of_node, 0); + if (IS_ERR(gpio->clk)) { + dev_warn(&pdev->dev, + "No HPLL clock phandle provided, debouncing disabled\n"); + gpio->clk = NULL; + } + gpio->config = gpio_id->data; + gpio->chip.parent = &pdev->dev; gpio->chip.ngpio = gpio->config->nr_gpios; gpio->chip.parent = &pdev->dev; gpio->chip.direction_input = aspeed_gpio_dir_in; @@ -576,6 +843,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) gpio->chip.free = aspeed_gpio_free; gpio->chip.get = aspeed_gpio_get; gpio->chip.set = aspeed_gpio_set; + gpio->chip.set_config = aspeed_gpio_set_config; gpio->chip.label = dev_name(&pdev->dev); gpio->chip.base = -1; gpio->chip.irq_need_valid_mask = true; @@ -584,6 +852,9 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) if (rc < 0) return rc; + gpio->offset_timer = + devm_kzalloc(&pdev->dev, gpio->chip.ngpio, GFP_KERNEL); + return aspeed_gpio_setup_irqs(gpio, pdev); } From c3bafe017c3bd3f68c21637ce4b78963edf56ec5 Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Fri, 7 Apr 2017 22:29:02 +0930 Subject: [PATCH 66/77] gpio: aspeed: Add open-source and open-drain support As per the datasheet, manage the IO and value states to implement open-source/open-drain, but do this by falling back to gpiolib's emulation. This commit simply makes the behaviour explicit for clarity, rather than relying on the implicit return of -ENOTSUPP to trigger the emulation. Signed-off-by: Andrew Jeffery Signed-off-by: Linus Walleij --- drivers/gpio/gpio-aspeed.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index 3327a48df862..ccea609676ee 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -761,6 +761,10 @@ static int aspeed_gpio_set_config(struct gpio_chip *chip, unsigned int offset, param == PIN_CONFIG_BIAS_PULL_DOWN || param == PIN_CONFIG_DRIVE_STRENGTH) return pinctrl_gpio_set_config(offset, config); + else if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN || + param == PIN_CONFIG_DRIVE_OPEN_SOURCE) + /* Return -ENOTSUPP to trigger emulation, as per datasheet */ + return -ENOTSUPP; return -ENOTSUPP; } From 5664aa1c9ef59895eee1af15e36140d09d20714d Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Thu, 13 Apr 2017 17:46:39 +0800 Subject: [PATCH 67/77] gpio: dwapb: use dwapb_read instead of readl_relaxed Commit 67809b974a07 ("GPIO: gpio-dwapb: Change readl&writel to dwapb_read&dwapb_write") missed this readl_relaxed() usage, I'm not sure the reason, maybe for performance reason? But if we do care the performance, we could use the relaxed io in dwapb_read and dwapb_write. Signed-off-by: Jisheng Zhang Signed-off-by: Linus Walleij --- drivers/gpio/gpio-dwapb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 53ade0b69f49..f051c4552af5 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -164,7 +164,7 @@ static void dwapb_toggle_trigger(struct dwapb_gpio *gpio, unsigned int offs) static u32 dwapb_do_irq(struct dwapb_gpio *gpio) { - u32 irq_status = readl_relaxed(gpio->regs + GPIO_INTSTATUS); + u32 irq_status = dwapb_read(gpio, GPIO_INTSTATUS); u32 ret = irq_status; while (irq_status) { From 7c2d176fe3f8dce632b948f79c7e89916ffe2c70 Mon Sep 17 00:00:00 2001 From: Kuppuswamy Sathyanarayanan Date: Fri, 14 Apr 2017 10:29:25 -0700 Subject: [PATCH 68/77] gpio: gpio-wcove: fix irq pending status bit width Whiskey cove PMIC has three GPIO banks with total number of 13 GPIO pins. But when checking for the pending status, for_each_set_bit() uses bit width of 7 and hence it only checks the status for first 7 GPIO pins missing to check/clear the status of rest of the GPIO pins. This patch fixes this issue. Signed-off-by: Kuppuswamy Sathyanarayanan Signed-off-by: Linus Walleij --- drivers/gpio/gpio-wcove.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-wcove.c b/drivers/gpio/gpio-wcove.c index 97613de5304e..bf7b71d7cf5b 100644 --- a/drivers/gpio/gpio-wcove.c +++ b/drivers/gpio/gpio-wcove.c @@ -317,7 +317,7 @@ static irqreturn_t wcove_gpio_irq_handler(int irq, void *data) while (pending) { /* One iteration is for all pending bits */ for_each_set_bit(gpio, (const unsigned long *)&pending, - GROUP0_NR_IRQS) { + WCOVE_GPIO_NUM) { offset = (gpio > GROUP0_NR_IRQS) ? 1 : 0; mask = (offset == 1) ? BIT(gpio - GROUP0_NR_IRQS) : BIT(gpio); From 7b7df5204d6fd6316495e6becfbc6277bf1371cc Mon Sep 17 00:00:00 2001 From: Nandor Han Date: Thu, 13 Apr 2017 13:27:48 +0300 Subject: [PATCH 69/77] dt-bindings: add exar to vendor prefixes list Add Exar Corporation to vendors list. Signed-off-by: Nandor Han Acked-by: Rob Herring Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index ec0bfb9bbebd..d941ce79da9b 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -102,6 +102,7 @@ ettus NI Ettus Research eukrea EukrĂ©a Electromatique everest Everest Semiconductor Co. Ltd. everspin Everspin Technologies, Inc. +exar Exar Corporation excito Excito ezchip EZchip Semiconductor faraday Faraday Technology Corporation From 42fcb203e3a8682c41b6a22d2b3fd1457b407fb9 Mon Sep 17 00:00:00 2001 From: Nandor Han Date: Thu, 13 Apr 2017 13:27:50 +0300 Subject: [PATCH 70/77] gpio: Add XRA1403 DTS binding documentation Add the XRA1403 DTS binding documentation. Signed-off-by: Nandor Han Acked-by: Rob Herring Signed-off-by: Linus Walleij --- .../devicetree/bindings/gpio/gpio-xra1403.txt | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/gpio-xra1403.txt diff --git a/Documentation/devicetree/bindings/gpio/gpio-xra1403.txt b/Documentation/devicetree/bindings/gpio/gpio-xra1403.txt new file mode 100644 index 000000000000..e13cc399b363 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-xra1403.txt @@ -0,0 +1,46 @@ +GPIO Driver for XRA1403 16-BIT GPIO Expander With Reset Input from EXAR + +The XRA1403 is an 16-bit GPIO expander with an SPI interface. Features available: + - Individually programmable inputs: + - Internal pull-up resistors + - Polarity inversion + - Individual interrupt enable + - Rising edge and/or Falling edge interrupt + - Input filter + - Individually programmable outputs + - Output Level Control + - Output Three-State Control + +Properties +---------- +Check documentation for SPI and GPIO controllers regarding properties needed to configure the node. + + - compatible = "exar,xra1403". + - reg - SPI id of the device. + - gpio-controller - marks the node as gpio. + - #gpio-cells - should be two where the first cell is the pin number + and the second one is used for optional parameters. + +Optional properties: +------------------- + - reset-gpios: in case available used to control the device reset line. + - interrupt-controller - marks the node as interrupt controller. + - #interrupt-cells - should be two and represents the number of cells + needed to encode interrupt source. + +Example +-------- + + gpioxra0: gpio@2 { + compatible = "exar,xra1403"; + reg = <2>; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + + reset-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>; + spi-max-frequency = <1000000>; + }; From 64c6a71126fdeb2d60e193b93e24ea5ffa9c40ba Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Wed, 19 Apr 2017 10:30:44 +0100 Subject: [PATCH 71/77] gpio: arizona: Correct check whether the pin is an input The logic to check if the pin is an input or output whilst testing if we need to read the register value from the hardware or not is currently inverted. Remove the erroneous not from the if statement. Fixes: 11598d174050 ("gpio: arizona: Correct handling for reading input GPIOs") Signed-off-by: Charles Keepax Signed-off-by: Linus Walleij --- drivers/gpio/gpio-arizona.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c index 60b3102279f3..cd23fd727f95 100644 --- a/drivers/gpio/gpio-arizona.c +++ b/drivers/gpio/gpio-arizona.c @@ -51,7 +51,7 @@ static int arizona_gpio_get(struct gpio_chip *chip, unsigned offset) return ret; /* Resume to read actual registers for input pins */ - if (!(val & ARIZONA_GPN_DIR)) { + if (val & ARIZONA_GPN_DIR) { ret = pm_runtime_get_sync(chip->parent); if (ret < 0) { dev_err(chip->parent, "Failed to resume: %d\n", ret); From 1b9a0c25065c174134494d1ca91f4da8430e6902 Mon Sep 17 00:00:00 2001 From: Anders Darander Date: Fri, 21 Apr 2017 14:46:30 +0200 Subject: [PATCH 72/77] gpio: move tca9554 from pcf857x to pca953x The TCA9554 doesn't work with the pcf857x driver, trying to change the direction gives a NAK bailout error. TCA9554 is similar to the PCA9554, thus change the driver. Signed-off-by: Anders Darander Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 2 +- drivers/gpio/gpio-pca953x.c | 1 + drivers/gpio/gpio-pcf857x.c | 2 -- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 63ceed246b6f..c0629e6639fa 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -752,7 +752,7 @@ config GPIO_PCA953X 4 bits: pca9536, pca9537 8 bits: max7310, max7315, pca6107, pca9534, pca9538, pca9554, - pca9556, pca9557, pca9574, tca6408, xra1202 + pca9556, pca9557, pca9574, tca6408, tca9554, xra1202 16 bits: max7312, max7313, pca9535, pca9539, pca9555, pca9575, tca6416 diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index b9373785ccf5..4c9e21300a26 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -82,6 +82,7 @@ static const struct i2c_device_id pca953x_id[] = { { "tca6416", 16 | PCA953X_TYPE | PCA_INT, }, { "tca6424", 24 | PCA953X_TYPE | PCA_INT, }, { "tca9539", 16 | PCA953X_TYPE | PCA_INT, }, + { "tca9554", 8 | PCA953X_TYPE | PCA_INT, }, { "xra1202", 8 | PCA953X_TYPE }, { } }; diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index 895af42a4513..8ddf9302ce3b 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c @@ -46,7 +46,6 @@ static const struct i2c_device_id pcf857x_id[] = { { "pca9675", 16 }, { "max7328", 8 }, { "max7329", 8 }, - { "tca9554", 8 }, { } }; MODULE_DEVICE_TABLE(i2c, pcf857x_id); @@ -66,7 +65,6 @@ static const struct of_device_id pcf857x_of_table[] = { { .compatible = "nxp,pca9675" }, { .compatible = "maxim,max7328" }, { .compatible = "maxim,max7329" }, - { .compatible = "ti,tca9554" }, { } }; MODULE_DEVICE_TABLE(of, pcf857x_of_table); From fa2f60ffa0e0a33406ef9538635a57ac499965ae Mon Sep 17 00:00:00 2001 From: Anders Darander Date: Fri, 21 Apr 2017 14:46:31 +0200 Subject: [PATCH 73/77] gpio: DT bindings, move tca9554 from pcf857x to pca953x The TCA9554 is similar to the PCA9554. Update the DT binding docs. Signed-off-by: Anders Darander Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/gpio/gpio-pca953x.txt | 1 + Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt b/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt index e63935710011..7f57271df2bc 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt @@ -26,6 +26,7 @@ Required properties: ti,tca6416 ti,tca6424 ti,tca9539 + ti,tca9554 onsemi,pca9654 exar,xra1202 diff --git a/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt b/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt index ada4e2973323..7d3bd631d011 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt @@ -25,7 +25,6 @@ Required Properties: - "nxp,pcf8574": For the NXP PCF8574 - "nxp,pcf8574a": For the NXP PCF8574A - "nxp,pcf8575": For the NXP PCF8575 - - "ti,tca9554": For the TI TCA9554 - reg: I2C slave address. From 881ebd229f4a5ea88f269c1225245e50db9ba303 Mon Sep 17 00:00:00 2001 From: Kuppuswamy Sathyanarayanan Date: Mon, 24 Apr 2017 12:15:04 -0700 Subject: [PATCH 74/77] gpio: gpio-wcove: fix GPIO IRQ status mask According to Whiskey Cove PMIC spec, bit 7 of GPIOIRQ0_REG belongs to battery IO. So we should skip this bit when checking for GPIO IRQ pending status. Otherwise, wcove_gpio_irq_handler() might go into the infinite loop until IRQ "pending" status becomes 0. This patch fixes this issue. Signed-off-by: Kuppuswamy Sathyanarayanan Acked-by: Mika Westerberg Acked-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-wcove.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-wcove.c b/drivers/gpio/gpio-wcove.c index bf7b71d7cf5b..7b1bc20be209 100644 --- a/drivers/gpio/gpio-wcove.c +++ b/drivers/gpio/gpio-wcove.c @@ -51,6 +51,8 @@ #define GROUP1_NR_IRQS 6 #define IRQ_MASK_BASE 0x4e19 #define IRQ_STATUS_BASE 0x4e0b +#define GPIO_IRQ0_MASK GENMASK(6, 0) +#define GPIO_IRQ1_MASK GENMASK(5, 0) #define UPDATE_IRQ_TYPE BIT(0) #define UPDATE_IRQ_MASK BIT(1) @@ -309,7 +311,7 @@ static irqreturn_t wcove_gpio_irq_handler(int irq, void *data) return IRQ_NONE; } - pending = p[0] | (p[1] << 8); + pending = (p[0] & GPIO_IRQ0_MASK) | ((p[1] & GPIO_IRQ1_MASK) << 7); if (!pending) return IRQ_NONE; @@ -333,7 +335,7 @@ static irqreturn_t wcove_gpio_irq_handler(int irq, void *data) break; } - pending = p[0] | (p[1] << 8); + pending = (p[0] & GPIO_IRQ0_MASK) | ((p[1] & GPIO_IRQ1_MASK) << 7); } return IRQ_HANDLED; From 9384793036afb7529c1c564e839ef4356271d68e Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 25 Apr 2017 20:32:09 +0200 Subject: [PATCH 75/77] gpio: Add ROHM BD9571MWV-M PMIC GPIO driver Add driver for the GPIO block in the ROHM BD9571MWV-W MFD PMIC. This block is pretty trivial and supports setting GPIO direction as Input/Output and in case of Output, supports setting value. Signed-off-by: Marek Vasut Cc: linux-gpio@vger.kernel.org Cc: Geert Uytterhoeven Cc: Linus Walleij Reviewed-by: Linus Walleij Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 11 +++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-bd9571mwv.c | 144 ++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 drivers/gpio/gpio-bd9571mwv.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index c0629e6639fa..5662b0580777 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -844,6 +844,17 @@ config GPIO_ARIZONA help Support for GPIOs on Wolfson Arizona class devices. +config GPIO_BD9571MWV + tristate "ROHM BD9571 GPIO support" + depends on MFD_BD9571MWV + help + Support for GPIOs on ROHM BD9571 PMIC. There are two GPIOs + available on the ROHM PMIC in total, both of which can also + generate interrupts. + + This driver can also be built as a module. If so, the module + will be called gpio-bd9571mwv. + config GPIO_CRYSTAL_COVE tristate "GPIO support for Crystal Cove PMIC" depends on (X86 || COMPILE_TEST) && INTEL_SOC_PMIC diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 095598e856ca..68b96277d9fa 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o obj-$(CONFIG_GPIO_AXP209) += gpio-axp209.o obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o +obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o diff --git a/drivers/gpio/gpio-bd9571mwv.c b/drivers/gpio/gpio-bd9571mwv.c new file mode 100644 index 000000000000..5224a946e8ab --- /dev/null +++ b/drivers/gpio/gpio-bd9571mwv.c @@ -0,0 +1,144 @@ +/* + * ROHM BD9571MWV-M GPIO driver + * + * Copyright (C) 2017 Marek Vasut + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether expressed or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License version 2 for more details. + * + * Based on the TPS65086 driver + * + * NOTE: Interrupts are not supported yet. + */ + +#include +#include +#include + +#include + +struct bd9571mwv_gpio { + struct gpio_chip chip; + struct bd9571mwv *bd; +}; + +static int bd9571mwv_gpio_get_direction(struct gpio_chip *chip, + unsigned int offset) +{ + struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); + int ret, val; + + ret = regmap_read(gpio->bd->regmap, BD9571MWV_GPIO_DIR, &val); + if (ret < 0) + return ret; + + return val & BIT(offset); +} + +static int bd9571mwv_gpio_direction_input(struct gpio_chip *chip, + unsigned int offset) +{ + struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); + + regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_DIR, + BIT(offset), 0); + + return 0; +} + +static int bd9571mwv_gpio_direction_output(struct gpio_chip *chip, + unsigned int offset, int value) +{ + struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); + + /* Set the initial value */ + regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_OUT, + BIT(offset), value ? BIT(offset) : 0); + regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_DIR, + BIT(offset), BIT(offset)); + + return 0; +} + +static int bd9571mwv_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); + int ret, val; + + ret = regmap_read(gpio->bd->regmap, BD9571MWV_GPIO_IN, &val); + if (ret < 0) + return ret; + + return val & BIT(offset); +} + +static void bd9571mwv_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + struct bd9571mwv_gpio *gpio = gpiochip_get_data(chip); + + regmap_update_bits(gpio->bd->regmap, BD9571MWV_GPIO_OUT, + BIT(offset), value ? BIT(offset) : 0); +} + +static const struct gpio_chip template_chip = { + .label = "bd9571mwv-gpio", + .owner = THIS_MODULE, + .get_direction = bd9571mwv_gpio_get_direction, + .direction_input = bd9571mwv_gpio_direction_input, + .direction_output = bd9571mwv_gpio_direction_output, + .get = bd9571mwv_gpio_get, + .set = bd9571mwv_gpio_set, + .base = -1, + .ngpio = 2, + .can_sleep = true, +}; + +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->bd = dev_get_drvdata(pdev->dev.parent); + gpio->chip = template_chip; + gpio->chip.parent = gpio->bd->dev; + + 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; +} + +static const struct platform_device_id bd9571mwv_gpio_id_table[] = { + { "bd9571mwv-gpio", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, bd9571mwv_gpio_id_table); + +static struct platform_driver bd9571mwv_gpio_driver = { + .driver = { + .name = "bd9571mwv-gpio", + }, + .probe = bd9571mwv_gpio_probe, + .id_table = bd9571mwv_gpio_id_table, +}; +module_platform_driver(bd9571mwv_gpio_driver); + +MODULE_AUTHOR("Marek Vasut "); +MODULE_DESCRIPTION("BD9571MWV GPIO driver"); +MODULE_LICENSE("GPL v2"); From 83977443938122baeed28dc9f078db3da9855f7c Mon Sep 17 00:00:00 2001 From: David Rivshin Date: Mon, 24 Apr 2017 18:56:50 -0400 Subject: [PATCH 76/77] gpio: omap: return error if requested debounce time is not possible omap_gpio_debounce() does not validate that the requested debounce is within a range it can handle. Instead it lets the register value wrap silently, and always returns success. This can lead to all sorts of unexpected behavior, such as gpio_keys asking for a too-long debounce, but getting a very short debounce in practice. Fix this by returning -EINVAL if the requested value does not fit into the register field. If there is no debounce clock available at all, return -ENOTSUPP. Fixes: e85ec6c3047b ("gpio: omap: fix omap2_set_gpio_debounce") Cc: # 4.3+ Signed-off-by: David Rivshin Acked-by: Grygorii Strashko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 5d6a5744352f..f8c550de6c72 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -208,9 +208,11 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank) * OMAP's debounce time is in 31us steps * = (GPIO_DEBOUNCINGTIME[7:0].DEBOUNCETIME + 1) x 31 * so we need to convert and round up to the closest unit. + * + * Return: 0 on success, negative error otherwise. */ -static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset, - unsigned debounce) +static int omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset, + unsigned debounce) { void __iomem *reg; u32 val; @@ -218,11 +220,12 @@ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset, bool enable = !!debounce; if (!bank->dbck_flag) - return; + return -ENOTSUPP; if (enable) { debounce = DIV_ROUND_UP(debounce, 31) - 1; - debounce &= OMAP4_GPIO_DEBOUNCINGTIME_MASK; + if ((debounce & OMAP4_GPIO_DEBOUNCINGTIME_MASK) != debounce) + return -EINVAL; } l = BIT(offset); @@ -255,6 +258,8 @@ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset, bank->context.debounce = debounce; bank->context.debounce_en = val; } + + return 0; } /** @@ -964,14 +969,20 @@ static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset, { struct gpio_bank *bank; unsigned long flags; + int ret; bank = gpiochip_get_data(chip); raw_spin_lock_irqsave(&bank->lock, flags); - omap2_set_gpio_debounce(bank, offset, debounce); + ret = omap2_set_gpio_debounce(bank, offset, debounce); raw_spin_unlock_irqrestore(&bank->lock, flags); - return 0; + if (ret) + dev_info(chip->parent, + "Could not set line %u debounce to %u microseconds (%d)", + offset, debounce, ret); + + return ret; } static int omap_gpio_set_config(struct gpio_chip *chip, unsigned offset, From b86c86aa9805b25ee70071d084e618b2c40641b5 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 26 Apr 2017 22:08:15 +0300 Subject: [PATCH 77/77] gpio: f7188x: Add a missing break A break statement was obviously intended here. Fixes: d69843e416d3 ("gpio: f7188x: Add F71889A GPIO support.") Signed-off-by: Dan Carpenter Signed-off-by: Linus Walleij --- drivers/gpio/gpio-f7188x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c index c013ff5deb70..13350c9d7f5e 100644 --- a/drivers/gpio/gpio-f7188x.c +++ b/drivers/gpio/gpio-f7188x.c @@ -398,6 +398,7 @@ static int f7188x_gpio_probe(struct platform_device *pdev) case f71889a: data->nr_bank = ARRAY_SIZE(f71889a_gpio_bank); data->bank = f71889a_gpio_bank; + break; case f71889f: data->nr_bank = ARRAY_SIZE(f71889_gpio_bank); data->bank = f71889_gpio_bank;