From 66ad66293edeb2bcc27a329f35018b18601da452 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 11 Jul 2019 10:29:36 +0200 Subject: [PATCH 01/82] gpio: em: use a helper variable for &pdev->dev Instead of always dereferencing &pdev->dev, just assign a helper local variable of type struct device * and use it where applicable. Signed-off-by: Bartosz Golaszewski Reviewed-by: Geert Uytterhoeven --- drivers/gpio/gpio-em.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index a87951293aaa..620f25b7efb4 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -272,11 +272,12 @@ static int em_gio_probe(struct platform_device *pdev) struct resource *io[2], *irq[2]; struct gpio_chip *gpio_chip; struct irq_chip *irq_chip; - const char *name = dev_name(&pdev->dev); + struct device *dev = &pdev->dev; + const char *name = dev_name(dev); unsigned int ngpios; int ret; - p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); + p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL); if (!p) return -ENOMEM; @@ -290,27 +291,27 @@ static int em_gio_probe(struct platform_device *pdev) irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1); if (!io[0] || !io[1] || !irq[0] || !irq[1]) { - dev_err(&pdev->dev, "missing IRQ or IOMEM\n"); + dev_err(dev, "missing IRQ or IOMEM\n"); return -EINVAL; } - p->base0 = devm_ioremap_nocache(&pdev->dev, io[0]->start, + p->base0 = devm_ioremap_nocache(dev, io[0]->start, resource_size(io[0])); if (!p->base0) return -ENOMEM; - p->base1 = devm_ioremap_nocache(&pdev->dev, io[1]->start, + p->base1 = devm_ioremap_nocache(dev, io[1]->start, resource_size(io[1])); if (!p->base1) return -ENOMEM; - if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) { - dev_err(&pdev->dev, "Missing ngpios OF property\n"); + if (of_property_read_u32(dev->of_node, "ngpios", &ngpios)) { + dev_err(dev, "Missing ngpios OF property\n"); return -EINVAL; } gpio_chip = &p->gpio_chip; - gpio_chip->of_node = pdev->dev.of_node; + gpio_chip->of_node = dev->of_node; gpio_chip->direction_input = em_gio_direction_input; gpio_chip->get = em_gio_get; gpio_chip->direction_output = em_gio_direction_output; @@ -319,7 +320,7 @@ static int em_gio_probe(struct platform_device *pdev) gpio_chip->request = em_gio_request; gpio_chip->free = em_gio_free; gpio_chip->label = name; - gpio_chip->parent = &pdev->dev; + gpio_chip->parent = dev; gpio_chip->owner = THIS_MODULE; gpio_chip->base = -1; gpio_chip->ngpio = ngpios; @@ -333,33 +334,33 @@ static int em_gio_probe(struct platform_device *pdev) irq_chip->irq_release_resources = em_gio_irq_relres; irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND; - p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, ngpios, 0, + p->irq_domain = irq_domain_add_simple(dev->of_node, ngpios, 0, &em_gio_irq_domain_ops, p); if (!p->irq_domain) { - dev_err(&pdev->dev, "cannot initialize irq domain\n"); + dev_err(dev, "cannot initialize irq domain\n"); return -ENXIO; } - ret = devm_add_action_or_reset(&pdev->dev, em_gio_irq_domain_remove, + ret = devm_add_action_or_reset(dev, em_gio_irq_domain_remove, p->irq_domain); if (ret) return ret; - if (devm_request_irq(&pdev->dev, irq[0]->start, + if (devm_request_irq(dev, irq[0]->start, em_gio_irq_handler, 0, name, p)) { - dev_err(&pdev->dev, "failed to request low IRQ\n"); + dev_err(dev, "failed to request low IRQ\n"); return -ENOENT; } - if (devm_request_irq(&pdev->dev, irq[1]->start, + if (devm_request_irq(dev, irq[1]->start, em_gio_irq_handler, 0, name, p)) { - dev_err(&pdev->dev, "failed to request high IRQ\n"); + dev_err(dev, "failed to request high IRQ\n"); return -ENOENT; } - ret = devm_gpiochip_add_data(&pdev->dev, gpio_chip, p); + ret = devm_gpiochip_add_data(dev, gpio_chip, p); if (ret) { - dev_err(&pdev->dev, "failed to add GPIO controller\n"); + dev_err(dev, "failed to add GPIO controller\n"); return ret; } From a7db285664dda63e066b943e6ec3c5f69473bf77 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Tue, 23 Jul 2019 16:39:24 +0800 Subject: [PATCH 02/82] gpio: pch: Use dev_get_drvdata Instead of using to_pci_dev + pci_get_drvdata, use dev_get_drvdata to make code simpler. Signed-off-by: Chuhong Yuan Acked-by: Bartosz Golaszewski Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-pch.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index 1d99293096f2..3f3d9a94b709 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -409,8 +409,7 @@ static int pch_gpio_probe(struct pci_dev *pdev, static int __maybe_unused pch_gpio_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct pch_gpio *chip = pci_get_drvdata(pdev); + struct pch_gpio *chip = dev_get_drvdata(dev); unsigned long flags; spin_lock_irqsave(&chip->spinlock, flags); @@ -422,8 +421,7 @@ static int __maybe_unused pch_gpio_suspend(struct device *dev) static int __maybe_unused pch_gpio_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct pch_gpio *chip = pci_get_drvdata(pdev); + struct pch_gpio *chip = dev_get_drvdata(dev); unsigned long flags; spin_lock_irqsave(&chip->spinlock, flags); From 2229a3618abdaac40c9e32754509357ed78c90f5 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 26 Jun 2019 11:34:18 +0200 Subject: [PATCH 03/82] unicore: Drop pointless include I can't see why this file includes , it is not using any of the interfaces. Lots of things are named "gpio" in the file but it is an irqchip driver and has nothing to do with the GPIO interfaces. Cc: Guan Xuetao Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190626093418.6263-1-linus.walleij@linaro.org --- arch/unicore32/kernel/irq.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/unicore32/kernel/irq.c b/arch/unicore32/kernel/irq.c index d1129828c41e..c014ae3c3e48 100644 --- a/arch/unicore32/kernel/irq.c +++ b/arch/unicore32/kernel/irq.c @@ -21,7 +21,6 @@ #include #include #include -#include #include From cbf2be749076c266f51cafc71dc9045bcad9ed05 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 28 Jun 2019 17:14:19 +0100 Subject: [PATCH 04/82] gpio: bd70528: fix spelling misstake "debouce" -> "debounce" There is a spelling mistake in a dev_err message. Fix it. Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190628161419.26439-1-colin.king@canonical.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-bd70528.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-bd70528.c b/drivers/gpio/gpio-bd70528.c index fd85605d2dab..633422b430b4 100644 --- a/drivers/gpio/gpio-bd70528.c +++ b/drivers/gpio/gpio-bd70528.c @@ -36,7 +36,7 @@ static int bd70528_set_debounce(struct bd70528_gpio *bdgpio, break; default: dev_err(bdgpio->chip.dev, - "Invalid debouce value %u\n", debounce); + "Invalid debounce value %u\n", debounce); return -EINVAL; } return regmap_update_bits(bdgpio->chip.regmap, GPIO_IN_REG(offset), From f8650b8ff6fd96075391e72bb3b6d0a99f27829d Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 29 Jun 2019 13:33:06 +0100 Subject: [PATCH 05/82] gpio: bd70528: remove redundant assignment to variable ret Variable ret is being initialized with a value that is never read and ret is being re-assigned a little later on. The assignment is redundant and hence can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190629123306.12519-1-colin.king@canonical.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-bd70528.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-bd70528.c b/drivers/gpio/gpio-bd70528.c index 633422b430b4..0c1ead12d883 100644 --- a/drivers/gpio/gpio-bd70528.c +++ b/drivers/gpio/gpio-bd70528.c @@ -153,7 +153,7 @@ static int bd70528_gpio_get_i(struct bd70528_gpio *bdgpio, unsigned int offset) static int bd70528_gpio_get(struct gpio_chip *chip, unsigned int offset) { - int ret = -EINVAL; + int ret; struct bd70528_gpio *bdgpio = gpiochip_get_data(chip); /* From f626d6dfb709852595e6fb24710819f9d21bc5ae Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 17 Jul 2019 09:10:01 +0200 Subject: [PATCH 06/82] gpio: of: Break out OF-only code The core gpiolib should not contain any OF/device tree-only code. Try to break out the main part of it and push it down into the optional gpiolib-of.c part of the library. Create a local gpiolib-of.h header and move stuff around a bit to get a clean cut. Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190717071001.3858-1-linus.walleij@linaro.org --- drivers/gpio/gpiolib-of.c | 114 ++++++++++++++++++++++++++++++++++++++ drivers/gpio/gpiolib-of.h | 45 +++++++++++++++ drivers/gpio/gpiolib.c | 113 +++---------------------------------- drivers/gpio/gpiolib.h | 27 --------- 4 files changed, 167 insertions(+), 132 deletions(-) create mode 100644 drivers/gpio/gpiolib-of.h diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 567fb98c0892..b10d04dd9296 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -21,6 +21,34 @@ #include #include "gpiolib.h" +#include "gpiolib-of.h" + +/* + * This is used by external users of of_gpio_count() from + * + * FIXME: get rid of those external users by converting them to GPIO + * descriptors and let them all use gpiod_get_count() + */ +int of_gpio_get_count(struct device *dev, const char *con_id) +{ + int ret; + char propname[32]; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) { + if (con_id) + snprintf(propname, sizeof(propname), "%s-%s", + con_id, gpio_suffixes[i]); + else + snprintf(propname, sizeof(propname), "%s", + gpio_suffixes[i]); + + ret = of_gpio_named_count(dev->of_node, propname); + if (ret > 0) + break; + } + return ret ? ret : -ENOENT; +} static int of_gpiochip_match_node_and_xlate(struct gpio_chip *chip, void *data) { @@ -53,6 +81,23 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip, return gpiochip_get_desc(chip, ret); } +/** + * of_gpio_need_valid_mask() - figure out if the OF GPIO driver needs + * to set the .valid_mask + * @dev: the device for the GPIO provider + * @return: true if the valid mask needs to be set + */ +bool of_gpio_need_valid_mask(struct gpio_chip *gc) +{ + int size; + struct device_node *np = gc->of_node; + + size = of_property_count_u32_elems(np, "gpio-reserved-ranges"); + if (size > 0 && size % 2 == 0) + return true; + return false; +} + static void of_gpio_flags_quirks(struct device_node *np, const char *propname, enum of_gpio_flags *flags, @@ -231,6 +276,75 @@ int of_get_named_gpio_flags(struct device_node *np, const char *list_name, } EXPORT_SYMBOL(of_get_named_gpio_flags); +/** + * gpiod_get_from_of_node() - obtain a GPIO from an OF node + * @node: handle of the OF node + * @propname: name of the DT property representing the GPIO + * @index: index of the GPIO to obtain for the consumer + * @dflags: GPIO initialization flags + * @label: label to attach to the requested GPIO + * + * Returns: + * On successful request the GPIO pin is configured in accordance with + * provided @dflags. + * + * In case of error an ERR_PTR() is returned. + */ +struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, + const char *propname, int index, + enum gpiod_flags dflags, + const char *label) +{ + unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT; + struct gpio_desc *desc; + enum of_gpio_flags flags; + bool active_low = false; + bool single_ended = false; + bool open_drain = false; + bool transitory = false; + int ret; + + desc = of_get_named_gpiod_flags(node, propname, + index, &flags); + + if (!desc || IS_ERR(desc)) { + return desc; + } + + active_low = flags & OF_GPIO_ACTIVE_LOW; + single_ended = flags & OF_GPIO_SINGLE_ENDED; + open_drain = flags & OF_GPIO_OPEN_DRAIN; + transitory = flags & OF_GPIO_TRANSITORY; + + ret = gpiod_request(desc, label); + if (ret == -EBUSY && (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE)) + return desc; + if (ret) + return ERR_PTR(ret); + + if (active_low) + lflags |= GPIO_ACTIVE_LOW; + + if (single_ended) { + if (open_drain) + lflags |= GPIO_OPEN_DRAIN; + else + lflags |= GPIO_OPEN_SOURCE; + } + + if (transitory) + lflags |= GPIO_TRANSITORY; + + ret = gpiod_configure_flags(desc, propname, lflags, dflags); + if (ret < 0) { + gpiod_put(desc); + return ERR_PTR(ret); + } + + return desc; +} +EXPORT_SYMBOL(gpiod_get_from_of_node); + /* * The SPI GPIO bindings happened before we managed to establish that GPIO * properties should be named "foo-gpios" so we have this special kludge for diff --git a/drivers/gpio/gpiolib-of.h b/drivers/gpio/gpiolib-of.h new file mode 100644 index 000000000000..34954921d96e --- /dev/null +++ b/drivers/gpio/gpiolib-of.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef GPIOLIB_OF_H +#define GPIOLIB_OF_H + +struct gpio_chip; +enum of_gpio_flags; + +#ifdef CONFIG_OF_GPIO +struct gpio_desc *of_find_gpio(struct device *dev, + const char *con_id, + unsigned int idx, + unsigned long *lookupflags); +struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, + const char *list_name, int index, enum of_gpio_flags *flags); +int of_gpiochip_add(struct gpio_chip *gc); +void of_gpiochip_remove(struct gpio_chip *gc); +int of_gpio_get_count(struct device *dev, const char *con_id); +bool of_gpio_need_valid_mask(struct gpio_chip *gc); +#else +static inline struct gpio_desc *of_find_gpio(struct device *dev, + const char *con_id, + unsigned int idx, + unsigned long *lookupflags) +{ + return ERR_PTR(-ENOENT); +} +static inline struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, + const char *list_name, int index, enum of_gpio_flags *flags) +{ + return ERR_PTR(-ENOENT); +} +static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; } +static inline void of_gpiochip_remove(struct gpio_chip *gc) { } +static inline int of_gpio_get_count(struct device *dev, const char *con_id) +{ + return 0; +} +static inline bool of_gpio_need_valid_mask(struct gpio_chip *gc) +{ + return false; +} +#endif /* CONFIG_OF_GPIO */ + +#endif /* GPIOLIB_OF_H */ diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 3ee99d070608..03883f519d53 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -30,6 +29,7 @@ #include #include "gpiolib.h" +#include "gpiolib-of.h" #define CREATE_TRACE_POINTS #include @@ -360,22 +360,15 @@ static unsigned long *gpiochip_allocate_mask(struct gpio_chip *chip) return p; } -static int gpiochip_alloc_valid_mask(struct gpio_chip *gpiochip) +static int gpiochip_alloc_valid_mask(struct gpio_chip *gc) { -#ifdef CONFIG_OF_GPIO - int size; - struct device_node *np = gpiochip->of_node; - - size = of_property_count_u32_elems(np, "gpio-reserved-ranges"); - if (size > 0 && size % 2 == 0) - gpiochip->need_valid_mask = true; -#endif - - if (!gpiochip->need_valid_mask) + if (IS_ENABLED(CONFIG_OF_GPIO)) + gc->need_valid_mask = of_gpio_need_valid_mask(gc); + if (!gc->need_valid_mask) return 0; - gpiochip->valid_mask = gpiochip_allocate_mask(gpiochip); - if (!gpiochip->valid_mask) + gc->valid_mask = gpiochip_allocate_mask(gc); + if (!gc->valid_mask) return -ENOMEM; return 0; @@ -3993,27 +3986,6 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, return desc; } -static int dt_gpio_count(struct device *dev, const char *con_id) -{ - int ret; - char propname[32]; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) { - if (con_id) - snprintf(propname, sizeof(propname), "%s-%s", - con_id, gpio_suffixes[i]); - else - snprintf(propname, sizeof(propname), "%s", - gpio_suffixes[i]); - - ret = of_gpio_named_count(dev->of_node, propname); - if (ret > 0) - break; - } - return ret ? ret : -ENOENT; -} - static int platform_gpio_count(struct device *dev, const char *con_id) { struct gpiod_lookup_table *table; @@ -4046,7 +4018,7 @@ int gpiod_count(struct device *dev, const char *con_id) int count = -ENOENT; if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) - count = dt_gpio_count(dev, con_id); + count = of_gpio_get_count(dev, con_id); else if (IS_ENABLED(CONFIG_ACPI) && dev && ACPI_HANDLE(dev)) count = acpi_gpio_count(dev, con_id); @@ -4247,75 +4219,6 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, } EXPORT_SYMBOL_GPL(gpiod_get_index); -/** - * gpiod_get_from_of_node() - obtain a GPIO from an OF node - * @node: handle of the OF node - * @propname: name of the DT property representing the GPIO - * @index: index of the GPIO to obtain for the consumer - * @dflags: GPIO initialization flags - * @label: label to attach to the requested GPIO - * - * Returns: - * On successful request the GPIO pin is configured in accordance with - * provided @dflags. - * - * In case of error an ERR_PTR() is returned. - */ -struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, - const char *propname, int index, - enum gpiod_flags dflags, - const char *label) -{ - unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT; - struct gpio_desc *desc; - enum of_gpio_flags flags; - bool active_low = false; - bool single_ended = false; - bool open_drain = false; - bool transitory = false; - int ret; - - desc = of_get_named_gpiod_flags(node, propname, - index, &flags); - - if (!desc || IS_ERR(desc)) { - return desc; - } - - active_low = flags & OF_GPIO_ACTIVE_LOW; - single_ended = flags & OF_GPIO_SINGLE_ENDED; - open_drain = flags & OF_GPIO_OPEN_DRAIN; - transitory = flags & OF_GPIO_TRANSITORY; - - ret = gpiod_request(desc, label); - if (ret == -EBUSY && (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE)) - return desc; - if (ret) - return ERR_PTR(ret); - - if (active_low) - lflags |= GPIO_ACTIVE_LOW; - - if (single_ended) { - if (open_drain) - lflags |= GPIO_OPEN_DRAIN; - else - lflags |= GPIO_OPEN_SOURCE; - } - - if (transitory) - lflags |= GPIO_TRANSITORY; - - ret = gpiod_configure_flags(desc, propname, lflags, dflags); - if (ret < 0) { - gpiod_put(desc); - return ERR_PTR(ret); - } - - return desc; -} -EXPORT_SYMBOL(gpiod_get_from_of_node); - /** * fwnode_get_named_gpiod - obtain a GPIO from firmware node * @fwnode: handle of the firmware node diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 7c52c2442173..75d2e909d8c6 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -16,7 +16,6 @@ #include #include -enum of_gpio_flags; struct acpi_device; /** @@ -92,32 +91,6 @@ struct acpi_gpio_info { /* gpio suffixes used for ACPI and device tree lookup */ static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" }; -#ifdef CONFIG_OF_GPIO -struct gpio_desc *of_find_gpio(struct device *dev, - const char *con_id, - unsigned int idx, - unsigned long *lookupflags); -struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, - const char *list_name, int index, enum of_gpio_flags *flags); -int of_gpiochip_add(struct gpio_chip *gc); -void of_gpiochip_remove(struct gpio_chip *gc); -#else -static inline struct gpio_desc *of_find_gpio(struct device *dev, - const char *con_id, - unsigned int idx, - unsigned long *lookupflags) -{ - return ERR_PTR(-ENOENT); -} -static inline struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, - const char *list_name, int index, enum of_gpio_flags *flags) -{ - return ERR_PTR(-ENOENT); -} -static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; } -static inline void of_gpiochip_remove(struct gpio_chip *gc) { } -#endif /* CONFIG_OF_GPIO */ - #ifdef CONFIG_ACPI void acpi_gpiochip_add(struct gpio_chip *chip); void acpi_gpiochip_remove(struct gpio_chip *chip); From a299726da44fd679ce805aa80d7d6b559bac9874 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 3 Jul 2019 10:46:01 +0200 Subject: [PATCH 07/82] gpio: max77650: add MODULE_ALIAS() Define a MODULE_ALIAS() in the gpio sub-driver for max77650 so that the appropriate module gets loaded together with the core mfd driver. Signed-off-by: Bartosz Golaszewski Link: https://lore.kernel.org/r/20190703084601.9276-1-brgl@bgdev.pl Signed-off-by: Linus Walleij --- drivers/gpio/gpio-max77650.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-max77650.c b/drivers/gpio/gpio-max77650.c index 3f03f4e8956c..3075f2513c6f 100644 --- a/drivers/gpio/gpio-max77650.c +++ b/drivers/gpio/gpio-max77650.c @@ -188,3 +188,4 @@ module_platform_driver(max77650_gpio_driver); MODULE_DESCRIPTION("MAXIM 77650/77651 GPIO driver"); MODULE_AUTHOR("Bartosz Golaszewski "); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:max77650-gpio"); From 9091373ab7ea27cad381ce71aa37de6b9e687e81 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 30 Jul 2019 14:43:47 +0900 Subject: [PATCH 08/82] gpio: remove less important #ifdef around declarations The whole struct/function declarations in this header are surrounded by #ifdef. As far as I understood, the motivation of this is probably to break the build earlier if a driver misses to select or depend on correct CONFIG options in Kconfig. Since commit 94bed2a9c4ae ("Add -Werror-implicit-function-declaration") no one cannot call functions that have not been declared. So, I see some benefit in doing this in the cost of uglier headers. In reality, it would not be so easy to catch missed 'select' or 'depends on' because GPIOLIB, GPIOLIB_IRQCHIP etc. are already selected by someone else eventually. So, this kind of error, if any, will be caught by randconfig bots. In summary, I am not a big fan of cluttered #ifdef nesting, and this does not matter for normal developers. The code readability wins. Signed-off-by: Masahiro Yamada Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/driver.h | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 6a0e420915a3..f28f534f451a 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -20,9 +20,6 @@ struct module; enum gpiod_flags; enum gpio_lookup_flags; -#ifdef CONFIG_GPIOLIB - -#ifdef CONFIG_GPIOLIB_IRQCHIP /** * struct gpio_irq_chip - GPIO interrupt controller */ @@ -161,7 +158,6 @@ struct gpio_irq_chip { */ void (*irq_disable)(struct irq_data *data); }; -#endif /* CONFIG_GPIOLIB_IRQCHIP */ /** * struct gpio_chip - abstract a GPIO controller @@ -441,16 +437,12 @@ bool gpiochip_line_is_valid(const struct gpio_chip *chip, unsigned int offset); /* get driver data */ void *gpiochip_get_data(struct gpio_chip *chip); -struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc); - struct bgpio_pdata { const char *label; int base; int ngpio; }; -#if IS_ENABLED(CONFIG_GPIO_GENERIC) - int bgpio_init(struct gpio_chip *gc, struct device *dev, unsigned long sz, void __iomem *dat, void __iomem *set, void __iomem *clr, void __iomem *dirout, void __iomem *dirin, @@ -463,10 +455,6 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev, #define BGPIOF_READ_OUTPUT_REG_SET BIT(4) /* reg_set stores output value */ #define BGPIOF_NO_OUTPUT BIT(5) /* only input */ -#endif /* CONFIG_GPIO_GENERIC */ - -#ifdef CONFIG_GPIOLIB_IRQCHIP - int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq); void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq); @@ -555,15 +543,11 @@ static inline int gpiochip_irqchip_add_nested(struct gpio_chip *gpiochip, } #endif /* CONFIG_LOCKDEP */ -#endif /* CONFIG_GPIOLIB_IRQCHIP */ - int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset); void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset); int gpiochip_generic_config(struct gpio_chip *chip, unsigned offset, unsigned long config); -#ifdef CONFIG_PINCTRL - /** * struct gpio_pin_range - pin range controlled by a gpio chip * @node: list for maintaining set of pin ranges, used internally @@ -576,6 +560,8 @@ struct gpio_pin_range { struct pinctrl_gpio_range range; }; +#ifdef CONFIG_PINCTRL + int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, unsigned int gpio_offset, unsigned int pin_offset, unsigned int npins); @@ -586,8 +572,6 @@ void gpiochip_remove_pin_ranges(struct gpio_chip *chip); #else /* ! CONFIG_PINCTRL */ -struct pinctrl_dev; - static inline int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, unsigned int gpio_offset, unsigned int pin_offset, @@ -619,6 +603,11 @@ void gpiochip_free_own_desc(struct gpio_desc *desc); void devprop_gpiochip_set_names(struct gpio_chip *chip, const struct fwnode_handle *fwnode); + +#ifdef CONFIG_GPIOLIB + +struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc); + #else /* CONFIG_GPIOLIB */ static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) @@ -630,4 +619,4 @@ static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) #endif /* CONFIG_GPIOLIB */ -#endif +#endif /* __LINUX_GPIO_DRIVER_H */ From d9e5ebac18a122f53ee87671f62d42b0d9e9a491 Mon Sep 17 00:00:00 2001 From: Jeremy Cline Date: Mon, 29 Jul 2019 10:37:30 -0400 Subject: [PATCH 09/82] Documentation: gpio: fix function links in the HTML docs The shorthand [_data] and [devm_] cause the HTML documentation to not link to the function documentation properly. This expands the references to the complete function names with the exception of devm_gpiochip_remove() which was dropped by commit 48207d7595d2 ("gpio: drop devm_gpiochip_remove()"). Signed-off-by: Jeremy Cline Signed-off-by: Bartosz Golaszewski --- Documentation/driver-api/gpio/driver.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Documentation/driver-api/gpio/driver.rst b/Documentation/driver-api/gpio/driver.rst index 921c71a3d683..906af220b164 100644 --- a/Documentation/driver-api/gpio/driver.rst +++ b/Documentation/driver-api/gpio/driver.rst @@ -69,9 +69,9 @@ driver code: The code implementing a gpio_chip should support multiple instances of the controller, preferably using the driver model. That code will configure each -gpio_chip and issue ``gpiochip_add[_data]()`` or ``devm_gpiochip_add_data()``. -Removing a GPIO controller should be rare; use ``[devm_]gpiochip_remove()`` -when it is unavoidable. +gpio_chip and issue gpiochip_add(), gpiochip_add_data(), or +devm_gpiochip_add_data(). Removing a GPIO controller should be rare; use +gpiochip_remove() when it is unavoidable. Often a gpio_chip is part of an instance-specific structure with states not exposed by the GPIO interfaces, such as addressing, power management, and more. @@ -418,11 +418,11 @@ symbol: If there is a need to exclude certain GPIO lines from the IRQ domain handled by these helpers, we can set .irq.need_valid_mask of the gpiochip before -``[devm_]gpiochip_add_data()`` is called. This allocates an .irq.valid_mask with as -many bits set as there are GPIO lines in the chip, each bit representing line -0..n-1. Drivers can exclude GPIO lines by clearing bits from this mask. The mask -must be filled in before gpiochip_irqchip_add() or gpiochip_irqchip_add_nested() -is called. +devm_gpiochip_add_data() or gpiochip_add_data() is called. This allocates an +.irq.valid_mask with as many bits set as there are GPIO lines in the chip, each +bit representing line 0..n-1. Drivers can exclude GPIO lines by clearing bits +from this mask. The mask must be filled in before gpiochip_irqchip_add() or +gpiochip_irqchip_add_nested() is called. To use the helpers please keep the following in mind: From fce04b1ce8e326bf2cafaea4a0c91dbc3e99e403 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 30 Jul 2019 13:43:35 +0300 Subject: [PATCH 10/82] gpiolib: of: Reshuffle contents of consumer.h for new library layout Kernel build bot reported a compilation error after the commit f626d6dfb709 ("gpio: of: Break out OF-only code"): drivers/gpio/gpiolib-devres.o: In function `devm_gpiod_get_from_of_node': gpiolib-devres.c:(.text+0x19a): undefined reference to `gpiod_get_from_of_node' This happens due to move the latter under umbrella of CONFIG_OF_GPIO while customer.h contains staled data. Fix it by reshuffling contents of consumer.h to satisfy build dependencies. Reported-by: kbuild test robot Fixes: f626d6dfb709 ("gpio: of: Break out OF-only code"): Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190730104337.21235-1-andriy.shevchenko@linux.intel.com Signed-off-by: Linus Walleij --- include/linux/gpio/consumer.h | 78 +++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 9ddcf50a3c59..6019d4d128c5 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -170,18 +170,8 @@ struct gpio_desc *gpio_to_desc(unsigned gpio); int desc_to_gpio(const struct gpio_desc *desc); /* Child properties interface */ -struct device_node; struct fwnode_handle; -struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, - const char *propname, int index, - enum gpiod_flags dflags, - const char *label); -struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, - struct device_node *node, - const char *propname, int index, - enum gpiod_flags dflags, - const char *label); struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, const char *propname, int index, enum gpiod_flags dflags, @@ -530,28 +520,8 @@ static inline int desc_to_gpio(const struct gpio_desc *desc) } /* Child properties interface */ -struct device_node; struct fwnode_handle; -static inline -struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, - const char *propname, int index, - enum gpiod_flags dflags, - const char *label) -{ - return ERR_PTR(-ENOSYS); -} - -static inline -struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, - struct device_node *node, - const char *propname, int index, - enum gpiod_flags dflags, - const char *label) -{ - return ERR_PTR(-ENOSYS); -} - static inline struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, const char *propname, int index, @@ -584,6 +554,54 @@ struct gpio_desc *devm_fwnode_get_gpiod_from_child(struct device *dev, flags, label); } +#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_OF_GPIO) +struct device_node; + +struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, + const char *propname, int index, + enum gpiod_flags dflags, + const char *label); + +#else /* CONFIG_GPIOLIB && CONFIG_OF_GPIO */ + +struct device_node; + +static inline +struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, + const char *propname, int index, + enum gpiod_flags dflags, + const char *label) +{ + return ERR_PTR(-ENOSYS); +} + +#endif /* CONFIG_GPIOLIB && CONFIG_OF_GPIO */ + +#ifdef CONFIG_GPIOLIB +struct device_node; + +struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, + struct device_node *node, + const char *propname, int index, + enum gpiod_flags dflags, + const char *label); + +#else /* CONFIG_GPIOLIB */ + +struct device_node; + +static inline +struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, + struct device_node *node, + const char *propname, int index, + enum gpiod_flags dflags, + const char *label) +{ + return ERR_PTR(-ENOSYS); +} + +#endif /* CONFIG_GPIOLIB */ + #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) int gpiod_export(struct gpio_desc *desc, bool direction_may_change); From 77cb907abe6c4b399ad77f9b6c1d77d44a435de3 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 30 Jul 2019 13:43:36 +0300 Subject: [PATCH 11/82] gpiolib: acpi: Split ACPI stuff to gpiolib-acpi.h This is a follow up to the commit f626d6dfb709 ("gpio: of: Break out OF-only code") which broke down OF parts of GPIO library. Here we do the similar to ACPI. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190730104337.21235-2-andriy.shevchenko@linux.intel.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-dwapb.c | 1 + drivers/gpio/gpio-mb86s7x.c | 1 + drivers/gpio/gpio-xgene-sb.c | 1 + drivers/gpio/gpiolib-acpi.c | 1 + drivers/gpio/gpiolib-acpi.h | 104 +++++++++++++++++++++++++++++++++++ drivers/gpio/gpiolib.c | 1 + drivers/gpio/gpiolib.h | 93 ------------------------------- 7 files changed, 109 insertions(+), 93 deletions(-) create mode 100644 drivers/gpio/gpiolib-acpi.h diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 3108be5e208c..92e127e74813 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -27,6 +27,7 @@ #include #include "gpiolib.h" +#include "gpiolib-acpi.h" #define GPIO_SWPORTA_DR 0x00 #define GPIO_SWPORTA_DDR 0x04 diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c index 8f466993cd24..501e89548f53 100644 --- a/drivers/gpio/gpio-mb86s7x.c +++ b/drivers/gpio/gpio-mb86s7x.c @@ -21,6 +21,7 @@ #include #include "gpiolib.h" +#include "gpiolib-acpi.h" /* * Only first 8bits of a register correspond to each pin, diff --git a/drivers/gpio/gpio-xgene-sb.c b/drivers/gpio/gpio-xgene-sb.c index 38c01912c7b2..25d86441666e 100644 --- a/drivers/gpio/gpio-xgene-sb.c +++ b/drivers/gpio/gpio-xgene-sb.c @@ -16,6 +16,7 @@ #include #include "gpiolib.h" +#include "gpiolib-acpi.h" /* Common property names */ #define XGENE_NIRQ_PROPERTY "apm,nr-irqs" diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 39f2f9035c11..d54fc6e7c8a9 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -18,6 +18,7 @@ #include #include "gpiolib.h" +#include "gpiolib-acpi.h" /** * struct acpi_gpio_event - ACPI GPIO event handler data diff --git a/drivers/gpio/gpiolib-acpi.h b/drivers/gpio/gpiolib-acpi.h new file mode 100644 index 000000000000..d7241b432b8b --- /dev/null +++ b/drivers/gpio/gpiolib-acpi.h @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ACPI helpers for GPIO API + * + * Copyright (C) 2012,2019 Intel Corporation + */ + +#ifndef GPIOLIB_ACPI_H +#define GPIOLIB_ACPI_H + +struct acpi_device; + +/** + * struct acpi_gpio_info - ACPI GPIO specific information + * @adev: reference to ACPI device which consumes GPIO resource + * @flags: GPIO initialization flags + * @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo + * @pin_config: pin bias as provided by ACPI + * @polarity: interrupt polarity as provided by ACPI + * @triggering: triggering type as provided by ACPI + * @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping + */ +struct acpi_gpio_info { + struct acpi_device *adev; + enum gpiod_flags flags; + bool gpioint; + int pin_config; + int polarity; + int triggering; + unsigned int quirks; +}; + +#ifdef CONFIG_ACPI +void acpi_gpiochip_add(struct gpio_chip *chip); +void acpi_gpiochip_remove(struct gpio_chip *chip); + +void acpi_gpiochip_request_interrupts(struct gpio_chip *chip); +void acpi_gpiochip_free_interrupts(struct gpio_chip *chip); + +int acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, + struct acpi_gpio_info *info); +int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags, + struct acpi_gpio_info *info); + +struct gpio_desc *acpi_find_gpio(struct device *dev, + const char *con_id, + unsigned int idx, + enum gpiod_flags *dflags, + unsigned long *lookupflags); +struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, + const char *propname, int index, + struct acpi_gpio_info *info); + +int acpi_gpio_count(struct device *dev, const char *con_id); + +bool acpi_can_fallback_to_crs(struct acpi_device *adev, const char *con_id); +#else +static inline void acpi_gpiochip_add(struct gpio_chip *chip) { } +static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { } + +static inline void +acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { } + +static inline void +acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { } + +static inline int +acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *info) +{ + return 0; +} +static inline int +acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags, + struct acpi_gpio_info *info) +{ + return 0; +} + +static inline struct gpio_desc * +acpi_find_gpio(struct device *dev, const char *con_id, + unsigned int idx, enum gpiod_flags *dflags, + unsigned long *lookupflags) +{ + return ERR_PTR(-ENOENT); +} +static inline struct gpio_desc * +acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname, + int index, struct acpi_gpio_info *info) +{ + return ERR_PTR(-ENXIO); +} +static inline int acpi_gpio_count(struct device *dev, const char *con_id) +{ + return -ENODEV; +} + +static inline bool acpi_can_fallback_to_crs(struct acpi_device *adev, + const char *con_id) +{ + return false; +} +#endif + +#endif /* GPIOLIB_ACPI_H */ diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 03883f519d53..f83870a18ae7 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -30,6 +30,7 @@ #include "gpiolib.h" #include "gpiolib-of.h" +#include "gpiolib-acpi.h" #define CREATE_TRACE_POINTS #include diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 75d2e909d8c6..b8b10a409c7b 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -16,8 +16,6 @@ #include #include -struct acpi_device; - /** * struct gpio_device - internal state container for GPIO devices * @id: numerical ID number for the GPIO chip @@ -68,100 +66,9 @@ struct gpio_device { #endif }; -/** - * struct acpi_gpio_info - ACPI GPIO specific information - * @adev: reference to ACPI device which consumes GPIO resource - * @flags: GPIO initialization flags - * @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo - * @pin_config: pin bias as provided by ACPI - * @polarity: interrupt polarity as provided by ACPI - * @triggering: triggering type as provided by ACPI - * @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping - */ -struct acpi_gpio_info { - struct acpi_device *adev; - enum gpiod_flags flags; - bool gpioint; - int pin_config; - int polarity; - int triggering; - unsigned int quirks; -}; - /* gpio suffixes used for ACPI and device tree lookup */ static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" }; -#ifdef CONFIG_ACPI -void acpi_gpiochip_add(struct gpio_chip *chip); -void acpi_gpiochip_remove(struct gpio_chip *chip); - -void acpi_gpiochip_request_interrupts(struct gpio_chip *chip); -void acpi_gpiochip_free_interrupts(struct gpio_chip *chip); - -int acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, - struct acpi_gpio_info *info); -int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags, - struct acpi_gpio_info *info); - -struct gpio_desc *acpi_find_gpio(struct device *dev, - const char *con_id, - unsigned int idx, - enum gpiod_flags *dflags, - unsigned long *lookupflags); -struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, - const char *propname, int index, - struct acpi_gpio_info *info); - -int acpi_gpio_count(struct device *dev, const char *con_id); - -bool acpi_can_fallback_to_crs(struct acpi_device *adev, const char *con_id); -#else -static inline void acpi_gpiochip_add(struct gpio_chip *chip) { } -static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { } - -static inline void -acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { } - -static inline void -acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { } - -static inline int -acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *info) -{ - return 0; -} -static inline int -acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags, - struct acpi_gpio_info *info) -{ - return 0; -} - -static inline struct gpio_desc * -acpi_find_gpio(struct device *dev, const char *con_id, - unsigned int idx, enum gpiod_flags *dflags, - unsigned long *lookupflags) -{ - return ERR_PTR(-ENOENT); -} -static inline struct gpio_desc * -acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname, - int index, struct acpi_gpio_info *info) -{ - return ERR_PTR(-ENXIO); -} -static inline int acpi_gpio_count(struct device *dev, const char *con_id) -{ - return -ENODEV; -} - -static inline bool acpi_can_fallback_to_crs(struct acpi_device *adev, - const char *con_id) -{ - return false; -} -#endif - struct gpio_array { struct gpio_desc **desc; unsigned int size; From 2838bf941b120ec846a3903db13e319368d51b08 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 30 Jul 2019 13:43:37 +0300 Subject: [PATCH 12/82] gpiolib-acpi: Move acpi_dev_add_driver_gpios() et al to consumer.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The API, which belongs to GPIO library, is foreign to ACPI headers. Earlier we moved out I²C out of the latter, and now it's time for acpi_dev_add_driver_gpios() et al. For time being the acpi_gpio_get_irq_resource() and acpi_dev_gpio_irq_get() are left untouched as they need more thought about. Note, it requires uninline acpi_dev_remove_driver_gpios() to keep purity of consumer.h. Cc: Pierre-Louis Bossart Cc: Liam Girdwood Cc: Jie Yang Cc: Mark Brown Cc: alsa-devel@alsa-project.org (moderated list:INTEL ASoC DRIVERS) Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20190730104337.21235-3-andriy.shevchenko@linux.intel.com Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 7 +++ include/linux/acpi.h | 51 ------------------ include/linux/gpio/consumer.h | 57 ++++++++++++++++++++ sound/soc/intel/boards/bytcht_cx2072x.c | 1 + sound/soc/intel/boards/cht_bsw_max98090_ti.c | 1 + sound/soc/intel/boards/cht_bsw_rt5672.c | 1 + 6 files changed, 67 insertions(+), 51 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index d54fc6e7c8a9..fdee8afa5339 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -383,6 +383,13 @@ int acpi_dev_add_driver_gpios(struct acpi_device *adev, } EXPORT_SYMBOL_GPL(acpi_dev_add_driver_gpios); +void acpi_dev_remove_driver_gpios(struct acpi_device *adev) +{ + if (adev) + adev->driver_gpios = NULL; +} +EXPORT_SYMBOL_GPL(acpi_dev_remove_driver_gpios); + static void devm_acpi_dev_release_driver_gpios(struct device *dev, void *res) { acpi_dev_remove_driver_gpios(ACPI_COMPANION(dev)); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 9426b9aaed86..e40e1e27ed8e 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -994,62 +994,11 @@ void __acpi_handle_debug(struct _ddebug *descriptor, acpi_handle handle, const c #endif #endif -struct acpi_gpio_params { - unsigned int crs_entry_index; - unsigned int line_index; - bool active_low; -}; - -struct acpi_gpio_mapping { - const char *name; - const struct acpi_gpio_params *data; - unsigned int size; - -/* Ignore IoRestriction field */ -#define ACPI_GPIO_QUIRK_NO_IO_RESTRICTION BIT(0) -/* - * When ACPI GPIO mapping table is in use the index parameter inside it - * refers to the GPIO resource in _CRS method. That index has no - * distinction of actual type of the resource. When consumer wants to - * get GpioIo type explicitly, this quirk may be used. - */ -#define ACPI_GPIO_QUIRK_ONLY_GPIOIO BIT(1) - - unsigned int quirks; -}; - #if defined(CONFIG_ACPI) && defined(CONFIG_GPIOLIB) -int acpi_dev_add_driver_gpios(struct acpi_device *adev, - const struct acpi_gpio_mapping *gpios); - -static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev) -{ - if (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); - bool acpi_gpio_get_irq_resource(struct acpi_resource *ares, struct acpi_resource_gpio **agpio); 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, - const struct acpi_gpio_mapping *gpios) -{ - return -ENXIO; -} -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 bool acpi_gpio_get_irq_resource(struct acpi_resource *ares, struct acpi_resource_gpio **agpio) { diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 6019d4d128c5..aac617371b60 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -602,6 +602,63 @@ struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, #endif /* CONFIG_GPIOLIB */ +struct acpi_gpio_params { + unsigned int crs_entry_index; + unsigned int line_index; + bool active_low; +}; + +struct acpi_gpio_mapping { + const char *name; + const struct acpi_gpio_params *data; + unsigned int size; + +/* Ignore IoRestriction field */ +#define ACPI_GPIO_QUIRK_NO_IO_RESTRICTION BIT(0) +/* + * When ACPI GPIO mapping table is in use the index parameter inside it + * refers to the GPIO resource in _CRS method. That index has no + * distinction of actual type of the resource. When consumer wants to + * get GpioIo type explicitly, this quirk may be used. + */ +#define ACPI_GPIO_QUIRK_ONLY_GPIOIO BIT(1) + + unsigned int quirks; +}; + +#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_ACPI) + +struct acpi_device; + +int acpi_dev_add_driver_gpios(struct acpi_device *adev, + const struct acpi_gpio_mapping *gpios); +void acpi_dev_remove_driver_gpios(struct acpi_device *adev); + +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); + +#else /* CONFIG_GPIOLIB && CONFIG_ACPI */ + +struct acpi_device; + +static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev, + const struct acpi_gpio_mapping *gpios) +{ + return -ENXIO; +} +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) {} + +#endif /* CONFIG_GPIOLIB && CONFIG_ACPI */ + + #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) int gpiod_export(struct gpio_desc *desc, bool direction_may_change); diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c index 54ac2fd41925..67f06c95eec5 100644 --- a/sound/soc/intel/boards/bytcht_cx2072x.c +++ b/sound/soc/intel/boards/bytcht_cx2072x.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index 33eb72545be6..05db311b579e 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c @@ -12,6 +12,7 @@ */ #include +#include #include #include #include diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index 4977b5a65eb8..9d657421730a 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -8,6 +8,7 @@ * Mengdong Lin */ +#include #include #include #include From 61059b7048ee1d635673f3014ea9f7e3e4b1532f Mon Sep 17 00:00:00 2001 From: Ding Xiang Date: Wed, 31 Jul 2019 17:47:54 +0800 Subject: [PATCH 13/82] gpio: ixp4xx: remove redundant dev_err message devm_ioremap_resource already contains error message, so remove the redundant dev_err message Signed-off-by: Ding Xiang Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-ixp4xx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c index 670c2a85a35b..2b2b89b6cd18 100644 --- a/drivers/gpio/gpio-ixp4xx.c +++ b/drivers/gpio/gpio-ixp4xx.c @@ -321,10 +321,8 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); g->base = devm_ioremap_resource(dev, res); - if (IS_ERR(g->base)) { - dev_err(dev, "ioremap error\n"); + if (IS_ERR(g->base)) return PTR_ERR(g->base); - } /* * Make sure GPIO 14 and 15 are NOT used as clocks but GPIO on From 49281a222ac42724b94f6c874f43a284ec58d37e Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 1 Aug 2019 00:28:26 +0200 Subject: [PATCH 14/82] gpio: of: Fix hard-assigned valid_mask for OF case The recent refactoring to break out OF code to its own file contained a bug letting the need_valid_mask be overridden by the need of the device tree range check, and if there were no ranges, but device tree was active and the reserved GPIO used in another way, things likely crash. Cc: Mark Brown Cc: Bjorn Andersson Cc: Stephen Boyd Fixes: f626d6dfb709 ("gpio: of: Break out OF-only code") Reported-by: Mark Brown Suggested-by: Stephen Boyd Signed-off-by: Stephen Boyd Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 2 +- drivers/gpio/gpiolib-of.h | 4 ++-- drivers/gpio/gpiolib.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index b10d04dd9296..e39b4290b80c 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -87,7 +87,7 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip, * @dev: the device for the GPIO provider * @return: true if the valid mask needs to be set */ -bool of_gpio_need_valid_mask(struct gpio_chip *gc) +bool of_gpio_need_valid_mask(const struct gpio_chip *gc) { int size; struct device_node *np = gc->of_node; diff --git a/drivers/gpio/gpiolib-of.h b/drivers/gpio/gpiolib-of.h index 34954921d96e..454d1658ee2d 100644 --- a/drivers/gpio/gpiolib-of.h +++ b/drivers/gpio/gpiolib-of.h @@ -16,7 +16,7 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, int of_gpiochip_add(struct gpio_chip *gc); void of_gpiochip_remove(struct gpio_chip *gc); int of_gpio_get_count(struct device *dev, const char *con_id); -bool of_gpio_need_valid_mask(struct gpio_chip *gc); +bool of_gpio_need_valid_mask(const struct gpio_chip *gc); #else static inline struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, @@ -36,7 +36,7 @@ static inline int of_gpio_get_count(struct device *dev, const char *con_id) { return 0; } -static inline bool of_gpio_need_valid_mask(struct gpio_chip *gc) +static inline bool of_gpio_need_valid_mask(const struct gpio_chip *gc) { return false; } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index f83870a18ae7..20f13129cdaa 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -363,8 +363,8 @@ static unsigned long *gpiochip_allocate_mask(struct gpio_chip *chip) static int gpiochip_alloc_valid_mask(struct gpio_chip *gc) { - if (IS_ENABLED(CONFIG_OF_GPIO)) - gc->need_valid_mask = of_gpio_need_valid_mask(gc); + if (of_gpio_need_valid_mask(gc)) + gc->need_valid_mask = true; if (!gc->need_valid_mask) return 0; From 7beb620f805dcb6757b5e7870bebd75e3e9b37e0 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Thu, 1 Aug 2019 16:44:39 +0800 Subject: [PATCH 15/82] gpio: mxc: Use devm_clk_get_optional instead of devm_clk_get i.MX SoC's GPIO clock is optional, so it is better to use devm_clk_get_optional instead of devm_clk_get. Signed-off-by: Anson Huang Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-mxc.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index b2813580c582..7907a8755866 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -435,12 +435,9 @@ static int mxc_gpio_probe(struct platform_device *pdev) return port->irq; /* the controller clock is optional */ - port->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(port->clk)) { - if (PTR_ERR(port->clk) == -EPROBE_DEFER) - return -EPROBE_DEFER; - port->clk = NULL; - } + port->clk = devm_clk_get_optional(&pdev->dev, NULL); + if (IS_ERR(port->clk)) + return PTR_ERR(port->clk); err = clk_prepare_enable(port->clk); if (err) { From 8eeb467d3b4f8a5f05e49dd88e7674a2d6c0f346 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 1 Aug 2019 20:39:35 +0300 Subject: [PATCH 16/82] gpio: pca953x: Switch to use device_get_match_data() Instead of open coded variants, switch to direct use of device_get_match_data(). Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pca953x.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 378b206d2dc9..54cf01901320 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -949,19 +949,15 @@ static int pca953x_probe(struct i2c_client *client, if (i2c_id) { chip->driver_data = i2c_id->driver_data; } else { - const struct acpi_device_id *acpi_id; - struct device *dev = &client->dev; + const void *match; - chip->driver_data = (uintptr_t)of_device_get_match_data(dev); - if (!chip->driver_data) { - acpi_id = acpi_match_device(pca953x_acpi_ids, dev); - if (!acpi_id) { - ret = -ENODEV; - goto err_exit; - } - - chip->driver_data = acpi_id->driver_data; + match = device_get_match_data(&client->dev); + if (!match) { + ret = -ENODEV; + goto err_exit; } + + chip->driver_data = (uintptr_t)match; } i2c_set_clientdata(client, chip); From 63b484c2a69a4a98a22e072ea2ad1317a85e3abf Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 1 Aug 2019 20:39:36 +0300 Subject: [PATCH 17/82] gpio: pca953x: Use GENMASK() consistently Use GENMASK() macro for all definitions where it's appropriate. No functional change intended. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pca953x.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 54cf01901320..aaba0b394d2f 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -28,9 +29,9 @@ #define PCA953X_INVERT 0x02 #define PCA953X_DIRECTION 0x03 -#define REG_ADDR_MASK 0x3f -#define REG_ADDR_EXT 0x40 -#define REG_ADDR_AI 0x80 +#define REG_ADDR_MASK GENMASK(5, 0) +#define REG_ADDR_EXT BIT(6) +#define REG_ADDR_AI BIT(7) #define PCA957X_IN 0x00 #define PCA957X_INVRT 0x01 @@ -55,17 +56,17 @@ #define PCAL6524_OUT_INDCONF 0x2c #define PCAL6524_DEBOUNCE 0x2d -#define PCA_GPIO_MASK 0x00FF +#define PCA_GPIO_MASK GENMASK(7, 0) -#define PCAL_GPIO_MASK 0x1f -#define PCAL_PINCTRL_MASK 0x60 +#define PCAL_GPIO_MASK GENMASK(4, 0) +#define PCAL_PINCTRL_MASK GENMASK(6, 5) -#define PCA_INT 0x0100 -#define PCA_PCAL 0x0200 +#define PCA_INT BIT(8) +#define PCA_PCAL BIT(9) #define PCA_LATCH_INT (PCA_PCAL | PCA_INT) -#define PCA953X_TYPE 0x1000 -#define PCA957X_TYPE 0x2000 -#define PCA_TYPE_MASK 0xF000 +#define PCA953X_TYPE BIT(12) +#define PCA957X_TYPE BIT(13) +#define PCA_TYPE_MASK GENMASK(15, 12) #define PCA_CHIP_TYPE(x) ((x) & PCA_TYPE_MASK) @@ -565,7 +566,7 @@ static void pca953x_irq_mask(struct irq_data *d) struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct pca953x_chip *chip = gpiochip_get_data(gc); - chip->irq_mask[d->hwirq / BANK_SZ] &= ~(1 << (d->hwirq % BANK_SZ)); + chip->irq_mask[d->hwirq / BANK_SZ] &= ~BIT(d->hwirq % BANK_SZ); } static void pca953x_irq_unmask(struct irq_data *d) @@ -573,7 +574,7 @@ static void pca953x_irq_unmask(struct irq_data *d) struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct pca953x_chip *chip = gpiochip_get_data(gc); - chip->irq_mask[d->hwirq / BANK_SZ] |= 1 << (d->hwirq % BANK_SZ); + chip->irq_mask[d->hwirq / BANK_SZ] |= BIT(d->hwirq % BANK_SZ); } static int pca953x_irq_set_wake(struct irq_data *d, unsigned int on) @@ -641,7 +642,7 @@ static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct pca953x_chip *chip = gpiochip_get_data(gc); int bank_nb = d->hwirq / BANK_SZ; - u8 mask = 1 << (d->hwirq % BANK_SZ); + u8 mask = BIT(d->hwirq % BANK_SZ); if (!(type & IRQ_TYPE_EDGE_BOTH)) { dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", @@ -666,7 +667,7 @@ static void pca953x_irq_shutdown(struct irq_data *d) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct pca953x_chip *chip = gpiochip_get_data(gc); - u8 mask = 1 << (d->hwirq % BANK_SZ); + u8 mask = BIT(d->hwirq % BANK_SZ); chip->irq_trig_raise[d->hwirq / BANK_SZ] &= ~mask; chip->irq_trig_fall[d->hwirq / BANK_SZ] &= ~mask; From 6dd6a2d27e5a0d192b542389f4c9a035d1b77b8e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 1 Aug 2019 20:39:37 +0300 Subject: [PATCH 18/82] gpio: pca953x: Remove explicit comparison with 0 There is no need to explicitly compare return code with 0. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pca953x.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index aaba0b394d2f..454bbe2fb41f 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -850,12 +850,12 @@ static int device_pca95xx_init(struct pca953x_chip *chip, u32 invert) ret = regcache_sync_region(chip->regmap, chip->regs->output, chip->regs->output + NBANK(chip)); - if (ret != 0) + if (ret) goto out; ret = regcache_sync_region(chip->regmap, chip->regs->direction, chip->regs->direction + NBANK(chip)); - if (ret != 0) + if (ret) goto out; /* set platform specific polarity inversion */ @@ -1061,14 +1061,14 @@ static int pca953x_regcache_sync(struct device *dev) */ ret = regcache_sync_region(chip->regmap, chip->regs->direction, chip->regs->direction + NBANK(chip)); - if (ret != 0) { + if (ret) { dev_err(dev, "Failed to sync GPIO dir registers: %d\n", ret); return ret; } ret = regcache_sync_region(chip->regmap, chip->regs->output, chip->regs->output + NBANK(chip)); - if (ret != 0) { + if (ret) { dev_err(dev, "Failed to sync GPIO out registers: %d\n", ret); return ret; } @@ -1077,7 +1077,7 @@ static int pca953x_regcache_sync(struct device *dev) if (chip->driver_data & PCA_PCAL) { ret = regcache_sync_region(chip->regmap, PCAL953X_IN_LATCH, PCAL953X_IN_LATCH + NBANK(chip)); - if (ret != 0) { + if (ret) { dev_err(dev, "Failed to sync INT latch registers: %d\n", ret); return ret; @@ -1085,7 +1085,7 @@ static int pca953x_regcache_sync(struct device *dev) ret = regcache_sync_region(chip->regmap, PCAL953X_INT_MASK, PCAL953X_INT_MASK + NBANK(chip)); - if (ret != 0) { + if (ret) { dev_err(dev, "Failed to sync INT mask registers: %d\n", ret); return ret; @@ -1117,7 +1117,7 @@ static int pca953x_resume(struct device *dev) if (!atomic_read(&chip->wakeup_path)) { ret = regulator_enable(chip->regulator); - if (ret != 0) { + if (ret) { dev_err(dev, "Failed to enable regulator: %d\n", ret); return 0; } @@ -1130,7 +1130,7 @@ static int pca953x_resume(struct device *dev) return ret; ret = regcache_sync(chip->regmap); - if (ret != 0) { + if (ret) { dev_err(dev, "Failed to restore register map: %d\n", ret); return ret; } From f4160faac98c36556231621b03b44b646508b08e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 1 Aug 2019 20:39:38 +0300 Subject: [PATCH 19/82] gpio: pca953x: Drop %s for constant string literals There is no need to use %s for constant string literals w/o special characters inside. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pca953x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 454bbe2fb41f..64d02ca60f53 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -1038,8 +1038,7 @@ static int pca953x_remove(struct i2c_client *client) ret = pdata->teardown(client, chip->gpio_chip.base, chip->gpio_chip.ngpio, pdata->context); if (ret < 0) - dev_err(&client->dev, "%s failed, %d\n", - "teardown", ret); + dev_err(&client->dev, "teardown failed, %d\n", ret); } else { ret = 0; } From bd4bd337039df9d5c6a3c11c439511fd99e11f52 Mon Sep 17 00:00:00 2001 From: Song Hui Date: Thu, 18 Jul 2019 17:49:02 +0800 Subject: [PATCH 20/82] gpio: mpc8xxx: Add ls1028a device specify function. There is a device specify register(named GPIO_IBE) on ls1028a need to enable in initial stage. Signed-off-by: Song Hui Link: https://lore.kernel.org/r/20190718094902.15562-2-hui.song_1@nxp.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mpc8xxx.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index c8673a5d9412..1a680aa28769 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -32,6 +32,7 @@ #define GPIO_IMR 0x10 #define GPIO_ICR 0x14 #define GPIO_ICR2 0x18 +#define GPIO_IBE 0x18 struct mpc8xxx_gpio_chip { struct gpio_chip gc; @@ -45,6 +46,27 @@ struct mpc8xxx_gpio_chip { unsigned int irqn; }; +/* The GPIO Input Buffer Enable register(GPIO_IBE) is used to + * control the input enable of each individual GPIO port. + * When an individual GPIO port’s direction is set to + * input (GPIO_GPDIR[DRn=0]), the associated input enable must be + * set (GPIOxGPIE[IEn]=1) to propagate the port value to the GPIO + * Data Register. + */ +static int ls1028a_gpio_dir_in_init(struct gpio_chip *gc) +{ + unsigned long flags; + struct mpc8xxx_gpio_chip *mpc8xxx_gc = gpiochip_get_data(gc); + + spin_lock_irqsave(&gc->bgpio_lock, flags); + + gc->write_reg(mpc8xxx_gc->regs + GPIO_IBE, 0xffffffff); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); + + return 0; +} + /* * This hardware has a big endian bit assignment such that GPIO line 0 is * connected to bit 31, line 1 to bit 30 ... line 31 to bit 0. @@ -261,6 +283,7 @@ static const struct irq_domain_ops mpc8xxx_gpio_irq_ops = { }; struct mpc8xxx_gpio_devtype { + int (*gpio_dir_in_init)(struct gpio_chip *chip); int (*gpio_dir_out)(struct gpio_chip *, unsigned int, int); int (*gpio_get)(struct gpio_chip *, unsigned int); int (*irq_set_type)(struct irq_data *, unsigned int); @@ -271,6 +294,10 @@ static const struct mpc8xxx_gpio_devtype mpc512x_gpio_devtype = { .irq_set_type = mpc512x_irq_set_type, }; +static const struct mpc8xxx_gpio_devtype ls1028a_gpio_devtype = { + .gpio_dir_in_init = ls1028a_gpio_dir_in_init, +}; + static const struct mpc8xxx_gpio_devtype mpc5125_gpio_devtype = { .gpio_dir_out = mpc5125_gpio_dir_out, .irq_set_type = mpc512x_irq_set_type, @@ -291,6 +318,7 @@ static const struct of_device_id mpc8xxx_gpio_ids[] = { { .compatible = "fsl,mpc5121-gpio", .data = &mpc512x_gpio_devtype, }, { .compatible = "fsl,mpc5125-gpio", .data = &mpc5125_gpio_devtype, }, { .compatible = "fsl,pq3-gpio", }, + { .compatible = "fsl,ls1028a-gpio", .data = &ls1028a_gpio_devtype, }, { .compatible = "fsl,qoriq-gpio", }, {} }; @@ -376,6 +404,9 @@ static int mpc8xxx_probe(struct platform_device *pdev) /* ack and mask all irqs */ gc->write_reg(mpc8xxx_gc->regs + GPIO_IER, 0xffffffff); gc->write_reg(mpc8xxx_gc->regs + GPIO_IMR, 0); + /* enable input buffer */ + if (devtype->gpio_dir_in_init) + devtype->gpio_dir_in_init(gc); irq_set_chained_handler_and_data(mpc8xxx_gc->irqn, mpc8xxx_gpio_irq_cascade, mpc8xxx_gc); From 7bdbd1eccc9fb3875f33af1a2257001128824e81 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 18 Jul 2019 15:51:01 +0900 Subject: [PATCH 21/82] gpio: refactor gpiochip_allocate_mask() with bitmap_alloc() Refactor gpiochip_allocate_mask() slightly by using bitmap_alloc(). I used bitmap_free() for the corresponding free parts. Actually, bitmap_free() is a wrapper of kfree(), but I did this for consistency. Signed-off-by: Masahiro Yamada Link: https://lore.kernel.org/r/20190718065101.26994-1-yamada.masahiro@socionext.com Reviewed-by: Stephen Boyd Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 20f13129cdaa..537a37a89891 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -351,7 +351,7 @@ static unsigned long *gpiochip_allocate_mask(struct gpio_chip *chip) { unsigned long *p; - p = kmalloc_array(BITS_TO_LONGS(chip->ngpio), sizeof(*p), GFP_KERNEL); + p = bitmap_alloc(chip->ngpio, GFP_KERNEL); if (!p) return NULL; @@ -385,7 +385,7 @@ static int gpiochip_init_valid_mask(struct gpio_chip *gpiochip) static void gpiochip_free_valid_mask(struct gpio_chip *gpiochip) { - kfree(gpiochip->valid_mask); + bitmap_free(gpiochip->valid_mask); gpiochip->valid_mask = NULL; } @@ -1620,7 +1620,7 @@ static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip) static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip) { - kfree(gpiochip->irq.valid_mask); + bitmap_free(gpiochip->irq.valid_mask); gpiochip->irq.valid_mask = NULL; } From d111e7a387d71b444b9a785d754f348d9a623204 Mon Sep 17 00:00:00 2001 From: Hennie Muller Date: Sun, 21 Jul 2019 14:52:58 +0200 Subject: [PATCH 22/82] gpio: viperboard: Replace 'unsigned' with 'unsigned int' Fixes a couple of warnings by checkpatch and sparse. Signed-off-by: Hennie Muller Link: https://lore.kernel.org/r/20190721125259.13990-1-hm@bitlabs.co.za Signed-off-by: Linus Walleij --- drivers/gpio/gpio-viperboard.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpio/gpio-viperboard.c b/drivers/gpio/gpio-viperboard.c index 9b604f13e302..c301c1d56dd2 100644 --- a/drivers/gpio/gpio-viperboard.c +++ b/drivers/gpio/gpio-viperboard.c @@ -79,7 +79,7 @@ MODULE_PARM_DESC(gpioa_freq, /* ----- begin of gipo a chip -------------------------------------------- */ static int vprbrd_gpioa_get(struct gpio_chip *chip, - unsigned offset) + unsigned int offset) { int ret, answer, error = 0; struct vprbrd_gpio *gpio = gpiochip_get_data(chip); @@ -129,7 +129,7 @@ static int vprbrd_gpioa_get(struct gpio_chip *chip, } static void vprbrd_gpioa_set(struct gpio_chip *chip, - unsigned offset, int value) + unsigned int offset, int value) { int ret; struct vprbrd_gpio *gpio = gpiochip_get_data(chip); @@ -170,7 +170,7 @@ static void vprbrd_gpioa_set(struct gpio_chip *chip, } static int vprbrd_gpioa_direction_input(struct gpio_chip *chip, - unsigned offset) + unsigned int offset) { int ret; struct vprbrd_gpio *gpio = gpiochip_get_data(chip); @@ -207,7 +207,7 @@ static int vprbrd_gpioa_direction_input(struct gpio_chip *chip, } static int vprbrd_gpioa_direction_output(struct gpio_chip *chip, - unsigned offset, int value) + unsigned int offset, int value) { int ret; struct vprbrd_gpio *gpio = gpiochip_get_data(chip); @@ -251,8 +251,8 @@ static int vprbrd_gpioa_direction_output(struct gpio_chip *chip, /* ----- begin of gipo b chip -------------------------------------------- */ -static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned offset, - unsigned dir) +static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned int offset, + unsigned int dir) { struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf; int ret; @@ -273,7 +273,7 @@ static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned offset, } static int vprbrd_gpiob_get(struct gpio_chip *chip, - unsigned offset) + unsigned int offset) { int ret; u16 val; @@ -305,7 +305,7 @@ static int vprbrd_gpiob_get(struct gpio_chip *chip, } static void vprbrd_gpiob_set(struct gpio_chip *chip, - unsigned offset, int value) + unsigned int offset, int value) { int ret; struct vprbrd_gpio *gpio = gpiochip_get_data(chip); @@ -338,7 +338,7 @@ static void vprbrd_gpiob_set(struct gpio_chip *chip, } static int vprbrd_gpiob_direction_input(struct gpio_chip *chip, - unsigned offset) + unsigned int offset) { int ret; struct vprbrd_gpio *gpio = gpiochip_get_data(chip); @@ -359,7 +359,7 @@ static int vprbrd_gpiob_direction_input(struct gpio_chip *chip, } static int vprbrd_gpiob_direction_output(struct gpio_chip *chip, - unsigned offset, int value) + unsigned int offset, int value) { int ret; struct vprbrd_gpio *gpio = gpiochip_get_data(chip); From 72ce665f170ee22069726840cd13ccf5af4ef34d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 22 Jul 2019 10:07:45 +0100 Subject: [PATCH 23/82] gpio: arizona: Use local copy of pdata A local copy of the pdata exists and it should be used rather than pulling a fresh copy. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20190722090748.20807-1-ckeepax@opensource.cirrus.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-arizona.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c index c07fad975049..5640efe5e750 100644 --- a/drivers/gpio/gpio-arizona.c +++ b/drivers/gpio/gpio-arizona.c @@ -142,7 +142,7 @@ static const struct gpio_chip template_chip = { static int arizona_gpio_probe(struct platform_device *pdev) { struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); - struct arizona_pdata *pdata = dev_get_platdata(arizona->dev); + struct arizona_pdata *pdata = &arizona->pdata; struct arizona_gpio *arizona_gpio; int ret; @@ -177,7 +177,7 @@ static int arizona_gpio_probe(struct platform_device *pdev) return -EINVAL; } - if (pdata && pdata->gpio_base) + if (pdata->gpio_base) arizona_gpio->gpio_chip.base = pdata->gpio_base; else arizona_gpio->gpio_chip.base = -1; From fe2afa0d7b5ce05f8d2c4508e4041f3a216a5539 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 22 Jul 2019 10:07:46 +0100 Subject: [PATCH 24/82] gpio: madera: Use local copy of pdata A local copy of the pdata exists and it should be used rather than pulling a fresh copy. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20190722090748.20807-2-ckeepax@opensource.cirrus.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-madera.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-madera.c b/drivers/gpio/gpio-madera.c index 4dbc837d1215..fa3441df0a5d 100644 --- a/drivers/gpio/gpio-madera.c +++ b/drivers/gpio/gpio-madera.c @@ -120,7 +120,7 @@ static const struct gpio_chip madera_gpio_chip = { static int madera_gpio_probe(struct platform_device *pdev) { struct madera *madera = dev_get_drvdata(pdev->dev.parent); - struct madera_pdata *pdata = dev_get_platdata(madera->dev); + struct madera_pdata *pdata = &madera->pdata; struct madera_gpio *madera_gpio; int ret; @@ -153,7 +153,7 @@ static int madera_gpio_probe(struct platform_device *pdev) } /* We want to be usable on systems that don't use devicetree or acpi */ - if (pdata && pdata->gpio_base) + if (pdata->gpio_base) madera_gpio->gpio_chip.base = pdata->gpio_base; else madera_gpio->gpio_chip.base = -1; From d06be8bc290aa255b9fd8602e60fb9f487aa0f48 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Mon, 22 Jul 2019 10:07:47 +0100 Subject: [PATCH 25/82] gpio: madera: Add support for Cirrus Logic CS47L15 As the gpio is common to all madera codecs all that is needed is to setup the correct number of GPIO pins for the CS47L15. Signed-off-by: Richard Fitzgerald Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20190722090748.20807-3-ckeepax@opensource.cirrus.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-madera.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpio/gpio-madera.c b/drivers/gpio/gpio-madera.c index fa3441df0a5d..c403899ff450 100644 --- a/drivers/gpio/gpio-madera.c +++ b/drivers/gpio/gpio-madera.c @@ -136,6 +136,9 @@ static int madera_gpio_probe(struct platform_device *pdev) madera_gpio->gpio_chip.parent = pdev->dev.parent; switch (madera->type) { + case CS47L15: + madera_gpio->gpio_chip.ngpio = CS47L15_NUM_GPIOS; + break; case CS47L35: madera_gpio->gpio_chip.ngpio = CS47L35_NUM_GPIOS; break; From 74d2d0e68701bcd53d2cf771dd3b3cb9f84bed5c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 22 Jul 2019 10:07:48 +0100 Subject: [PATCH 26/82] gpio: madera: Add support for Cirrus Logic CS47L92 As the gpio is common to all madera codecs all that is needed is to setup the correct number of GPIO pins for the CS47L92. Signed-off-by: Charles Keepax Link: https://lore.kernel.org/r/20190722090748.20807-4-ckeepax@opensource.cirrus.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-madera.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpio/gpio-madera.c b/drivers/gpio/gpio-madera.c index c403899ff450..7086f8b5388f 100644 --- a/drivers/gpio/gpio-madera.c +++ b/drivers/gpio/gpio-madera.c @@ -150,6 +150,11 @@ static int madera_gpio_probe(struct platform_device *pdev) case CS47L91: madera_gpio->gpio_chip.ngpio = CS47L90_NUM_GPIOS; break; + case CS42L92: + case CS47L92: + case CS47L93: + madera_gpio->gpio_chip.ngpio = CS47L92_NUM_GPIOS; + break; default: dev_err(&pdev->dev, "Unknown chip variant %d\n", madera->type); return -EINVAL; From 15bddb7d787aebc837912cecf107b7eaccf03913 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:15 -0700 Subject: [PATCH 27/82] gpio: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Cc: linux-gpio@vger.kernel.org Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20190730181557.90391-16-swboyd@chromium.org Acked-by: Bartosz Golaszewski Signed-off-by: Linus Walleij --- drivers/gpio/gpio-brcmstb.c | 4 +--- drivers/gpio/gpio-eic-sprd.c | 4 +--- drivers/gpio/gpio-grgpio.c | 2 -- drivers/gpio/gpio-max77620.c | 4 +--- drivers/gpio/gpio-pmic-eic-sprd.c | 4 +--- drivers/gpio/gpio-sprd.c | 4 +--- drivers/gpio/gpio-tb10x.c | 4 +--- drivers/gpio/gpio-tegra.c | 4 +--- drivers/gpio/gpio-zx.c | 1 - drivers/gpio/gpio-zynq.c | 4 +--- 10 files changed, 8 insertions(+), 27 deletions(-) diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index af936dcca659..05e3f99ae59c 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -636,10 +636,8 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) if (of_property_read_bool(np, "interrupt-controller")) { priv->parent_irq = platform_get_irq(pdev, 0); - if (priv->parent_irq <= 0) { - dev_err(dev, "Couldn't get IRQ"); + if (priv->parent_irq <= 0) return -ENOENT; - } } else { priv->parent_irq = -ENOENT; } diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c index 7b9ac4a12c20..fe7a73f52329 100644 --- a/drivers/gpio/gpio-eic-sprd.c +++ b/drivers/gpio/gpio-eic-sprd.c @@ -584,10 +584,8 @@ static int sprd_eic_probe(struct platform_device *pdev) sprd_eic->type = pdata->type; sprd_eic->irq = platform_get_irq(pdev, 0); - if (sprd_eic->irq < 0) { - dev_err(&pdev->dev, "Failed to get EIC interrupt.\n"); + if (sprd_eic->irq < 0) return sprd_eic->irq; - } for (i = 0; i < SPRD_EIC_MAX_BANK; i++) { /* diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c index 0937b605e134..08234e64993a 100644 --- a/drivers/gpio/gpio-grgpio.c +++ b/drivers/gpio/gpio-grgpio.c @@ -408,8 +408,6 @@ static int grgpio_probe(struct platform_device *ofdev) * Continue without irq functionality for that * gpio line */ - dev_err(priv->dev, - "Failed to get irq for offset %d\n", i); continue; } priv->uirqs[lirq->index].uirq = ret; diff --git a/drivers/gpio/gpio-max77620.c b/drivers/gpio/gpio-max77620.c index b7d89e30131e..47d05e357e61 100644 --- a/drivers/gpio/gpio-max77620.c +++ b/drivers/gpio/gpio-max77620.c @@ -270,10 +270,8 @@ static int max77620_gpio_probe(struct platform_device *pdev) int ret; gpio_irq = platform_get_irq(pdev, 0); - if (gpio_irq <= 0) { - dev_err(&pdev->dev, "GPIO irq not available %d\n", gpio_irq); + if (gpio_irq <= 0) return -ENODEV; - } mgpio = devm_kzalloc(&pdev->dev, sizeof(*mgpio), GFP_KERNEL); if (!mgpio) diff --git a/drivers/gpio/gpio-pmic-eic-sprd.c b/drivers/gpio/gpio-pmic-eic-sprd.c index 24228cf79afc..05000cace9b2 100644 --- a/drivers/gpio/gpio-pmic-eic-sprd.c +++ b/drivers/gpio/gpio-pmic-eic-sprd.c @@ -305,10 +305,8 @@ static int sprd_pmic_eic_probe(struct platform_device *pdev) mutex_init(&pmic_eic->buslock); pmic_eic->irq = platform_get_irq(pdev, 0); - if (pmic_eic->irq < 0) { - dev_err(&pdev->dev, "Failed to get PMIC EIC interrupt.\n"); + if (pmic_eic->irq < 0) return pmic_eic->irq; - } pmic_eic->map = dev_get_regmap(pdev->dev.parent, NULL); if (!pmic_eic->map) diff --git a/drivers/gpio/gpio-sprd.c b/drivers/gpio/gpio-sprd.c index f5c8b3a351d5..d7314d39ab65 100644 --- a/drivers/gpio/gpio-sprd.c +++ b/drivers/gpio/gpio-sprd.c @@ -226,10 +226,8 @@ static int sprd_gpio_probe(struct platform_device *pdev) return -ENOMEM; sprd_gpio->irq = platform_get_irq(pdev, 0); - if (sprd_gpio->irq < 0) { - dev_err(&pdev->dev, "Failed to get GPIO interrupt.\n"); + if (sprd_gpio->irq < 0) return sprd_gpio->irq; - } sprd_gpio->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sprd_gpio->base)) diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c index bd1f3f775ce9..5e375186f90e 100644 --- a/drivers/gpio/gpio-tb10x.c +++ b/drivers/gpio/gpio-tb10x.c @@ -171,10 +171,8 @@ static int tb10x_gpio_probe(struct platform_device *pdev) struct irq_chip_generic *gc; ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(dev, "No interrupt specified.\n"); + if (ret < 0) return ret; - } tb10x_gpio->gc.to_irq = tb10x_gpio_to_irq; tb10x_gpio->irq = ret; diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 0f59161a4701..8a01d3694b28 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -624,10 +624,8 @@ static int tegra_gpio_probe(struct platform_device *pdev) for (i = 0; i < tgi->bank_count; i++) { ret = platform_get_irq(pdev, i); - if (ret < 0) { - dev_err(&pdev->dev, "Missing IRQ resource: %d\n", ret); + if (ret < 0) return ret; - } bank = &tgi->bank_info[i]; bank->bank = i; diff --git a/drivers/gpio/gpio-zx.c b/drivers/gpio/gpio-zx.c index 8637adb6bc20..8d9b9bf8510a 100644 --- a/drivers/gpio/gpio-zx.c +++ b/drivers/gpio/gpio-zx.c @@ -253,7 +253,6 @@ static int zx_gpio_probe(struct platform_device *pdev) writew_relaxed(0, chip->base + ZX_GPIO_IE); irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(dev, "invalid IRQ\n"); gpiochip_remove(&chip->gc); return -ENODEV; } diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index f241b6c13dbe..86b0bd256c13 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -849,10 +849,8 @@ static int zynq_gpio_probe(struct platform_device *pdev) return PTR_ERR(gpio->base_addr); gpio->irq = platform_get_irq(pdev, 0); - if (gpio->irq < 0) { - dev_err(&pdev->dev, "invalid IRQ\n"); + if (gpio->irq < 0) return gpio->irq; - } /* configure the gpio chip */ chip = &gpio->chip; From 40b0bcd3e0e258cff3382717fb287f8be161a398 Mon Sep 17 00:00:00 2001 From: Song Hui Date: Wed, 7 Aug 2019 10:12:54 +0800 Subject: [PATCH 28/82] gpio: mpc8xxx: Add new platforms GPIO DT node description Update the NXP GPIO node dt-binding file for QorIQ and Layerscape platforms, and add one more example with ls1028a GPIO node. Signed-off-by: Song Hui Link: https://lore.kernel.org/r/20190807021254.49092-1-hui.song_1@nxp.com Signed-off-by: Linus Walleij --- .../devicetree/bindings/gpio/gpio-mpc8xxx.txt | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt index 69d46162d0f5..baf95d93f85d 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt @@ -4,7 +4,7 @@ Required properties: - compatible : Should be "fsl,-gpio" The following s are known to be supported: mpc5121, mpc5125, mpc8349, mpc8572, mpc8610, pq3, qoriq, - ls1021a, ls1043a, ls2080a. + ls1021a, ls1043a, ls2080a, ls1028a. - reg : Address and length of the register set for the device - interrupts : Should be the port interrupt shared by all 32 pins. - #gpio-cells : Should be two. The first cell is the pin number and @@ -37,3 +37,17 @@ gpio0: gpio@2300000 { interrupt-controller; #interrupt-cells = <2>; }; + + +Example of gpio-controller node for a ls1028a SoC: + +gpio1: gpio@2300000 { + compatible = "fsl,ls1028a-gpio","fsl,qoriq-gpio"; + reg = <0x0 0x2300000 0x0 0x10000>; + interrupts = ; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + little-endian; +}; From b772d7aeae093a120c737c0183df532262229efe Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 9 Aug 2019 22:27:31 +0200 Subject: [PATCH 29/82] gpio: remove ks8695 driver The platform is getting removed, so there are no remaining users of this driver. Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20190809202749.742267-4-arnd@arndb.de Signed-off-by: Linus Walleij --- drivers/gpio/Makefile | 1 - drivers/gpio/gpio-ks8695.c | 284 ------------------------------------- 2 files changed, 285 deletions(-) delete mode 100644 drivers/gpio/gpio-ks8695.c diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index a4e91175c708..65d74084c9b2 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -67,7 +67,6 @@ obj-$(CONFIG_GPIO_IT87) += gpio-it87.o obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o -obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o diff --git a/drivers/gpio/gpio-ks8695.c b/drivers/gpio/gpio-ks8695.c deleted file mode 100644 index a0f87c124894..000000000000 --- a/drivers/gpio/gpio-ks8695.c +++ /dev/null @@ -1,284 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * arch/arm/mach-ks8695/gpio.c - * - * Copyright (C) 2006 Andrew Victor - * Updated to GPIOLIB, Copyright 2008 Simtec Electronics - * Daniel Silverstone - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -/* - * Configure a GPIO line for either GPIO function, or its internal - * function (Interrupt, Timer, etc). - */ -static void ks8695_gpio_mode(unsigned int pin, short gpio) -{ - unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN }; - unsigned long x, flags; - - if (pin > KS8695_GPIO_5) /* only GPIO 0..5 have internal functions */ - return; - - local_irq_save(flags); - - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC); - if (gpio) /* GPIO: set bit to 0 */ - x &= ~enable[pin]; - else /* Internal function: set bit to 1 */ - x |= enable[pin]; - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC); - - local_irq_restore(flags); -} - - -static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 }; - -/* - * Configure GPIO pin as external interrupt source. - */ -int ks8695_gpio_interrupt(unsigned int pin, unsigned int type) -{ - unsigned long x, flags; - - if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */ - return -EINVAL; - - local_irq_save(flags); - - /* set pin as input */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); - x &= ~IOPM(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); - - local_irq_restore(flags); - - /* Set IRQ triggering type */ - irq_set_irq_type(gpio_irq[pin], type); - - /* enable interrupt mode */ - ks8695_gpio_mode(pin, 0); - - return 0; -} -EXPORT_SYMBOL(ks8695_gpio_interrupt); - - - -/* .... Generic GPIO interface .............................................. */ - -/* - * Configure the GPIO line as an input. - */ -static int ks8695_gpio_direction_input(struct gpio_chip *gc, unsigned int pin) -{ - unsigned long x, flags; - - if (pin > KS8695_GPIO_15) - return -EINVAL; - - /* set pin to GPIO mode */ - ks8695_gpio_mode(pin, 1); - - local_irq_save(flags); - - /* set pin as input */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); - x &= ~IOPM(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); - - local_irq_restore(flags); - - return 0; -} - - -/* - * Configure the GPIO line as an output, with default state. - */ -static int ks8695_gpio_direction_output(struct gpio_chip *gc, - unsigned int pin, int state) -{ - unsigned long x, flags; - - if (pin > KS8695_GPIO_15) - return -EINVAL; - - /* set pin to GPIO mode */ - ks8695_gpio_mode(pin, 1); - - local_irq_save(flags); - - /* set line state */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); - if (state) - x |= IOPD(pin); - else - x &= ~IOPD(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD); - - /* set pin as output */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); - x |= IOPM(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); - - local_irq_restore(flags); - - return 0; -} - - -/* - * Set the state of an output GPIO line. - */ -static void ks8695_gpio_set_value(struct gpio_chip *gc, - unsigned int pin, int state) -{ - unsigned long x, flags; - - if (pin > KS8695_GPIO_15) - return; - - local_irq_save(flags); - - /* set output line state */ - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); - if (state) - x |= IOPD(pin); - else - x &= ~IOPD(pin); - __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD); - - local_irq_restore(flags); -} - - -/* - * Read the state of a GPIO line. - */ -static int ks8695_gpio_get_value(struct gpio_chip *gc, unsigned int pin) -{ - unsigned long x; - - if (pin > KS8695_GPIO_15) - return -EINVAL; - - x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); - return (x & IOPD(pin)) != 0; -} - - -/* - * Map GPIO line to IRQ number. - */ -static int ks8695_gpio_to_irq(struct gpio_chip *gc, unsigned int pin) -{ - if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */ - return -EINVAL; - - return gpio_irq[pin]; -} - -/* GPIOLIB interface */ - -static struct gpio_chip ks8695_gpio_chip = { - .label = "KS8695", - .direction_input = ks8695_gpio_direction_input, - .direction_output = ks8695_gpio_direction_output, - .get = ks8695_gpio_get_value, - .set = ks8695_gpio_set_value, - .to_irq = ks8695_gpio_to_irq, - .base = 0, - .ngpio = 16, - .can_sleep = false, -}; - -/* Register the GPIOs */ -void ks8695_register_gpios(void) -{ - if (gpiochip_add_data(&ks8695_gpio_chip, NULL)) - printk(KERN_ERR "Unable to register core GPIOs\n"); -} - -/* .... Debug interface ..................................................... */ - -#ifdef CONFIG_DEBUG_FS - -static int ks8695_gpio_show(struct seq_file *s, void *unused) -{ - unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN }; - unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM }; - unsigned long mode, ctrl, data; - int i; - - mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); - ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC); - data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); - - seq_printf(s, "Pin\tI/O\tFunction\tState\n\n"); - - for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) { - seq_printf(s, "%i:\t", i); - - seq_printf(s, "%s\t", (mode & IOPM(i)) ? "Output" : "Input"); - - if (i <= KS8695_GPIO_3) { - if (ctrl & enable[i]) { - seq_printf(s, "EXT%i ", i); - - switch ((ctrl & intmask[i]) >> (4 * i)) { - case IOPC_TM_LOW: - seq_printf(s, "(Low)"); break; - case IOPC_TM_HIGH: - seq_printf(s, "(High)"); break; - case IOPC_TM_RISING: - seq_printf(s, "(Rising)"); break; - case IOPC_TM_FALLING: - seq_printf(s, "(Falling)"); break; - case IOPC_TM_EDGE: - seq_printf(s, "(Edges)"); break; - } - } else - seq_printf(s, "GPIO\t"); - } else if (i <= KS8695_GPIO_5) { - if (ctrl & enable[i]) - seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4); - else - seq_printf(s, "GPIO\t"); - } else { - seq_printf(s, "GPIO\t"); - } - - seq_printf(s, "\t"); - - seq_printf(s, "%i\n", (data & IOPD(i)) ? 1 : 0); - } - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(ks8695_gpio); - -static int __init ks8695_gpio_debugfs_init(void) -{ - /* /sys/kernel/debug/ks8695_gpio */ - debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, - &ks8695_gpio_fops); - return 0; -} -postcore_initcall(ks8695_gpio_debugfs_init); - -#endif From f2ee73147a3f23cc4b032a76b5677b4b8441ba74 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 9 Aug 2019 16:40:31 +0200 Subject: [PATCH 30/82] gpio: lpc32xx: allow building on non-lpc32xx targets The driver uses hardwire MMIO addresses instead of the data that is passed in device tree. Change it over to only hardcode the register offset values and allow compile-testing. Acked-by: Sylvain Lemieux Tested-by: Sylvain Lemieux Signed-off-by: Arnd Bergmann Signed-off-by: Bartosz Golaszewski --- arch/arm/configs/lpc32xx_defconfig | 1 + drivers/gpio/Kconfig | 7 ++ drivers/gpio/Makefile | 2 +- drivers/gpio/gpio-lpc32xx.c | 118 +++++++++++++++++------------ 4 files changed, 77 insertions(+), 51 deletions(-) diff --git a/arch/arm/configs/lpc32xx_defconfig b/arch/arm/configs/lpc32xx_defconfig index 0cdc6c7974b3..3772d5a8975a 100644 --- a/arch/arm/configs/lpc32xx_defconfig +++ b/arch/arm/configs/lpc32xx_defconfig @@ -93,6 +93,7 @@ CONFIG_SERIAL_HS_LPC32XX_CONSOLE=y # CONFIG_HW_RANDOM is not set CONFIG_I2C_CHARDEV=y CONFIG_I2C_PNX=y +CONFIG_GPIO_LPC32XX=y CONFIG_SPI=y CONFIG_SPI_PL022=y CONFIG_GPIO_SYSFS=y diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index bb13c266c329..8b40a578963c 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -311,6 +311,13 @@ config GPIO_LPC18XX Select this option to enable GPIO driver for NXP LPC18XX/43XX devices. +config GPIO_LPC32XX + tristate "NXP LPC32XX GPIO support" + depends on OF_GPIO && (ARCH_LPC32XX || COMPILE_TEST) + help + Select this option to enable GPIO driver for + NXP LPC32XX devices. + config GPIO_LYNXPOINT tristate "Intel Lynxpoint GPIO support" depends on ACPI && X86 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index a4e91175c708..87d659ae95eb 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -74,7 +74,7 @@ obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o obj-$(CONFIG_GPIO_LP873X) += gpio-lp873x.o obj-$(CONFIG_GPIO_LP87565) += gpio-lp87565.o obj-$(CONFIG_GPIO_LPC18XX) += gpio-lpc18xx.o -obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o +obj-$(CONFIG_GPIO_LPC32XX) += gpio-lpc32xx.o obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o obj-$(CONFIG_GPIO_MADERA) += gpio-madera.o obj-$(CONFIG_GPIO_MAX3191X) += gpio-max3191x.o diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index 24885b3db3d5..4e626c4235c2 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -16,36 +16,33 @@ #include #include -#include -#include - -#define LPC32XX_GPIO_P3_INP_STATE _GPREG(0x000) -#define LPC32XX_GPIO_P3_OUTP_SET _GPREG(0x004) -#define LPC32XX_GPIO_P3_OUTP_CLR _GPREG(0x008) -#define LPC32XX_GPIO_P3_OUTP_STATE _GPREG(0x00C) -#define LPC32XX_GPIO_P2_DIR_SET _GPREG(0x010) -#define LPC32XX_GPIO_P2_DIR_CLR _GPREG(0x014) -#define LPC32XX_GPIO_P2_DIR_STATE _GPREG(0x018) -#define LPC32XX_GPIO_P2_INP_STATE _GPREG(0x01C) -#define LPC32XX_GPIO_P2_OUTP_SET _GPREG(0x020) -#define LPC32XX_GPIO_P2_OUTP_CLR _GPREG(0x024) -#define LPC32XX_GPIO_P2_MUX_SET _GPREG(0x028) -#define LPC32XX_GPIO_P2_MUX_CLR _GPREG(0x02C) -#define LPC32XX_GPIO_P2_MUX_STATE _GPREG(0x030) -#define LPC32XX_GPIO_P0_INP_STATE _GPREG(0x040) -#define LPC32XX_GPIO_P0_OUTP_SET _GPREG(0x044) -#define LPC32XX_GPIO_P0_OUTP_CLR _GPREG(0x048) -#define LPC32XX_GPIO_P0_OUTP_STATE _GPREG(0x04C) -#define LPC32XX_GPIO_P0_DIR_SET _GPREG(0x050) -#define LPC32XX_GPIO_P0_DIR_CLR _GPREG(0x054) -#define LPC32XX_GPIO_P0_DIR_STATE _GPREG(0x058) -#define LPC32XX_GPIO_P1_INP_STATE _GPREG(0x060) -#define LPC32XX_GPIO_P1_OUTP_SET _GPREG(0x064) -#define LPC32XX_GPIO_P1_OUTP_CLR _GPREG(0x068) -#define LPC32XX_GPIO_P1_OUTP_STATE _GPREG(0x06C) -#define LPC32XX_GPIO_P1_DIR_SET _GPREG(0x070) -#define LPC32XX_GPIO_P1_DIR_CLR _GPREG(0x074) -#define LPC32XX_GPIO_P1_DIR_STATE _GPREG(0x078) +#define LPC32XX_GPIO_P3_INP_STATE (0x000) +#define LPC32XX_GPIO_P3_OUTP_SET (0x004) +#define LPC32XX_GPIO_P3_OUTP_CLR (0x008) +#define LPC32XX_GPIO_P3_OUTP_STATE (0x00C) +#define LPC32XX_GPIO_P2_DIR_SET (0x010) +#define LPC32XX_GPIO_P2_DIR_CLR (0x014) +#define LPC32XX_GPIO_P2_DIR_STATE (0x018) +#define LPC32XX_GPIO_P2_INP_STATE (0x01C) +#define LPC32XX_GPIO_P2_OUTP_SET (0x020) +#define LPC32XX_GPIO_P2_OUTP_CLR (0x024) +#define LPC32XX_GPIO_P2_MUX_SET (0x028) +#define LPC32XX_GPIO_P2_MUX_CLR (0x02C) +#define LPC32XX_GPIO_P2_MUX_STATE (0x030) +#define LPC32XX_GPIO_P0_INP_STATE (0x040) +#define LPC32XX_GPIO_P0_OUTP_SET (0x044) +#define LPC32XX_GPIO_P0_OUTP_CLR (0x048) +#define LPC32XX_GPIO_P0_OUTP_STATE (0x04C) +#define LPC32XX_GPIO_P0_DIR_SET (0x050) +#define LPC32XX_GPIO_P0_DIR_CLR (0x054) +#define LPC32XX_GPIO_P0_DIR_STATE (0x058) +#define LPC32XX_GPIO_P1_INP_STATE (0x060) +#define LPC32XX_GPIO_P1_OUTP_SET (0x064) +#define LPC32XX_GPIO_P1_OUTP_CLR (0x068) +#define LPC32XX_GPIO_P1_OUTP_STATE (0x06C) +#define LPC32XX_GPIO_P1_DIR_SET (0x070) +#define LPC32XX_GPIO_P1_DIR_CLR (0x074) +#define LPC32XX_GPIO_P1_DIR_STATE (0x078) #define GPIO012_PIN_TO_BIT(x) (1 << (x)) #define GPIO3_PIN_TO_BIT(x) (1 << ((x) + 25)) @@ -72,12 +69,12 @@ #define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX) struct gpio_regs { - void __iomem *inp_state; - void __iomem *outp_state; - void __iomem *outp_set; - void __iomem *outp_clr; - void __iomem *dir_set; - void __iomem *dir_clr; + unsigned long inp_state; + unsigned long outp_state; + unsigned long outp_set; + unsigned long outp_clr; + unsigned long dir_set; + unsigned long dir_clr; }; /* @@ -165,16 +162,27 @@ static struct gpio_regs gpio_grp_regs_p3 = { struct lpc32xx_gpio_chip { struct gpio_chip chip; struct gpio_regs *gpio_grp; + void __iomem *reg_base; }; +static inline u32 gpreg_read(struct lpc32xx_gpio_chip *group, unsigned long offset) +{ + return __raw_readl(group->reg_base + offset); +} + +static inline void gpreg_write(struct lpc32xx_gpio_chip *group, u32 val, unsigned long offset) +{ + __raw_writel(val, group->reg_base + offset); +} + static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group, unsigned pin, int input) { if (input) - __raw_writel(GPIO012_PIN_TO_BIT(pin), + gpreg_write(group, GPIO012_PIN_TO_BIT(pin), group->gpio_grp->dir_clr); else - __raw_writel(GPIO012_PIN_TO_BIT(pin), + gpreg_write(group, GPIO012_PIN_TO_BIT(pin), group->gpio_grp->dir_set); } @@ -184,19 +192,19 @@ static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group, u32 u = GPIO3_PIN_TO_BIT(pin); if (input) - __raw_writel(u, group->gpio_grp->dir_clr); + gpreg_write(group, u, group->gpio_grp->dir_clr); else - __raw_writel(u, group->gpio_grp->dir_set); + gpreg_write(group, u, group->gpio_grp->dir_set); } static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group, unsigned pin, int high) { if (high) - __raw_writel(GPIO012_PIN_TO_BIT(pin), + gpreg_write(group, GPIO012_PIN_TO_BIT(pin), group->gpio_grp->outp_set); else - __raw_writel(GPIO012_PIN_TO_BIT(pin), + gpreg_write(group, GPIO012_PIN_TO_BIT(pin), group->gpio_grp->outp_clr); } @@ -206,31 +214,31 @@ static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group, u32 u = GPIO3_PIN_TO_BIT(pin); if (high) - __raw_writel(u, group->gpio_grp->outp_set); + gpreg_write(group, u, group->gpio_grp->outp_set); else - __raw_writel(u, group->gpio_grp->outp_clr); + gpreg_write(group, u, group->gpio_grp->outp_clr); } static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group, unsigned pin, int high) { if (high) - __raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set); + gpreg_write(group, GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set); else - __raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr); + gpreg_write(group, GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr); } static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group, unsigned pin) { - return GPIO012_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), + return GPIO012_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->inp_state), pin); } static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group, unsigned pin) { - int state = __raw_readl(group->gpio_grp->inp_state); + int state = gpreg_read(group, group->gpio_grp->inp_state); /* * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped @@ -242,13 +250,13 @@ static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group, static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group, unsigned pin) { - return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin); + return GPI3_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->inp_state), pin); } static int __get_gpo_state_p3(struct lpc32xx_gpio_chip *group, unsigned pin) { - return GPO3_PIN_IN_SEL(__raw_readl(group->gpio_grp->outp_state), pin); + return GPO3_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->outp_state), pin); } /* @@ -497,12 +505,18 @@ static int lpc32xx_of_xlate(struct gpio_chip *gc, static int lpc32xx_gpio_probe(struct platform_device *pdev) { int i; + void __iomem *reg_base; + + reg_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(reg_base)) + return PTR_ERR(reg_base); for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++) { if (pdev->dev.of_node) { lpc32xx_gpiochip[i].chip.of_xlate = lpc32xx_of_xlate; lpc32xx_gpiochip[i].chip.of_gpio_n_cells = 3; lpc32xx_gpiochip[i].chip.of_node = pdev->dev.of_node; + lpc32xx_gpiochip[i].reg_base = reg_base; } devm_gpiochip_add_data(&pdev->dev, &lpc32xx_gpiochip[i].chip, &lpc32xx_gpiochip[i]); @@ -527,3 +541,7 @@ static struct platform_driver lpc32xx_gpio_driver = { }; module_platform_driver(lpc32xx_gpio_driver); + +MODULE_AUTHOR("Kevin Wells "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("GPIO driver for LPC32xx SoC"); From 8069e69a9792402b52eff61e5bb874fa94798fc9 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 11 Aug 2019 10:05:39 +0200 Subject: [PATCH 31/82] gpio: intel-mid: Pass irqchip when adding gpiochip We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. Cc: Andy Shevchenko Cc: Mika Westerberg Cc: David Cohen Cc: Thierry Reding Signed-off-by: Linus Walleij Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-intel-mid.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c index 4e803baf980e..4d835f9089df 100644 --- a/drivers/gpio/gpio-intel-mid.c +++ b/drivers/gpio/gpio-intel-mid.c @@ -329,6 +329,7 @@ static int intel_gpio_probe(struct pci_dev *pdev, u32 gpio_base; u32 irq_base; int retval; + struct gpio_irq_chip *girq; struct intel_mid_gpio_ddata *ddata = (struct intel_mid_gpio_ddata *)id->driver_data; @@ -369,6 +370,22 @@ static int intel_gpio_probe(struct pci_dev *pdev, spin_lock_init(&priv->lock); + girq = &priv->chip.irq; + girq->chip = &intel_mid_irqchip; + girq->parent_handler = intel_mid_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = pdev->irq; + girq->first = irq_base; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; + + intel_mid_irq_init_hw(priv); + pci_set_drvdata(pdev, priv); retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv); if (retval) { @@ -376,24 +393,6 @@ static int intel_gpio_probe(struct pci_dev *pdev, return retval; } - retval = gpiochip_irqchip_add(&priv->chip, - &intel_mid_irqchip, - irq_base, - handle_simple_irq, - IRQ_TYPE_NONE); - if (retval) { - dev_err(&pdev->dev, - "could not connect irqchip to gpiochip\n"); - return retval; - } - - intel_mid_irq_init_hw(priv); - - gpiochip_set_chained_irqchip(&priv->chip, - &intel_mid_irqchip, - pdev->irq, - intel_mid_irq_handler); - pm_runtime_put_noidle(&pdev->dev); pm_runtime_allow(&pdev->dev); From 7b1e889436a156c2c88953fbc5602a64a75889bd Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 12 Aug 2019 10:13:51 +0200 Subject: [PATCH 32/82] gpio: lynxpoint: Pass irqchip when adding gpiochip We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. Cc: Andy Shevchenko Cc: Mika Westerberg Cc: David Cohen Cc: Thierry Reding Signed-off-by: Linus Walleij Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-lynxpoint.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c index 31b4a091ab60..6bb9741ad036 100644 --- a/drivers/gpio/gpio-lynxpoint.c +++ b/drivers/gpio/gpio-lynxpoint.c @@ -358,27 +358,32 @@ static int lp_gpio_probe(struct platform_device *pdev) gc->can_sleep = false; gc->parent = dev; + /* set up interrupts */ + if (irq_rc && irq_rc->start) { + struct gpio_irq_chip *girq; + + girq = &gc->irq; + girq->chip = &lp_irqchip; + girq->parent_handler = lp_gpio_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = (unsigned)irq_rc->start; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; + + lp_gpio_irq_init_hw(lg); + } + ret = devm_gpiochip_add_data(dev, gc, lg); if (ret) { dev_err(dev, "failed adding lp-gpio chip\n"); return ret; } - /* set up interrupts */ - if (irq_rc && irq_rc->start) { - lp_gpio_irq_init_hw(lg); - ret = gpiochip_irqchip_add(gc, &lp_irqchip, 0, - handle_simple_irq, IRQ_TYPE_NONE); - if (ret) { - dev_err(dev, "failed to add irqchip\n"); - return ret; - } - - gpiochip_set_chained_irqchip(gc, &lp_irqchip, - (unsigned)irq_rc->start, - lp_gpio_irq_handler); - } - pm_runtime_enable(dev); return 0; From 8f86a5b4ad679e4836733b47414226074eee4e4d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 12 Aug 2019 10:23:31 +0200 Subject: [PATCH 33/82] gpio: merrifield: Pass irqchip when adding gpiochip We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. Cc: Andy Shevchenko Cc: Mika Westerberg Cc: David Cohen Cc: Thierry Reding Signed-off-by: Linus Walleij Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-merrifield.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c index 3302125e5265..4f27ddfe1e2f 100644 --- a/drivers/gpio/gpio-merrifield.c +++ b/drivers/gpio/gpio-merrifield.c @@ -397,6 +397,7 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id { const struct mrfld_gpio_pinrange *range; const char *pinctrl_dev_name; + struct gpio_irq_chip *girq; struct mrfld_gpio *priv; u32 gpio_base, irq_base; void __iomem *base; @@ -444,6 +445,21 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id raw_spin_lock_init(&priv->lock); + girq = &priv->chip.irq; + girq->chip = &mrfld_irqchip; + girq->parent_handler = mrfld_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = pdev->irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + + mrfld_irq_init_hw(priv); + pci_set_drvdata(pdev, priv); retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv); if (retval) { @@ -465,18 +481,6 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id } } - retval = gpiochip_irqchip_add(&priv->chip, &mrfld_irqchip, irq_base, - handle_bad_irq, IRQ_TYPE_NONE); - if (retval) { - dev_err(&pdev->dev, "could not connect irqchip to gpiochip\n"); - return retval; - } - - mrfld_irq_init_hw(priv); - - gpiochip_set_chained_irqchip(&priv->chip, &mrfld_irqchip, pdev->irq, - mrfld_irq_handler); - return 0; } From 7a637fd32b234d4605fdf3c75c622b0ca1ce8cfb Mon Sep 17 00:00:00 2001 From: Hongwei Zhang Date: Wed, 31 Jul 2019 16:01:36 -0400 Subject: [PATCH 34/82] dt-bindings: gpio: aspeed: Add SGPIO support Add bindings to support SGPIO on AST2400 or AST2500. Signed-off-by: Hongwei Zhang Reviewed-by: Andrew Jeffery Link: https://lore.kernel.org/r/1564603297-1391-2-git-send-email-hongweiz@ami.com [Adjusted when applying in several ways] Signed-off-by: Linus Walleij --- .../devicetree/bindings/gpio/sgpio-aspeed.txt | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt diff --git a/Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt b/Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt new file mode 100644 index 000000000000..d4d83916c09d --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt @@ -0,0 +1,45 @@ +Aspeed SGPIO controller Device Tree Bindings +-------------------------------------------- + +This SGPIO controller is for ASPEED AST2500 SoC, it supports up to 80 full +featured Serial GPIOs. Each of the Serial GPIO pins can be programmed to +support the following options: +- Support interrupt option for each input port and various interrupt + sensitivity option (level-high, level-low, edge-high, edge-low) +- Support reset tolerance option for each output port +- Directly connected to APB bus and its shift clock is from APB bus clock + divided by a programmable value. +- Co-work with external signal-chained TTL components (74LV165/74LV595) + +Required properties: + +- compatible : Should be one of + "aspeed,ast2400-sgpio", "aspeed,ast2500-sgpio" +- #gpio-cells : Should be 2, see gpio.txt +- reg : Address and length of the register set for the device +- gpio-controller : Marks the device node as a GPIO controller +- interrupts : Interrupt specifier, see interrupt-controller/interrupts.txt +- interrupt-controller : Mark the GPIO controller as an interrupt-controller +- ngpios : number of GPIO lines, see gpio.txt + (should be multiple of 8, up to 80 pins) +- clocks : A phandle to the APB clock for SGPM clock division +- bus-frequency : SGPM CLK frequency + +The sgpio and interrupt properties are further described in their respective +bindings documentation: + +- Documentation/devicetree/bindings/gpio/gpio.txt +- Documentation/devicetree/bindings/interrupt-controller/interrupts.txt + + Example: + sgpio: sgpio@1e780200 { + #gpio-cells = <2>; + compatible = "aspeed,ast2500-sgpio"; + gpio-controller; + interrupts = <40>; + reg = <0x1e780200 0x0100>; + clocks = <&syscon ASPEED_CLK_APB>; + interrupt-controller; + ngpios = <8>; + bus-frequency = <12000000>; + }; From fdd61a013a24f2699aec1a446f0168682b6f9ec4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 8 Aug 2019 14:32:37 +0200 Subject: [PATCH 35/82] gpio: Add support for hierarchical IRQ domains Hierarchical IRQ domains can be used to stack different IRQ controllers on top of each other. Bring hierarchical IRQ domains into the GPIOLIB core with the following basic idea: Drivers that need their interrupts handled hierarchically specify a callback to translate the child hardware IRQ and IRQ type for each GPIO offset to a parent hardware IRQ and parent hardware IRQ type. Users have to pass the callback, fwnode, and parent irqdomain before calling gpiochip_irqchip_add(). We use the new method of just filling in the struct gpio_irq_chip before adding the gpiochip for all hierarchical irqchips of this type. The code path for device tree is pretty straight-forward, while the code path for old boardfiles or anything else will be more convoluted requireing upfront allocation of the interrupts when adding the chip. One specific use-case where this can be useful is if a power management controller has top-level controls for wakeup interrupts. In such cases, the power management controller can be a parent to other interrupt controllers and program additional registers when an IRQ has its wake capability enabled or disabled. The hierarchical irqchip helper code will only be available when IRQ_DOMAIN_HIERARCHY is selected to GPIO chips using this should select or depend on that symbol. When using hierarchical IRQs, the parent interrupt controller must also be hierarchical all the way up to the top interrupt controller wireing directly into the CPU, so on systems that do not have this we can get rid of all the extra code for supporting hierarchical irqs. Cc: Thomas Gleixner Cc: Marc Zyngier Cc: Lina Iyer Cc: Jon Hunter Cc: Sowjanya Komatineni Cc: Bitan Biswas Cc: linux-tegra@vger.kernel.org Cc: David Daney Cc: Masahiro Yamada Cc: Brian Masney Signed-off-by: Thierry Reding Signed-off-by: Brian Masney Co-developed-by: Brian Masney Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190808123242.5359-1-linus.walleij@linaro.org --- Documentation/driver-api/gpio/driver.rst | 120 ++++++++- drivers/gpio/gpiolib.c | 318 ++++++++++++++++++++++- include/linux/gpio/driver.h | 111 ++++++++ 3 files changed, 525 insertions(+), 24 deletions(-) diff --git a/Documentation/driver-api/gpio/driver.rst b/Documentation/driver-api/gpio/driver.rst index 921c71a3d683..5e96dbc7f4e7 100644 --- a/Documentation/driver-api/gpio/driver.rst +++ b/Documentation/driver-api/gpio/driver.rst @@ -259,7 +259,7 @@ most often cascaded off a parent interrupt controller, and in some special cases the GPIO logic is melded with a SoC's primary interrupt controller. The IRQ portions of the GPIO block are implemented using an irq_chip, using -the header . So basically such a driver is utilizing two sub- +the header . So this combined driver is utilizing two sub- systems simultaneously: gpio and irq. It is legal for any IRQ consumer to request an IRQ from any irqchip even if it @@ -391,25 +391,119 @@ Infrastructure helpers for GPIO irqchips ---------------------------------------- To help out in handling the set-up and management of GPIO irqchips and the -associated irqdomain and resource allocation callbacks, the gpiolib has -some helpers that can be enabled by selecting the GPIOLIB_IRQCHIP Kconfig -symbol: +associated irqdomain and resource allocation callbacks. These are activated +by selecting the Kconfig symbol GPIOLIB_IRQCHIP. If the symbol +IRQ_DOMAIN_HIERARCHY is also selected, hierarchical helpers will also be +provided. A big portion of overhead code will be managed by gpiolib, +under the assumption that your interrupts are 1-to-1-mapped to the +GPIO line index: -- gpiochip_irqchip_add(): adds a chained cascaded irqchip to a gpiochip. It - will pass the struct gpio_chip* for the chip to all IRQ callbacks, so the - callbacks need to embed the gpio_chip in its state container and obtain a - pointer to the container using container_of(). - (See Documentation/driver-api/driver-model/design-patterns.rst) + GPIO line offset Hardware IRQ + 0 0 + 1 1 + 2 2 + ... ... + ngpio-1 ngpio-1 + +If some GPIO lines do not have corresponding IRQs, the bitmask valid_mask +and the flag need_valid_mask in gpio_irq_chip can be used to mask off some +lines as invalid for associating with IRQs. + +The preferred way to set up the helpers is to fill in the +struct gpio_irq_chip inside struct gpio_chip before adding the gpio_chip. +If you do this, the additional irq_chip will be set up by gpiolib at the +same time as setting up the rest of the GPIO functionality. The following +is a typical example of a cascaded interrupt handler using gpio_irq_chip: + + /* Typical state container with dynamic irqchip */ + struct my_gpio { + struct gpio_chip gc; + struct irq_chip irq; + }; + + int irq; /* from platform etc */ + struct my_gpio *g; + struct gpio_irq_chip *girq; + + /* Set up the irqchip dynamically */ + g->irq.name = "my_gpio_irq"; + g->irq.irq_ack = my_gpio_ack_irq; + g->irq.irq_mask = my_gpio_mask_irq; + g->irq.irq_unmask = my_gpio_unmask_irq; + g->irq.irq_set_type = my_gpio_set_irq_type; + + /* Get a pointer to the gpio_irq_chip */ + girq = &g->gc.irq; + girq->chip = &g->irq; + girq->parent_handler = ftgpio_gpio_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + girq->parents[0] = irq; + + return devm_gpiochip_add_data(dev, &g->gc, g); + +The helper support using hierarchical interrupt controllers as well. +In this case the typical set-up will look like this: + + /* Typical state container with dynamic irqchip */ + struct my_gpio { + struct gpio_chip gc; + struct irq_chip irq; + struct fwnode_handle *fwnode; + }; + + int irq; /* from platform etc */ + struct my_gpio *g; + struct gpio_irq_chip *girq; + + /* Set up the irqchip dynamically */ + g->irq.name = "my_gpio_irq"; + g->irq.irq_ack = my_gpio_ack_irq; + g->irq.irq_mask = my_gpio_mask_irq; + g->irq.irq_unmask = my_gpio_unmask_irq; + g->irq.irq_set_type = my_gpio_set_irq_type; + + /* Get a pointer to the gpio_irq_chip */ + girq = &g->gc.irq; + girq->chip = &g->irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + girq->fwnode = g->fwnode; + girq->parent_domain = parent; + girq->child_to_parent_hwirq = my_gpio_child_to_parent_hwirq; + + return devm_gpiochip_add_data(dev, &g->gc, g); + +As you can see pretty similar, but you do not supply a parent handler for +the IRQ, instead a parent irqdomain, an fwnode for the hardware and +a funcion .child_to_parent_hwirq() that has the purpose of looking up +the parent hardware irq from a child (i.e. this gpio chip) hardware irq. +As always it is good to look at examples in the kernel tree for advice +on how to find the required pieces. + +The old way of adding irqchips to gpiochips after registration is also still +available but we try to move away from this: + +- DEPRECATED: gpiochip_irqchip_add(): adds a chained cascaded irqchip to a + gpiochip. It will pass the struct gpio_chip* for the chip to all IRQ + callbacks, so the callbacks need to embed the gpio_chip in its state + container and obtain a pointer to the container using container_of(). + (See Documentation/driver-model/design-patterns.txt) - gpiochip_irqchip_add_nested(): adds a nested cascaded irqchip to a gpiochip, as discussed above regarding different types of cascaded irqchips. The cascaded irq has to be handled by a threaded interrupt handler. Apart from that it works exactly like the chained irqchip. -- gpiochip_set_chained_irqchip(): sets up a chained cascaded irq handler for a - gpio_chip from a parent IRQ and passes the struct gpio_chip* as handler - data. Notice that we pass is as the handler data, since the irqchip data is - likely used by the parent irqchip. +- DEPRECATED: gpiochip_set_chained_irqchip(): sets up a chained cascaded irq + handler for a gpio_chip from a parent IRQ and passes the struct gpio_chip* + as handler data. Notice that we pass is as the handler data, since the + irqchip data is likely used by the parent irqchip. - gpiochip_set_nested_irqchip(): sets up a nested cascaded irq handler for a gpio_chip from a parent IRQ. As the parent IRQ has usually been diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 537a37a89891..5277b8f1ff7c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1720,6 +1720,273 @@ void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip, } EXPORT_SYMBOL_GPL(gpiochip_set_nested_irqchip); +#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY + +/** + * gpiochip_set_hierarchical_irqchip() - connects a hierarchical irqchip + * to a gpiochip + * @gc: the gpiochip to set the irqchip hierarchical handler to + * @irqchip: the irqchip to handle this level of the hierarchy, the interrupt + * will then percolate up to the parent + */ +static void gpiochip_set_hierarchical_irqchip(struct gpio_chip *gc, + struct irq_chip *irqchip) +{ + /* DT will deal with mapping each IRQ as we go along */ + if (is_of_node(gc->irq.fwnode)) + return; + + /* + * This is for legacy and boardfile "irqchip" fwnodes: allocate + * irqs upfront instead of dynamically since we don't have the + * dynamic type of allocation that hardware description languages + * provide. Once all GPIO drivers using board files are gone from + * the kernel we can delete this code, but for a transitional period + * it is necessary to keep this around. + */ + if (is_fwnode_irqchip(gc->irq.fwnode)) { + int i; + int ret; + + for (i = 0; i < gc->ngpio; i++) { + struct irq_fwspec fwspec; + unsigned int parent_hwirq; + unsigned int parent_type; + struct gpio_irq_chip *girq = &gc->irq; + + /* + * We call the child to parent translation function + * only to check if the child IRQ is valid or not. + * Just pick the rising edge type here as that is what + * we likely need to support. + */ + ret = girq->child_to_parent_hwirq(gc, i, + IRQ_TYPE_EDGE_RISING, + &parent_hwirq, + &parent_type); + if (ret) { + chip_err(gc, "skip set-up on hwirq %d\n", + i); + continue; + } + + fwspec.fwnode = gc->irq.fwnode; + /* This is the hwirq for the GPIO line side of things */ + fwspec.param[0] = girq->child_offset_to_irq(gc, i); + /* Just pick something */ + fwspec.param[1] = IRQ_TYPE_EDGE_RISING; + fwspec.param_count = 2; + ret = __irq_domain_alloc_irqs(gc->irq.domain, + /* just pick something */ + -1, + 1, + NUMA_NO_NODE, + &fwspec, + false, + NULL); + if (ret < 0) { + chip_err(gc, + "can not allocate irq for GPIO line %d parent hwirq %d in hierarchy domain: %d\n", + i, parent_hwirq, + ret); + } + } + } + + chip_err(gc, "%s unknown fwnode type proceed anyway\n", __func__); + + return; +} + +static int gpiochip_hierarchy_irq_domain_translate(struct irq_domain *d, + struct irq_fwspec *fwspec, + unsigned long *hwirq, + unsigned int *type) +{ + /* We support standard DT translation */ + if (is_of_node(fwspec->fwnode) && fwspec->param_count == 2) { + return irq_domain_translate_twocell(d, fwspec, hwirq, type); + } + + /* This is for board files and others not using DT */ + if (is_fwnode_irqchip(fwspec->fwnode)) { + int ret; + + ret = irq_domain_translate_twocell(d, fwspec, hwirq, type); + if (ret) + return ret; + WARN_ON(*type == IRQ_TYPE_NONE); + return 0; + } + return -EINVAL; +} + +static int gpiochip_hierarchy_irq_domain_alloc(struct irq_domain *d, + unsigned int irq, + unsigned int nr_irqs, + void *data) +{ + struct gpio_chip *gc = d->host_data; + irq_hw_number_t hwirq; + unsigned int type = IRQ_TYPE_NONE; + struct irq_fwspec *fwspec = data; + struct irq_fwspec parent_fwspec; + unsigned int parent_hwirq; + unsigned int parent_type; + struct gpio_irq_chip *girq = &gc->irq; + int ret; + + /* + * The nr_irqs parameter is always one except for PCI multi-MSI + * so this should not happen. + */ + WARN_ON(nr_irqs != 1); + + ret = gc->irq.child_irq_domain_ops.translate(d, fwspec, &hwirq, &type); + if (ret) + return ret; + + chip_info(gc, "allocate IRQ %d, hwirq %lu\n", irq, hwirq); + + ret = girq->child_to_parent_hwirq(gc, hwirq, type, + &parent_hwirq, &parent_type); + if (ret) { + chip_err(gc, "can't look up hwirq %lu\n", hwirq); + return ret; + } + chip_info(gc, "found parent hwirq %u\n", parent_hwirq); + + /* + * We set handle_bad_irq because the .set_type() should + * always be invoked and set the right type of handler. + */ + irq_domain_set_info(d, + irq, + hwirq, + gc->irq.chip, + gc, + girq->handler, + NULL, NULL); + irq_set_probe(irq); + + /* + * Create a IRQ fwspec to send up to the parent irqdomain: + * specify the hwirq we address on the parent and tie it + * all together up the chain. + */ + parent_fwspec.fwnode = d->parent->fwnode; + /* This parent only handles asserted level IRQs */ + girq->populate_parent_fwspec(gc, &parent_fwspec, parent_hwirq, + parent_type); + chip_info(gc, "alloc_irqs_parent for %d parent hwirq %d\n", + irq, parent_hwirq); + ret = irq_domain_alloc_irqs_parent(d, irq, 1, &parent_fwspec); + if (ret) + chip_err(gc, + "failed to allocate parent hwirq %d for hwirq %lu\n", + parent_hwirq, hwirq); + + return ret; +} + +static unsigned int gpiochip_child_offset_to_irq_noop(struct gpio_chip *chip, + unsigned int offset) +{ + return offset; +} + +static void gpiochip_hierarchy_setup_domain_ops(struct irq_domain_ops *ops) +{ + ops->activate = gpiochip_irq_domain_activate; + ops->deactivate = gpiochip_irq_domain_deactivate; + ops->alloc = gpiochip_hierarchy_irq_domain_alloc; + ops->free = irq_domain_free_irqs_common; + + /* + * We only allow overriding the translate() function for + * hierarchical chips, and this should only be done if the user + * really need something other than 1:1 translation. + */ + if (!ops->translate) + ops->translate = gpiochip_hierarchy_irq_domain_translate; +} + +static int gpiochip_hierarchy_add_domain(struct gpio_chip *gc) +{ + if (!gc->irq.child_to_parent_hwirq || + !gc->irq.fwnode) { + chip_err(gc, "missing irqdomain vital data\n"); + return -EINVAL; + } + + if (!gc->irq.child_offset_to_irq) + gc->irq.child_offset_to_irq = gpiochip_child_offset_to_irq_noop; + + if (!gc->irq.populate_parent_fwspec) + gc->irq.populate_parent_fwspec = + gpiochip_populate_parent_fwspec_twocell; + + gpiochip_hierarchy_setup_domain_ops(&gc->irq.child_irq_domain_ops); + + gc->irq.domain = irq_domain_create_hierarchy( + gc->irq.parent_domain, + 0, + gc->ngpio, + gc->irq.fwnode, + &gc->irq.child_irq_domain_ops, + gc); + + if (!gc->irq.domain) + return -ENOMEM; + + gpiochip_set_hierarchical_irqchip(gc, gc->irq.chip); + + return 0; +} + +static bool gpiochip_hierarchy_is_hierarchical(struct gpio_chip *gc) +{ + return !!gc->irq.parent_domain; +} + +void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, + struct irq_fwspec *fwspec, + unsigned int parent_hwirq, + unsigned int parent_type) +{ + fwspec->param_count = 2; + fwspec->param[0] = parent_hwirq; + fwspec->param[1] = parent_type; +} +EXPORT_SYMBOL_GPL(gpiochip_populate_parent_fwspec_twocell); + +void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, + struct irq_fwspec *fwspec, + unsigned int parent_hwirq, + unsigned int parent_type) +{ + fwspec->param_count = 4; + fwspec->param[0] = 0; + fwspec->param[1] = parent_hwirq; + fwspec->param[2] = 0; + fwspec->param[3] = parent_type; +} +EXPORT_SYMBOL_GPL(gpiochip_populate_parent_fwspec_fourcell); + +#else + +static int gpiochip_hierarchy_add_domain(struct gpio_chip *gc) +{ + return -EINVAL; +} + +static bool gpiochip_hierarchy_is_hierarchical(struct gpio_chip *gc) +{ + return false; +} + +#endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */ + /** * gpiochip_irq_map() - maps an IRQ into a GPIO irqchip * @d: the irqdomain used by this irqchip @@ -1788,6 +2055,11 @@ static const struct irq_domain_ops gpiochip_domain_ops = { .xlate = irq_domain_xlate_twocell, }; +/* + * TODO: move these activate/deactivate in under the hierarchicial + * irqchip implementation as static once SPMI and SSBI (all external + * users) are phased over. + */ /** * gpiochip_irq_domain_activate() - Lock a GPIO to be used as an IRQ * @domain: The IRQ domain used by this IRQ chip @@ -1827,10 +2099,25 @@ EXPORT_SYMBOL_GPL(gpiochip_irq_domain_deactivate); static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset) { + struct irq_domain *domain = chip->irq.domain; + if (!gpiochip_irqchip_irq_valid(chip, offset)) return -ENXIO; - return irq_create_mapping(chip->irq.domain, offset); +#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY + if (irq_domain_is_hierarchy(domain)) { + struct irq_fwspec spec; + + spec.fwnode = domain->fwnode; + spec.param_count = 2; + spec.param[0] = chip->irq.child_offset_to_irq(chip, offset); + spec.param[1] = IRQ_TYPE_NONE; + + return irq_create_fwspec_mapping(&spec); + } +#endif + + return irq_create_mapping(domain, offset); } static int gpiochip_irq_reqres(struct irq_data *d) @@ -1907,7 +2194,7 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, struct lock_class_key *request_key) { struct irq_chip *irqchip = gpiochip->irq.chip; - const struct irq_domain_ops *ops; + const struct irq_domain_ops *ops = NULL; struct device_node *np; unsigned int type; unsigned int i; @@ -1943,16 +2230,25 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, gpiochip->irq.lock_key = lock_key; gpiochip->irq.request_key = request_key; - if (gpiochip->irq.domain_ops) - ops = gpiochip->irq.domain_ops; - else - ops = &gpiochip_domain_ops; + /* If a parent irqdomain is provided, let's build a hierarchy */ + if (gpiochip_hierarchy_is_hierarchical(gpiochip)) { + int ret = gpiochip_hierarchy_add_domain(gpiochip); + if (ret) + return ret; + } else { + /* Some drivers provide custom irqdomain ops */ + if (gpiochip->irq.domain_ops) + ops = gpiochip->irq.domain_ops; - gpiochip->irq.domain = irq_domain_add_simple(np, gpiochip->ngpio, - gpiochip->irq.first, - ops, gpiochip); - if (!gpiochip->irq.domain) - return -EINVAL; + if (!ops) + ops = &gpiochip_domain_ops; + gpiochip->irq.domain = irq_domain_add_simple(np, + gpiochip->ngpio, + gpiochip->irq.first, + ops, gpiochip); + if (!gpiochip->irq.domain) + return -EINVAL; + } if (gpiochip->irq.parent_handler) { void *data = gpiochip->irq.parent_handler_data ?: gpiochip; diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 6a0e420915a3..0e6d3b0c0211 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -23,6 +23,9 @@ enum gpio_lookup_flags; #ifdef CONFIG_GPIOLIB #ifdef CONFIG_GPIOLIB_IRQCHIP + +struct gpio_chip; + /** * struct gpio_irq_chip - GPIO interrupt controller */ @@ -49,6 +52,84 @@ struct gpio_irq_chip { */ const struct irq_domain_ops *domain_ops; +#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY + /** + * @fwnode: + * + * Firmware node corresponding to this gpiochip/irqchip, necessary + * for hierarchical irqdomain support. + */ + struct fwnode_handle *fwnode; + + /** + * @parent_domain: + * + * If non-NULL, will be set as the parent of this GPIO interrupt + * controller's IRQ domain to establish a hierarchical interrupt + * domain. The presence of this will activate the hierarchical + * interrupt support. + */ + struct irq_domain *parent_domain; + + /** + * @child_to_parent_hwirq: + * + * This callback translates a child hardware IRQ offset to a parent + * hardware IRQ offset on a hierarchical interrupt chip. The child + * hardware IRQs correspond to the GPIO index 0..ngpio-1 (see the + * ngpio field of struct gpio_chip) and the corresponding parent + * hardware IRQ and type (such as IRQ_TYPE_*) shall be returned by + * the driver. The driver can calculate this from an offset or using + * a lookup table or whatever method is best for this chip. Return + * 0 on successful translation in the driver. + * + * If some ranges of hardware IRQs do not have a corresponding parent + * HWIRQ, return -EINVAL, but also make sure to fill in @valid_mask and + * @need_valid_mask to make these GPIO lines unavailable for + * translation. + */ + int (*child_to_parent_hwirq)(struct gpio_chip *chip, + unsigned int child_hwirq, + unsigned int child_type, + unsigned int *parent_hwirq, + unsigned int *parent_type); + + /** + * @populate_parent_fwspec: + * + * This optional callback populates the &struct irq_fwspec for the + * parent's IRQ domain. If this is not specified, then + * &gpiochip_populate_parent_fwspec_twocell will be used. A four-cell + * variant named &gpiochip_populate_parent_fwspec_fourcell is also + * available. + */ + void (*populate_parent_fwspec)(struct gpio_chip *chip, + struct irq_fwspec *fwspec, + unsigned int parent_hwirq, + unsigned int parent_type); + + /** + * @child_offset_to_irq: + * + * This optional callback is used to translate the child's GPIO line + * offset on the GPIO chip to an IRQ number for the GPIO to_irq() + * callback. If this is not specified, then a default callback will be + * provided that returns the line offset. + */ + unsigned int (*child_offset_to_irq)(struct gpio_chip *chip, + unsigned int pin); + + /** + * @child_irq_domain_ops: + * + * The IRQ domain operations that will be used for this GPIO IRQ + * chip. If no operations are provided, then default callbacks will + * be populated to setup the IRQ hierarchy. Some drivers need to + * supply their own translate function. + */ + struct irq_domain_ops child_irq_domain_ops; +#endif + /** * @handler: * @@ -449,6 +530,36 @@ struct bgpio_pdata { int ngpio; }; +#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY + +void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, + struct irq_fwspec *fwspec, + unsigned int parent_hwirq, + unsigned int parent_type); +void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, + struct irq_fwspec *fwspec, + unsigned int parent_hwirq, + unsigned int parent_type); + +#else + +static void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, + struct irq_fwspec *fwspec, + unsigned int parent_hwirq, + unsigned int parent_type) +{ +} + +static void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, + struct irq_fwspec *fwspec, + unsigned int parent_hwirq, + unsigned int parent_type) +{ +} + +#endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */ + + #if IS_ENABLED(CONFIG_GPIO_GENERIC) int bgpio_init(struct gpio_chip *gc, struct device *dev, From aa7d618ac65fb10697972549efc38d606595afc7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 8 Aug 2019 14:32:38 +0200 Subject: [PATCH 36/82] gpio: ixp4xx: Convert to hierarchical GPIOLIB_IRQCHIP This modifies the IXP4xx driver to use the new helpers to handle the remapping of parent to child hardware irqs in the gpiolib core. This pulls the majority of the code out of the driver and use the generic code in gpiolib. Cc: Thomas Gleixner Cc: Marc Zyngier Cc: Lina Iyer Cc: Jon Hunter Cc: Sowjanya Komatineni Cc: Bitan Biswas Cc: linux-tegra@vger.kernel.org Cc: Thierry Reding Cc: Brian Masney Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190808123242.5359-2-linus.walleij@linaro.org --- drivers/gpio/Kconfig | 2 +- drivers/gpio/gpio-ixp4xx.c | 277 +++++++++---------------------------- 2 files changed, 63 insertions(+), 216 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index bb13c266c329..b34e9b11a7ef 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -288,7 +288,7 @@ config GPIO_IXP4XX depends on ARM # For depends on ARCH_IXP4XX select GPIO_GENERIC - select IRQ_DOMAIN + select GPIOLIB_IRQCHIP select IRQ_DOMAIN_HIERARCHY help Say yes here to support the GPIO functionality of a number of Intel diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c index 670c2a85a35b..8bd23e80c61f 100644 --- a/drivers/gpio/gpio-ixp4xx.c +++ b/drivers/gpio/gpio-ixp4xx.c @@ -47,7 +47,6 @@ * @dev: containing device for this instance * @fwnode: the fwnode for this GPIO chip * @gc: gpiochip for this instance - * @domain: irqdomain for this chip instance * @base: remapped I/O-memory base * @irq_edge: Each bit represents an IRQ: 1: edge-triggered, * 0: level triggered @@ -56,48 +55,22 @@ struct ixp4xx_gpio { struct device *dev; struct fwnode_handle *fwnode; struct gpio_chip gc; - struct irq_domain *domain; void __iomem *base; unsigned long long irq_edge; }; -/** - * struct ixp4xx_gpio_map - IXP4 GPIO to parent IRQ map - * @gpio_offset: offset of the IXP4 GPIO line - * @parent_hwirq: hwirq on the parent IRQ controller - */ -struct ixp4xx_gpio_map { - int gpio_offset; - int parent_hwirq; -}; - -/* GPIO lines 0..12 have corresponding IRQs, GPIOs 13..15 have no IRQs */ -const struct ixp4xx_gpio_map ixp4xx_gpiomap[] = { - { .gpio_offset = 0, .parent_hwirq = 6 }, - { .gpio_offset = 1, .parent_hwirq = 7 }, - { .gpio_offset = 2, .parent_hwirq = 19 }, - { .gpio_offset = 3, .parent_hwirq = 20 }, - { .gpio_offset = 4, .parent_hwirq = 21 }, - { .gpio_offset = 5, .parent_hwirq = 22 }, - { .gpio_offset = 6, .parent_hwirq = 23 }, - { .gpio_offset = 7, .parent_hwirq = 24 }, - { .gpio_offset = 8, .parent_hwirq = 25 }, - { .gpio_offset = 9, .parent_hwirq = 26 }, - { .gpio_offset = 10, .parent_hwirq = 27 }, - { .gpio_offset = 11, .parent_hwirq = 28 }, - { .gpio_offset = 12, .parent_hwirq = 29 }, -}; - static void ixp4xx_gpio_irq_ack(struct irq_data *d) { - struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct ixp4xx_gpio *g = gpiochip_get_data(gc); __raw_writel(BIT(d->hwirq), g->base + IXP4XX_REG_GPIS); } static void ixp4xx_gpio_irq_unmask(struct irq_data *d) { - struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct ixp4xx_gpio *g = gpiochip_get_data(gc); /* ACK when unmasking if not edge-triggered */ if (!(g->irq_edge & BIT(d->hwirq))) @@ -108,7 +81,8 @@ static void ixp4xx_gpio_irq_unmask(struct irq_data *d) static int ixp4xx_gpio_irq_set_type(struct irq_data *d, unsigned int type) { - struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct ixp4xx_gpio *g = gpiochip_get_data(gc); int line = d->hwirq; unsigned long flags; u32 int_style; @@ -187,122 +161,31 @@ static struct irq_chip ixp4xx_gpio_irqchip = { .irq_set_type = ixp4xx_gpio_irq_set_type, }; -static int ixp4xx_gpio_to_irq(struct gpio_chip *gc, unsigned int offset) +static int ixp4xx_gpio_child_to_parent_hwirq(struct gpio_chip *gc, + unsigned int child, + unsigned int child_type, + unsigned int *parent, + unsigned int *parent_type) { - struct ixp4xx_gpio *g = gpiochip_get_data(gc); - struct irq_fwspec fwspec; + /* All these interrupts are level high in the CPU */ + *parent_type = IRQ_TYPE_LEVEL_HIGH; - fwspec.fwnode = g->fwnode; - fwspec.param_count = 2; - fwspec.param[0] = offset; - fwspec.param[1] = IRQ_TYPE_NONE; - - return irq_create_fwspec_mapping(&fwspec); -} - -static int ixp4xx_gpio_irq_domain_translate(struct irq_domain *domain, - struct irq_fwspec *fwspec, - unsigned long *hwirq, - unsigned int *type) -{ - int ret; - - /* We support standard DT translation */ - if (is_of_node(fwspec->fwnode) && fwspec->param_count == 2) { - return irq_domain_translate_twocell(domain, fwspec, - hwirq, type); + /* GPIO lines 0..12 have dedicated IRQs */ + if (child == 0) { + *parent = 6; + return 0; } - - /* This goes away when we transition to DT */ - if (is_fwnode_irqchip(fwspec->fwnode)) { - ret = irq_domain_translate_twocell(domain, fwspec, - hwirq, type); - if (ret) - return ret; - WARN_ON(*type == IRQ_TYPE_NONE); + if (child == 1) { + *parent = 7; + return 0; + } + if (child >= 2 && child <= 12) { + *parent = child + 17; return 0; } return -EINVAL; } -static int ixp4xx_gpio_irq_domain_alloc(struct irq_domain *d, - unsigned int irq, unsigned int nr_irqs, - void *data) -{ - struct ixp4xx_gpio *g = d->host_data; - irq_hw_number_t hwirq; - unsigned int type = IRQ_TYPE_NONE; - struct irq_fwspec *fwspec = data; - int ret; - int i; - - ret = ixp4xx_gpio_irq_domain_translate(d, fwspec, &hwirq, &type); - if (ret) - return ret; - - dev_dbg(g->dev, "allocate IRQ %d..%d, hwirq %lu..%lu\n", - irq, irq + nr_irqs - 1, - hwirq, hwirq + nr_irqs - 1); - - for (i = 0; i < nr_irqs; i++) { - struct irq_fwspec parent_fwspec; - const struct ixp4xx_gpio_map *map; - int j; - - /* Not all lines support IRQs */ - for (j = 0; j < ARRAY_SIZE(ixp4xx_gpiomap); j++) { - map = &ixp4xx_gpiomap[j]; - if (map->gpio_offset == hwirq) - break; - } - if (j == ARRAY_SIZE(ixp4xx_gpiomap)) { - dev_err(g->dev, "can't look up hwirq %lu\n", hwirq); - return -EINVAL; - } - dev_dbg(g->dev, "found parent hwirq %u\n", map->parent_hwirq); - - /* - * We set handle_bad_irq because the .set_type() should - * always be invoked and set the right type of handler. - */ - irq_domain_set_info(d, - irq + i, - hwirq + i, - &ixp4xx_gpio_irqchip, - g, - handle_bad_irq, - NULL, NULL); - irq_set_probe(irq + i); - - /* - * Create a IRQ fwspec to send up to the parent irqdomain: - * specify the hwirq we address on the parent and tie it - * all together up the chain. - */ - parent_fwspec.fwnode = d->parent->fwnode; - parent_fwspec.param_count = 2; - parent_fwspec.param[0] = map->parent_hwirq; - /* This parent only handles asserted level IRQs */ - parent_fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH; - dev_dbg(g->dev, "alloc_irqs_parent for %d parent hwirq %d\n", - irq + i, map->parent_hwirq); - ret = irq_domain_alloc_irqs_parent(d, irq + i, 1, - &parent_fwspec); - if (ret) - dev_err(g->dev, - "failed to allocate parent hwirq %d for hwirq %lu\n", - map->parent_hwirq, hwirq); - } - - return 0; -} - -static const struct irq_domain_ops ixp4xx_gpio_irqdomain_ops = { - .translate = ixp4xx_gpio_irq_domain_translate, - .alloc = ixp4xx_gpio_irq_domain_alloc, - .free = irq_domain_free_irqs_common, -}; - static int ixp4xx_gpio_probe(struct platform_device *pdev) { unsigned long flags; @@ -311,8 +194,8 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev) struct irq_domain *parent; struct resource *res; struct ixp4xx_gpio *g; + struct gpio_irq_chip *girq; int ret; - int i; g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL); if (!g) @@ -326,6 +209,35 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev) return PTR_ERR(g->base); } + /* + * When we convert to device tree we will simply look up the + * parent irqdomain using irq_find_host(parent) as parent comes + * from IRQCHIP_DECLARE(), then use of_node_to_fwnode() to get + * the fwnode. For now we need this boardfile style code. + */ + if (np) { + struct device_node *irq_parent; + + irq_parent = of_irq_find_parent(np); + if (!irq_parent) { + dev_err(dev, "no IRQ parent node\n"); + return -ENODEV; + } + parent = irq_find_host(irq_parent); + if (!parent) { + dev_err(dev, "no IRQ parent domain\n"); + return -ENODEV; + } + g->fwnode = of_node_to_fwnode(np); + } else { + parent = ixp4xx_get_irq_domain(); + g->fwnode = irq_domain_alloc_fwnode(g->base); + if (!g->fwnode) { + dev_err(dev, "no domain base\n"); + return -ENODEV; + } + } + /* * Make sure GPIO 14 and 15 are NOT used as clocks but GPIO on * specific machines. @@ -360,7 +272,6 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev) dev_err(dev, "unable to init generic GPIO\n"); return ret; } - g->gc.to_irq = ixp4xx_gpio_to_irq; g->gc.ngpio = 16; g->gc.label = "IXP4XX_GPIO_CHIP"; /* @@ -372,86 +283,22 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev) g->gc.parent = &pdev->dev; g->gc.owner = THIS_MODULE; + girq = &g->gc.irq; + girq->chip = &ixp4xx_gpio_irqchip; + girq->fwnode = g->fwnode; + girq->parent_domain = parent; + girq->child_to_parent_hwirq = ixp4xx_gpio_child_to_parent_hwirq; + girq->handler = handle_bad_irq; + girq->default_type = IRQ_TYPE_NONE; + ret = devm_gpiochip_add_data(dev, &g->gc, g); if (ret) { dev_err(dev, "failed to add SoC gpiochip\n"); return ret; } - /* - * When we convert to device tree we will simply look up the - * parent irqdomain using irq_find_host(parent) as parent comes - * from IRQCHIP_DECLARE(), then use of_node_to_fwnode() to get - * the fwnode. For now we need this boardfile style code. - */ - if (np) { - struct device_node *irq_parent; - - irq_parent = of_irq_find_parent(np); - if (!irq_parent) { - dev_err(dev, "no IRQ parent node\n"); - return -ENODEV; - } - parent = irq_find_host(irq_parent); - if (!parent) { - dev_err(dev, "no IRQ parent domain\n"); - return -ENODEV; - } - g->fwnode = of_node_to_fwnode(np); - } else { - parent = ixp4xx_get_irq_domain(); - g->fwnode = irq_domain_alloc_fwnode(g->base); - if (!g->fwnode) { - dev_err(dev, "no domain base\n"); - return -ENODEV; - } - } - g->domain = irq_domain_create_hierarchy(parent, - IRQ_DOMAIN_FLAG_HIERARCHY, - ARRAY_SIZE(ixp4xx_gpiomap), - g->fwnode, - &ixp4xx_gpio_irqdomain_ops, - g); - if (!g->domain) { - irq_domain_free_fwnode(g->fwnode); - dev_err(dev, "no hierarchical irq domain\n"); - return ret; - } - - /* - * After adding OF support, this is no longer needed: irqs - * will be allocated for the respective fwnodes. - */ - if (!np) { - for (i = 0; i < ARRAY_SIZE(ixp4xx_gpiomap); i++) { - const struct ixp4xx_gpio_map *map = &ixp4xx_gpiomap[i]; - struct irq_fwspec fwspec; - - fwspec.fwnode = g->fwnode; - /* This is the hwirq for the GPIO line side of things */ - fwspec.param[0] = map->gpio_offset; - fwspec.param[1] = IRQ_TYPE_EDGE_RISING; - fwspec.param_count = 2; - ret = __irq_domain_alloc_irqs(g->domain, - -1, /* just pick something */ - 1, - NUMA_NO_NODE, - &fwspec, - false, - NULL); - if (ret < 0) { - irq_domain_free_fwnode(g->fwnode); - dev_err(dev, - "can not allocate irq for GPIO line %d parent hwirq %d in hierarchy domain: %d\n", - map->gpio_offset, map->parent_hwirq, - ret); - return ret; - } - } - } - platform_set_drvdata(pdev, g); - dev_info(dev, "IXP4 GPIO @%p registered\n", g->base); + dev_info(dev, "IXP4 GPIO registered\n"); return 0; } From 821c76c4c374adf0c7a7608ee4661aa801f3c1c5 Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 8 Aug 2019 14:32:39 +0200 Subject: [PATCH 37/82] qcom: spmi-gpio: convert to hierarchical IRQ helpers in gpio core Now that the GPIO core has support for hierarchical IRQ chips, convert Qualcomm's spmi-gpio over to use these new helpers to reduce duplicated code across drivers. This change was tested on a LG Nexus 5 (hammerhead) phone. Signed-off-by: Brian Masney Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190808123242.5359-3-linus.walleij@linaro.org --- drivers/pinctrl/qcom/Kconfig | 1 + drivers/pinctrl/qcom/pinctrl-spmi-gpio.c | 94 +++++++----------------- 2 files changed, 27 insertions(+), 68 deletions(-) diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index 8e14a5f2e970..fa2c87821401 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -138,6 +138,7 @@ config PINCTRL_QCOM_SPMI_PMIC select PINMUX select PINCONF select GENERIC_PINCONF + select GPIOLIB_IRQCHIP select IRQ_DOMAIN_HIERARCHY help This is the pinctrl, pinmux, pinconf and gpiolib driver for the diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c index f39da87ea185..442db15e0729 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c @@ -170,8 +170,6 @@ struct pmic_gpio_state { struct regmap *map; struct pinctrl_dev *ctrl; struct gpio_chip chip; - struct fwnode_handle *fwnode; - struct irq_domain *domain; }; static const struct pinconf_generic_params pmic_gpio_bindings[] = { @@ -751,23 +749,6 @@ static int pmic_gpio_of_xlate(struct gpio_chip *chip, return gpio_desc->args[0] - PMIC_GPIO_PHYSICAL_OFFSET; } -static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned pin) -{ - struct pmic_gpio_state *state = gpiochip_get_data(chip); - struct irq_fwspec fwspec; - - fwspec.fwnode = state->fwnode; - fwspec.param_count = 2; - fwspec.param[0] = pin + PMIC_GPIO_PHYSICAL_OFFSET; - /* - * Set the type to a safe value temporarily. This will be overwritten - * later with the proper value by irq_set_type. - */ - fwspec.param[1] = IRQ_TYPE_EDGE_RISING; - - return irq_create_fwspec_mapping(&fwspec); -} - static void pmic_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) { struct pmic_gpio_state *state = gpiochip_get_data(chip); @@ -787,7 +768,6 @@ static const struct gpio_chip pmic_gpio_gpio_template = { .request = gpiochip_generic_request, .free = gpiochip_generic_free, .of_xlate = pmic_gpio_of_xlate, - .to_irq = pmic_gpio_to_irq, .dbg_show = pmic_gpio_dbg_show, }; @@ -964,45 +944,23 @@ static int pmic_gpio_domain_translate(struct irq_domain *domain, return 0; } -static int pmic_gpio_domain_alloc(struct irq_domain *domain, unsigned int virq, - unsigned int nr_irqs, void *data) +static unsigned int pmic_gpio_child_offset_to_irq(struct gpio_chip *chip, + unsigned int offset) { - struct pmic_gpio_state *state = container_of(domain->host_data, - struct pmic_gpio_state, - chip); - struct irq_fwspec *fwspec = data; - struct irq_fwspec parent_fwspec; - irq_hw_number_t hwirq; - unsigned int type; - int ret, i; - - ret = pmic_gpio_domain_translate(domain, fwspec, &hwirq, &type); - if (ret) - return ret; - - for (i = 0; i < nr_irqs; i++) - irq_domain_set_info(domain, virq + i, hwirq + i, - &pmic_gpio_irq_chip, state, - handle_level_irq, NULL, NULL); - - parent_fwspec.fwnode = domain->parent->fwnode; - parent_fwspec.param_count = 4; - parent_fwspec.param[0] = 0; - parent_fwspec.param[1] = hwirq + 0xc0; - parent_fwspec.param[2] = 0; - parent_fwspec.param[3] = fwspec->param[1]; - - return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, - &parent_fwspec); + return offset + PMIC_GPIO_PHYSICAL_OFFSET; } -static const struct irq_domain_ops pmic_gpio_domain_ops = { - .activate = gpiochip_irq_domain_activate, - .alloc = pmic_gpio_domain_alloc, - .deactivate = gpiochip_irq_domain_deactivate, - .free = irq_domain_free_irqs_common, - .translate = pmic_gpio_domain_translate, -}; +static int pmic_gpio_child_to_parent_hwirq(struct gpio_chip *chip, + unsigned int child_hwirq, + unsigned int child_type, + unsigned int *parent_hwirq, + unsigned int *parent_type) +{ + *parent_hwirq = child_hwirq + 0xc0; + *parent_type = child_type; + + return 0; +} static int pmic_gpio_probe(struct platform_device *pdev) { @@ -1013,6 +971,7 @@ static int pmic_gpio_probe(struct platform_device *pdev) struct pinctrl_desc *pctrldesc; struct pmic_gpio_pad *pad, *pads; struct pmic_gpio_state *state; + struct gpio_irq_chip *girq; int ret, npins, i; u32 reg; @@ -1092,19 +1051,21 @@ static int pmic_gpio_probe(struct platform_device *pdev) if (!parent_domain) return -ENXIO; - state->fwnode = of_node_to_fwnode(state->dev->of_node); - state->domain = irq_domain_create_hierarchy(parent_domain, 0, - state->chip.ngpio, - state->fwnode, - &pmic_gpio_domain_ops, - &state->chip); - if (!state->domain) - return -ENODEV; + girq = &state->chip.irq; + girq->chip = &pmic_gpio_irq_chip; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_level_irq; + girq->fwnode = of_node_to_fwnode(state->dev->of_node); + girq->parent_domain = parent_domain; + girq->child_to_parent_hwirq = pmic_gpio_child_to_parent_hwirq; + girq->populate_parent_fwspec = gpiochip_populate_parent_fwspec_fourcell; + girq->child_offset_to_irq = pmic_gpio_child_offset_to_irq; + girq->child_irq_domain_ops.translate = pmic_gpio_domain_translate; ret = gpiochip_add_data(&state->chip, state); if (ret) { dev_err(state->dev, "can't add gpio chip\n"); - goto err_chip_add_data; + return ret; } /* @@ -1130,8 +1091,6 @@ static int pmic_gpio_probe(struct platform_device *pdev) err_range: gpiochip_remove(&state->chip); -err_chip_add_data: - irq_domain_remove(state->domain); return ret; } @@ -1140,7 +1099,6 @@ static int pmic_gpio_remove(struct platform_device *pdev) struct pmic_gpio_state *state = platform_get_drvdata(pdev); gpiochip_remove(&state->chip); - irq_domain_remove(state->domain); return 0; } From a7fc89f9d5fcc10a5474cfe555f5a9e5df8b0f1f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 8 Aug 2019 14:32:40 +0200 Subject: [PATCH 38/82] gpio: thunderx: Switch to GPIOLIB_IRQCHIP Use the new infrastructure for hierarchical irqchips in gpiolib. The major part of the rewrite was dues to the fact that the driver was passing around a per-irq pointer to struct thunderx_line * data container, and the central handlers will assume struct gpio_chip * to be passed to we need to use the hwirq as index to look up the struct thunderx_line * for each IRQ. The pushing and pop:ing of the irqdomain was confusing because I've never seen this before, but I tried to replicate it as best I could. I have no chance to test or debug this so I need help. Cc: David Daney Cc: Thierry Reding Cc: Brian Masney Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190808123242.5359-4-linus.walleij@linaro.org --- drivers/gpio/Kconfig | 1 + drivers/gpio/gpio-thunderx.c | 161 ++++++++++++----------------------- 2 files changed, 56 insertions(+), 106 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b34e9b11a7ef..3125aca2db9f 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -539,6 +539,7 @@ config GPIO_THUNDERX tristate "Cavium ThunderX/OCTEON-TX GPIO" depends on ARCH_THUNDER || (64BIT && COMPILE_TEST) depends on PCI_MSI + select GPIOLIB_IRQCHIP select IRQ_DOMAIN_HIERARCHY select IRQ_FASTEOI_HIERARCHY_HANDLERS help diff --git a/drivers/gpio/gpio-thunderx.c b/drivers/gpio/gpio-thunderx.c index 715371b5102a..ddad5c7ea617 100644 --- a/drivers/gpio/gpio-thunderx.c +++ b/drivers/gpio/gpio-thunderx.c @@ -53,7 +53,6 @@ struct thunderx_line { struct thunderx_gpio { struct gpio_chip chip; u8 __iomem *register_base; - struct irq_domain *irqd; struct msix_entry *msix_entries; /* per line MSI-X */ struct thunderx_line *line_entries; /* per line irq info */ raw_spinlock_t lock; @@ -283,54 +282,60 @@ static void thunderx_gpio_set_multiple(struct gpio_chip *chip, } } -static void thunderx_gpio_irq_ack(struct irq_data *data) +static void thunderx_gpio_irq_ack(struct irq_data *d) { - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct thunderx_gpio *txgpio = gpiochip_get_data(gc); writeq(GPIO_INTR_INTR, - txline->txgpio->register_base + intr_reg(txline->line)); + txgpio->register_base + intr_reg(irqd_to_hwirq(d))); } -static void thunderx_gpio_irq_mask(struct irq_data *data) +static void thunderx_gpio_irq_mask(struct irq_data *d) { - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct thunderx_gpio *txgpio = gpiochip_get_data(gc); writeq(GPIO_INTR_ENA_W1C, - txline->txgpio->register_base + intr_reg(txline->line)); + txgpio->register_base + intr_reg(irqd_to_hwirq(d))); } -static void thunderx_gpio_irq_mask_ack(struct irq_data *data) +static void thunderx_gpio_irq_mask_ack(struct irq_data *d) { - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct thunderx_gpio *txgpio = gpiochip_get_data(gc); writeq(GPIO_INTR_ENA_W1C | GPIO_INTR_INTR, - txline->txgpio->register_base + intr_reg(txline->line)); + txgpio->register_base + intr_reg(irqd_to_hwirq(d))); } -static void thunderx_gpio_irq_unmask(struct irq_data *data) +static void thunderx_gpio_irq_unmask(struct irq_data *d) { - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct thunderx_gpio *txgpio = gpiochip_get_data(gc); writeq(GPIO_INTR_ENA_W1S, - txline->txgpio->register_base + intr_reg(txline->line)); + txgpio->register_base + intr_reg(irqd_to_hwirq(d))); } -static int thunderx_gpio_irq_set_type(struct irq_data *data, +static int thunderx_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type) { - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); - struct thunderx_gpio *txgpio = txline->txgpio; + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct thunderx_gpio *txgpio = gpiochip_get_data(gc); + struct thunderx_line *txline = + &txgpio->line_entries[irqd_to_hwirq(d)]; u64 bit_cfg; - irqd_set_trigger_type(data, flow_type); + irqd_set_trigger_type(d, flow_type); bit_cfg = txline->fil_bits | GPIO_BIT_CFG_INT_EN; if (flow_type & IRQ_TYPE_EDGE_BOTH) { - irq_set_handler_locked(data, handle_fasteoi_ack_irq); + irq_set_handler_locked(d, handle_fasteoi_ack_irq); bit_cfg |= GPIO_BIT_CFG_INT_TYPE; } else { - irq_set_handler_locked(data, handle_fasteoi_mask_irq); + irq_set_handler_locked(d, handle_fasteoi_mask_irq); } raw_spin_lock(&txgpio->lock); @@ -359,33 +364,6 @@ static void thunderx_gpio_irq_disable(struct irq_data *data) irq_chip_disable_parent(data); } -static int thunderx_gpio_irq_request_resources(struct irq_data *data) -{ - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); - struct thunderx_gpio *txgpio = txline->txgpio; - int r; - - r = gpiochip_lock_as_irq(&txgpio->chip, txline->line); - if (r) - return r; - - r = irq_chip_request_resources_parent(data); - if (r) - gpiochip_unlock_as_irq(&txgpio->chip, txline->line); - - return r; -} - -static void thunderx_gpio_irq_release_resources(struct irq_data *data) -{ - struct thunderx_line *txline = irq_data_get_irq_chip_data(data); - struct thunderx_gpio *txgpio = txline->txgpio; - - irq_chip_release_resources_parent(data); - - gpiochip_unlock_as_irq(&txgpio->chip, txline->line); -} - /* * Interrupts are chained from underlying MSI-X vectors. We have * these irq_chip functions to be able to handle level triggering @@ -402,50 +380,24 @@ static struct irq_chip thunderx_gpio_irq_chip = { .irq_unmask = thunderx_gpio_irq_unmask, .irq_eoi = irq_chip_eoi_parent, .irq_set_affinity = irq_chip_set_affinity_parent, - .irq_request_resources = thunderx_gpio_irq_request_resources, - .irq_release_resources = thunderx_gpio_irq_release_resources, .irq_set_type = thunderx_gpio_irq_set_type, .flags = IRQCHIP_SET_TYPE_MASKED }; -static int thunderx_gpio_irq_translate(struct irq_domain *d, - struct irq_fwspec *fwspec, - irq_hw_number_t *hwirq, - unsigned int *type) +static int thunderx_gpio_child_to_parent_hwirq(struct gpio_chip *gc, + unsigned int child, + unsigned int child_type, + unsigned int *parent, + unsigned int *parent_type) { - struct thunderx_gpio *txgpio = d->host_data; + struct thunderx_gpio *txgpio = gpiochip_get_data(gc); - if (WARN_ON(fwspec->param_count < 2)) - return -EINVAL; - if (fwspec->param[0] >= txgpio->chip.ngpio) - return -EINVAL; - *hwirq = fwspec->param[0]; - *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; + *parent = txgpio->base_msi + (2 * child); + *parent_type = IRQ_TYPE_LEVEL_HIGH; return 0; } -static int thunderx_gpio_irq_alloc(struct irq_domain *d, unsigned int virq, - unsigned int nr_irqs, void *arg) -{ - struct thunderx_line *txline = arg; - - return irq_domain_set_hwirq_and_chip(d, virq, txline->line, - &thunderx_gpio_irq_chip, txline); -} - -static const struct irq_domain_ops thunderx_gpio_irqd_ops = { - .alloc = thunderx_gpio_irq_alloc, - .translate = thunderx_gpio_irq_translate -}; - -static int thunderx_gpio_to_irq(struct gpio_chip *chip, unsigned int offset) -{ - struct thunderx_gpio *txgpio = gpiochip_get_data(chip); - - return irq_find_mapping(txgpio->irqd, offset); -} - static int thunderx_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -453,6 +405,7 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, struct device *dev = &pdev->dev; struct thunderx_gpio *txgpio; struct gpio_chip *chip; + struct gpio_irq_chip *girq; int ngpio, i; int err = 0; @@ -497,8 +450,8 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, } txgpio->msix_entries = devm_kcalloc(dev, - ngpio, sizeof(struct msix_entry), - GFP_KERNEL); + ngpio, sizeof(struct msix_entry), + GFP_KERNEL); if (!txgpio->msix_entries) { err = -ENOMEM; goto out; @@ -539,27 +492,6 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, if (err < 0) goto out; - /* - * Push GPIO specific irqdomain on hierarchy created as a side - * effect of the pci_enable_msix() - */ - txgpio->irqd = irq_domain_create_hierarchy(irq_get_irq_data(txgpio->msix_entries[0].vector)->domain, - 0, 0, of_node_to_fwnode(dev->of_node), - &thunderx_gpio_irqd_ops, txgpio); - if (!txgpio->irqd) { - err = -ENOMEM; - goto out; - } - - /* Push on irq_data and the domain for each line. */ - for (i = 0; i < ngpio; i++) { - err = irq_domain_push_irq(txgpio->irqd, - txgpio->msix_entries[i].vector, - &txgpio->line_entries[i]); - if (err < 0) - dev_err(dev, "irq_domain_push_irq: %d\n", err); - } - chip->label = KBUILD_MODNAME; chip->parent = dev; chip->owner = THIS_MODULE; @@ -574,11 +506,28 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, chip->set = thunderx_gpio_set; chip->set_multiple = thunderx_gpio_set_multiple; chip->set_config = thunderx_gpio_set_config; - chip->to_irq = thunderx_gpio_to_irq; + girq = &chip->irq; + girq->chip = &thunderx_gpio_irq_chip; + girq->fwnode = of_node_to_fwnode(dev->of_node); + girq->parent_domain = + irq_get_irq_data(txgpio->msix_entries[0].vector)->domain; + girq->child_to_parent_hwirq = thunderx_gpio_child_to_parent_hwirq; + girq->handler = handle_bad_irq; + girq->default_type = IRQ_TYPE_NONE; + err = devm_gpiochip_add_data(dev, chip, txgpio); if (err) goto out; + /* Push on irq_data and the domain for each line. */ + for (i = 0; i < ngpio; i++) { + err = irq_domain_push_irq(chip->irq.domain, + txgpio->msix_entries[i].vector, + chip); + if (err < 0) + dev_err(dev, "irq_domain_push_irq: %d\n", err); + } + dev_info(dev, "ThunderX GPIO: %d lines with base %d.\n", ngpio, chip->base); return 0; @@ -593,10 +542,10 @@ static void thunderx_gpio_remove(struct pci_dev *pdev) struct thunderx_gpio *txgpio = pci_get_drvdata(pdev); for (i = 0; i < txgpio->chip.ngpio; i++) - irq_domain_pop_irq(txgpio->irqd, + irq_domain_pop_irq(txgpio->chip.irq.domain, txgpio->msix_entries[i].vector); - irq_domain_remove(txgpio->irqd); + irq_domain_remove(txgpio->chip.irq.domain); pci_set_drvdata(pdev, NULL); } From 607a0dcddbdc5b147c595f6544e97bd8d9491c14 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 9 Aug 2019 15:18:04 +0200 Subject: [PATCH 39/82] gpio: cadence: Pass irqchip when adding gpiochip We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. Cc: Jan Kotas Cc: Thierry Reding Signed-off-by: Linus Walleij Tested-by: Jan Kotas Link: https://lore.kernel.org/r/20190809131804.20352-1-linus.walleij@linaro.org --- drivers/gpio/gpio-cadence.c | 40 +++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpio-cadence.c b/drivers/gpio/gpio-cadence.c index 712ae212b0b4..a4d3239d2594 100644 --- a/drivers/gpio/gpio-cadence.c +++ b/drivers/gpio/gpio-cadence.c @@ -214,29 +214,35 @@ static int cdns_gpio_probe(struct platform_device *pdev) goto err_revert_dir; } + /* + * Optional irq_chip support + */ + irq = platform_get_irq(pdev, 0); + if (irq >= 0) { + struct gpio_irq_chip *girq; + + girq = &cgpio->gc.irq; + girq->chip = &cdns_gpio_irqchip; + girq->parent_handler = cdns_gpio_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->dev, 1, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) { + ret = -ENOMEM; + goto err_disable_clk; + } + girq->parents[0] = irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_level_irq; + } + ret = devm_gpiochip_add_data(&pdev->dev, &cgpio->gc, cgpio); if (ret < 0) { dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); goto err_disable_clk; } - /* - * irq_chip support - */ - irq = platform_get_irq(pdev, 0); - if (irq >= 0) { - ret = gpiochip_irqchip_add(&cgpio->gc, &cdns_gpio_irqchip, - 0, handle_level_irq, - IRQ_TYPE_NONE); - if (ret) { - dev_err(&pdev->dev, "Could not add irqchip, %d\n", - ret); - goto err_disable_clk; - } - gpiochip_set_chained_irqchip(&cgpio->gc, &cdns_gpio_irqchip, - irq, cdns_gpio_irq_handler); - } - cgpio->bypass_orig = ioread32(cgpio->regs + CDNS_GPIO_BYPASS_MODE); /* From fe8cf20d29309f552c8d9afb3e350e4df2e75150 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Fri, 9 Aug 2019 13:59:42 +0530 Subject: [PATCH 40/82] dt-bindings: gpio: davinci: Add new compatible for J721E SoCs J721e SoCs have same gpio IP as K2G davinci gpio. Add a new compatible to handle J721E SoCs. Signed-off-by: Lokesh Vutla Link: https://lore.kernel.org/r/20190809082947.30590-2-lokeshvutla@ti.com Reviewed-by: Keerthy Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/gpio/gpio-davinci.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/gpio/gpio-davinci.txt b/Documentation/devicetree/bindings/gpio/gpio-davinci.txt index bc6b4b62df83..cd91d61eac31 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-davinci.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-davinci.txt @@ -6,6 +6,7 @@ Required Properties: 66AK2E SoCs "ti,k2g-gpio", "ti,keystone-gpio": for 66AK2G "ti,am654-gpio", "ti,keystone-gpio": for TI K3 AM654 + "ti,j721e-gpio", "ti,keystone-gpio": for J721E SoCs - reg: Physical base address of the controller and the size of memory mapped registers. From c7e66e48c05ac2de729999148daa56b563c30b2f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 9 Aug 2019 15:51:19 +0200 Subject: [PATCH 41/82] gpio: xlp: Pass irqchip when adding gpiochip We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. Cc: Jayachandran C Cc: Kamlakant Patel Cc: Thierry Reding Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190809135119.6946-1-linus.walleij@linaro.org Signed-off-by: Linus Walleij --- drivers/gpio/gpio-xlp.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/gpio-xlp.c b/drivers/gpio/gpio-xlp.c index 54d3359444f3..d7b16bb9e4e4 100644 --- a/drivers/gpio/gpio-xlp.c +++ b/drivers/gpio/gpio-xlp.c @@ -290,6 +290,7 @@ MODULE_DEVICE_TABLE(of, xlp_gpio_of_ids); static int xlp_gpio_probe(struct platform_device *pdev) { struct gpio_chip *gc; + struct gpio_irq_chip *girq; struct xlp_gpio_priv *priv; void __iomem *gpio_base; int irq_base, irq, err; @@ -395,27 +396,27 @@ static int xlp_gpio_probe(struct platform_device *pdev) irq_base = 0; } + girq = &gc->irq; + girq->chip = &xlp_gpio_irq_chip; + girq->parent_handler = xlp_gpio_generic_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->dev, 1, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = irq; + girq->first = irq_base; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_level_irq; + err = gpiochip_add_data(gc, priv); if (err < 0) return err; - err = gpiochip_irqchip_add(gc, &xlp_gpio_irq_chip, irq_base, - handle_level_irq, IRQ_TYPE_NONE); - if (err) { - dev_err(&pdev->dev, "Could not connect irqchip to gpiochip!\n"); - goto out_gpio_remove; - } - - gpiochip_set_chained_irqchip(gc, &xlp_gpio_irq_chip, irq, - xlp_gpio_generic_handler); - dev_info(&pdev->dev, "registered %d GPIOs\n", gc->ngpio); return 0; - -out_gpio_remove: - gpiochip_remove(gc); - return err; } #ifdef CONFIG_ACPI From a2ac3eb3656dd248f4e2b30a44a8ae622063d832 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 9 Aug 2019 16:00:05 +0200 Subject: [PATCH 42/82] gpio: hlwd: Pass irqchip when adding gpiochip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. Cc: Thierry Reding Link: https://lore.kernel.org/r/20190809140005.11654-1-linus.walleij@linaro.org Reviewed-by: Jonathan Neuschäfer Tested-by: Jonathan Neuschäfer Signed-off-by: Linus Walleij --- drivers/gpio/gpio-hlwd.c | 56 +++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/drivers/gpio/gpio-hlwd.c b/drivers/gpio/gpio-hlwd.c index e5fa00f8145f..4a17599f6d44 100644 --- a/drivers/gpio/gpio-hlwd.c +++ b/drivers/gpio/gpio-hlwd.c @@ -244,43 +244,45 @@ static int hlwd_gpio_probe(struct platform_device *pdev) ngpios = 32; hlwd->gpioc.ngpio = ngpios; - res = devm_gpiochip_add_data(&pdev->dev, &hlwd->gpioc, hlwd); - if (res) - return res; - /* Mask and ack all interrupts */ iowrite32be(0, hlwd->regs + HW_GPIOB_INTMASK); iowrite32be(0xffffffff, hlwd->regs + HW_GPIOB_INTFLAG); /* * If this GPIO controller is not marked as an interrupt controller in - * the DT, return. + * the DT, skip interrupt support. */ - if (!of_property_read_bool(pdev->dev.of_node, "interrupt-controller")) - return 0; + if (of_property_read_bool(pdev->dev.of_node, "interrupt-controller")) { + struct gpio_irq_chip *girq; - hlwd->irq = platform_get_irq(pdev, 0); - if (hlwd->irq < 0) { - dev_info(&pdev->dev, "platform_get_irq returned %d\n", - hlwd->irq); - return hlwd->irq; + hlwd->irq = platform_get_irq(pdev, 0); + if (hlwd->irq < 0) { + dev_info(&pdev->dev, "platform_get_irq returned %d\n", + hlwd->irq); + return hlwd->irq; + } + + hlwd->irqc.name = dev_name(&pdev->dev); + hlwd->irqc.irq_mask = hlwd_gpio_irq_mask; + hlwd->irqc.irq_unmask = hlwd_gpio_irq_unmask; + hlwd->irqc.irq_enable = hlwd_gpio_irq_enable; + hlwd->irqc.irq_set_type = hlwd_gpio_irq_set_type; + + girq = &hlwd->gpioc.irq; + girq->chip = &hlwd->irqc; + girq->parent_handler = hlwd_gpio_irqhandler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->dev, 1, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = hlwd->irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_level_irq; } - hlwd->irqc.name = dev_name(&pdev->dev); - hlwd->irqc.irq_mask = hlwd_gpio_irq_mask; - hlwd->irqc.irq_unmask = hlwd_gpio_irq_unmask; - hlwd->irqc.irq_enable = hlwd_gpio_irq_enable; - hlwd->irqc.irq_set_type = hlwd_gpio_irq_set_type; - - res = gpiochip_irqchip_add(&hlwd->gpioc, &hlwd->irqc, 0, - handle_level_irq, IRQ_TYPE_NONE); - if (res) - return res; - - gpiochip_set_chained_irqchip(&hlwd->gpioc, &hlwd->irqc, - hlwd->irq, hlwd_gpio_irqhandler); - - return 0; + return devm_gpiochip_add_data(&pdev->dev, &hlwd->gpioc, hlwd); } static const struct of_device_id hlwd_gpio_match[] = { From 8512ee31926296fd7d65c1b3c97bb20d67e7eb2a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 9 Aug 2019 14:55:15 +0200 Subject: [PATCH 43/82] gpio: aspeed: Pass irqchip when adding gpiochip We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. Cc: Joel Stanley Cc: Andrew Jeffery Cc: Benjamin Herrenschmidt Cc: Thierry Reding Link: https://lore.kernel.org/r/20190809125515.19094-1-linus.walleij@linaro.org Reviewed-by: Andrew Jeffery Tested-by: Andrew Jeffery Acked-by: Joel Stanley Signed-off-by: Linus Walleij --- drivers/gpio/gpio-aspeed.c | 60 ++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index 13d80bfbc3b6..9defe25d4721 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -711,32 +711,6 @@ static void set_irq_valid_mask(struct aspeed_gpio *gpio) } } -static int aspeed_gpio_setup_irqs(struct aspeed_gpio *gpio, - struct platform_device *pdev) -{ - int rc; - - rc = platform_get_irq(pdev, 0); - if (rc < 0) - return rc; - - gpio->irq = rc; - - set_irq_valid_mask(gpio); - - rc = gpiochip_irqchip_add(&gpio->chip, &aspeed_gpio_irqchip, - 0, handle_bad_irq, IRQ_TYPE_NONE); - if (rc) { - dev_info(&pdev->dev, "Could not add irqchip\n"); - return rc; - } - - gpiochip_set_chained_irqchip(&gpio->chip, &aspeed_gpio_irqchip, - gpio->irq, aspeed_gpio_irq_handler); - - return 0; -} - static int aspeed_gpio_reset_tolerance(struct gpio_chip *chip, unsigned int offset, bool enable) { @@ -1189,7 +1163,6 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) 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; /* Allocate a cache of the output registers */ banks = gpio->config->nr_gpios >> 5; @@ -1212,16 +1185,41 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) aspeed_gpio_change_cmd_source(gpio, bank, 3, GPIO_CMDSRC_ARM); } - rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); - if (rc < 0) - return rc; + /* Optionally set up an irqchip if there is an IRQ */ + rc = platform_get_irq(pdev, 0); + if (rc > 0) { + struct gpio_irq_chip *girq; + + gpio->irq = rc; + girq = &gpio->chip.irq; + girq->chip = &aspeed_gpio_irqchip; + girq->parent_handler = aspeed_gpio_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->dev, 1, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = gpio->irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + girq->need_valid_mask = true; + } gpio->offset_timer = devm_kzalloc(&pdev->dev, gpio->chip.ngpio, GFP_KERNEL); if (!gpio->offset_timer) return -ENOMEM; - return aspeed_gpio_setup_irqs(gpio, pdev); + rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); + if (rc < 0) + return rc; + + /* Now the valid mask is allocated */ + if (gpio->irq) + set_irq_valid_mask(gpio); + + return 0; } static struct platform_driver aspeed_gpio_driver = { From f3260e3ea1f570cc3c13a65d3e46c86ca581266d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 25 Jul 2019 15:10:02 +0200 Subject: [PATCH 44/82] gpio: mockup: don't depend twice on GPIOLIB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit config GPIO_MOCKUP is defined in a big if GPIOLIB ... endif block so it doesn't need to depend explicitly on GPIOLIB. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20190725131002.14597-1-uwe@kleine-koenig.org Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3125aca2db9f..8137f3e3a108 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1466,7 +1466,6 @@ endmenu config GPIO_MOCKUP tristate "GPIO Testing Driver" - depends on GPIOLIB select IRQ_SIM help This enables GPIO Testing driver, which provides a way to test GPIO From f52a0c7b5eb907a12bc08a33cc998ed02dad3507 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 16 Aug 2019 21:38:12 +1000 Subject: [PATCH 45/82] gpio: stubs in headers should be inline Fixes: fdd61a013a24 ("gpio: Add support for hierarchical IRQ domains") Signed-off-by: Stephen Rothwell Link: https://lore.kernel.org/r/20190816213812.40a130db@canb.auug.org.au Signed-off-by: Linus Walleij --- include/linux/gpio/driver.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 0e6d3b0c0211..72d48a2bab65 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -543,14 +543,14 @@ void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, #else -static void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, +static inline void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, struct irq_fwspec *fwspec, unsigned int parent_hwirq, unsigned int parent_type) { } -static void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, +static inline void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, struct irq_fwspec *fwspec, unsigned int parent_hwirq, unsigned int parent_type) From c9fc5aff217267a9ef3a76450760534488870c69 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 19 Aug 2019 10:49:04 +0200 Subject: [PATCH 46/82] gpio: Pass mask and size with the init_valid_mask() It is more helpful for drivers to have the affected fields directly available when we use the callback to set up the valid mask. Change this and switch over the only user (MSM) to use the passed parameters. If we do this we can also move the mask out of publicly visible struct fields. Cc: Stephen Boyd Cc: Bjorn Andersson Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190819084904.30027-1-linus.walleij@linaro.or Reviewed-by: Stephen Boyd Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 8 +++++--- drivers/pinctrl/qcom/pinctrl-msm.c | 19 ++++++++++--------- include/linux/gpio/driver.h | 4 +++- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5277b8f1ff7c..22b87c6e8cd5 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -375,10 +375,12 @@ static int gpiochip_alloc_valid_mask(struct gpio_chip *gc) return 0; } -static int gpiochip_init_valid_mask(struct gpio_chip *gpiochip) +static int gpiochip_init_valid_mask(struct gpio_chip *gc) { - if (gpiochip->init_valid_mask) - return gpiochip->init_valid_mask(gpiochip); + if (gc->init_valid_mask) + return gc->init_valid_mask(gc, + gc->valid_mask, + gc->ngpio); return 0; } diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 7f35c196bb3e..a5d8f75da4a7 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -593,24 +593,25 @@ static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) #define msm_gpio_dbg_show NULL #endif -static int msm_gpio_init_valid_mask(struct gpio_chip *chip) +static int msm_gpio_init_valid_mask(struct gpio_chip *gc, + unsigned long *valid_mask, + unsigned int ngpios) { - struct msm_pinctrl *pctrl = gpiochip_get_data(chip); + struct msm_pinctrl *pctrl = gpiochip_get_data(gc); int ret; unsigned int len, i; - unsigned int max_gpios = pctrl->soc->ngpios; const int *reserved = pctrl->soc->reserved_gpios; u16 *tmp; /* Driver provided reserved list overrides DT and ACPI */ if (reserved) { - bitmap_fill(chip->valid_mask, max_gpios); + bitmap_fill(valid_mask, ngpios); for (i = 0; reserved[i] >= 0; i++) { - if (i >= max_gpios || reserved[i] >= max_gpios) { + if (i >= ngpios || reserved[i] >= ngpios) { dev_err(pctrl->dev, "invalid list of reserved GPIOs\n"); return -EINVAL; } - clear_bit(reserved[i], chip->valid_mask); + clear_bit(reserved[i], valid_mask); } return 0; @@ -622,7 +623,7 @@ static int msm_gpio_init_valid_mask(struct gpio_chip *chip) if (ret < 0) return 0; - if (ret > max_gpios) + if (ret > ngpios) return -EINVAL; tmp = kmalloc_array(len, sizeof(*tmp), GFP_KERNEL); @@ -635,9 +636,9 @@ static int msm_gpio_init_valid_mask(struct gpio_chip *chip) goto out; } - bitmap_zero(chip->valid_mask, max_gpios); + bitmap_zero(valid_mask, ngpios); for (i = 0; i < len; i++) - set_bit(tmp[i], chip->valid_mask); + set_bit(tmp[i], valid_mask); out: kfree(tmp); diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 72d48a2bab65..dc03323897ef 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -363,7 +363,9 @@ struct gpio_chip { void (*dbg_show)(struct seq_file *s, struct gpio_chip *chip); - int (*init_valid_mask)(struct gpio_chip *chip); + int (*init_valid_mask)(struct gpio_chip *chip, + unsigned long *valid_mask, + unsigned int ngpios); int base; u16 ngpio; From da9b142ab2c55ae8c46242a7624fdf62c4089e7f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 19 Aug 2019 11:11:40 +0200 Subject: [PATCH 47/82] pinctrl: stmfx: Use the callback to populate valid_mask This makes use of the existing callback to populate the valid mask instead of iteratively setting it up during probe. Cc: Benjamin Gaignard Cc: Amelie Delaunay Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190819091140.622-1-linus.walleij@linaro.org --- drivers/pinctrl/pinctrl-stmfx.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c index d3332da35637..13b6d6f72bcc 100644 --- a/drivers/pinctrl/pinctrl-stmfx.c +++ b/drivers/pinctrl/pinctrl-stmfx.c @@ -585,12 +585,24 @@ static int stmfx_pinctrl_gpio_function_enable(struct stmfx_pinctrl *pctl) return stmfx_function_enable(pctl->stmfx, func); } +static int stmfx_pinctrl_gpio_init_valid_mask(struct gpio_chip *gc, + unsigned long *valid_mask, + unsigned int ngpios) +{ + struct stmfx_pinctrl *pctl = gpiochip_get_data(gc); + u32 n; + + for_each_clear_bit(n, &pctl->gpio_valid_mask, ngpios) + clear_bit(n, valid_mask); + + return 0; +} + static int stmfx_pinctrl_probe(struct platform_device *pdev) { struct stmfx *stmfx = dev_get_drvdata(pdev->dev.parent); struct device_node *np = pdev->dev.of_node; struct stmfx_pinctrl *pctl; - u32 n; int irq, ret; pctl = devm_kzalloc(stmfx->dev, sizeof(*pctl), GFP_KERNEL); @@ -651,6 +663,7 @@ static int stmfx_pinctrl_probe(struct platform_device *pdev) pctl->gpio_chip.can_sleep = true; pctl->gpio_chip.of_node = np; pctl->gpio_chip.need_valid_mask = true; + pctl->gpio_chip.init_valid_mask = stmfx_pinctrl_gpio_init_valid_mask; ret = devm_gpiochip_add_data(pctl->dev, &pctl->gpio_chip, pctl); if (ret) { @@ -668,8 +681,6 @@ static int stmfx_pinctrl_probe(struct platform_device *pdev) pctl->irq_chip.irq_set_type = stmfx_pinctrl_irq_set_type; pctl->irq_chip.irq_bus_lock = stmfx_pinctrl_irq_bus_lock; pctl->irq_chip.irq_bus_sync_unlock = stmfx_pinctrl_irq_bus_sync_unlock; - for_each_clear_bit(n, &pctl->gpio_valid_mask, pctl->gpio_chip.ngpio) - clear_bit(n, pctl->gpio_chip.valid_mask); ret = gpiochip_irqchip_add_nested(&pctl->gpio_chip, &pctl->irq_chip, 0, handle_bad_irq, IRQ_TYPE_NONE); From eb1e8bd6e3900e3a3b9776cd1b09ecfc05573619 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 19 Aug 2019 11:30:58 +0200 Subject: [PATCH 48/82] gpio: Use callback presence to determine need of valid_mask After we switched the two drivers that have .need_valid_mask set to use the callback for setting up the .valid_mask, we can just use the presence of the .init_valid_mask() callback (or the OF reserved ranges, nota bene) to determine whether to allocate the mask or not and we can drop the .need_valid_mask field altogether. Cc: Benjamin Gaignard Cc: Amelie Delaunay Cc: Stephen Boyd Cc: Bjorn Andersson Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190819093058.10863-1-linus.walleij@linaro.org --- drivers/gpio/gpiolib.c | 4 +--- drivers/pinctrl/pinctrl-stmfx.c | 1 - drivers/pinctrl/qcom/pinctrl-msm.c | 4 ++-- include/linux/gpio/driver.h | 9 --------- 4 files changed, 3 insertions(+), 15 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 22b87c6e8cd5..01aa5440454c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -363,9 +363,7 @@ static unsigned long *gpiochip_allocate_mask(struct gpio_chip *chip) static int gpiochip_alloc_valid_mask(struct gpio_chip *gc) { - if (of_gpio_need_valid_mask(gc)) - gc->need_valid_mask = true; - if (!gc->need_valid_mask) + if (!(of_gpio_need_valid_mask(gc) || gc->init_valid_mask)) return 0; gc->valid_mask = gpiochip_allocate_mask(gc); diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c index 13b6d6f72bcc..dd5aa9a2dfe5 100644 --- a/drivers/pinctrl/pinctrl-stmfx.c +++ b/drivers/pinctrl/pinctrl-stmfx.c @@ -662,7 +662,6 @@ static int stmfx_pinctrl_probe(struct platform_device *pdev) pctl->gpio_chip.ngpio = pctl->pctl_desc.npins; pctl->gpio_chip.can_sleep = true; pctl->gpio_chip.of_node = np; - pctl->gpio_chip.need_valid_mask = true; pctl->gpio_chip.init_valid_mask = stmfx_pinctrl_gpio_init_valid_mask; ret = devm_gpiochip_add_data(pctl->dev, &pctl->gpio_chip, pctl); diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index a5d8f75da4a7..b8a1c43222f8 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -654,7 +654,6 @@ static const struct gpio_chip msm_gpio_template = { .request = gpiochip_generic_request, .free = gpiochip_generic_free, .dbg_show = msm_gpio_dbg_show, - .init_valid_mask = msm_gpio_init_valid_mask, }; /* For dual-edge interrupts in software, since some hardware has no @@ -1016,7 +1015,8 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) chip->parent = pctrl->dev; chip->owner = THIS_MODULE; chip->of_node = pctrl->dev->of_node; - chip->need_valid_mask = msm_gpio_needs_valid_mask(pctrl); + if (msm_gpio_needs_valid_mask(pctrl)) + chip->init_valid_mask = msm_gpio_init_valid_mask; pctrl->irq_chip.name = "msmgpio"; pctrl->irq_chip.irq_enable = msm_gpio_irq_enable; diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index dc03323897ef..340121c7d2fb 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -403,15 +403,6 @@ struct gpio_chip { struct gpio_irq_chip irq; #endif /* CONFIG_GPIOLIB_IRQCHIP */ - /** - * @need_valid_mask: - * - * If set core allocates @valid_mask with all its values initialized - * with init_valid_mask() or set to one if init_valid_mask() is not - * defined - */ - bool need_valid_mask; - /** * @valid_mask: * From a7e42142926f815c776f745d027f69a53415d99c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 19 Aug 2019 10:27:04 +0200 Subject: [PATCH 49/82] gpio: ftgpio: Move hardware initialization It is probably wise to initialize the hardware before registering the irq chip. Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190819082704.14237-1-linus.walleij@linaro.org --- drivers/gpio/gpio-ftgpio010.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-ftgpio010.c b/drivers/gpio/gpio-ftgpio010.c index 250e71f3e688..3118d282514a 100644 --- a/drivers/gpio/gpio-ftgpio010.c +++ b/drivers/gpio/gpio-ftgpio010.c @@ -296,10 +296,6 @@ static int ftgpio_gpio_probe(struct platform_device *pdev) girq->handler = handle_bad_irq; girq->parents[0] = irq; - ret = devm_gpiochip_add_data(dev, &g->gc, g); - if (ret) - goto dis_clk; - /* Disable, unmask and clear all interrupts */ writel(0x0, g->base + GPIO_INT_EN); writel(0x0, g->base + GPIO_INT_MASK); @@ -308,6 +304,10 @@ static int ftgpio_gpio_probe(struct platform_device *pdev) /* Clear any use of debounce */ writel(0x0, g->base + GPIO_DEBOUNCE_EN); + ret = devm_gpiochip_add_data(dev, &g->gc, g); + if (ret) + goto dis_clk; + platform_set_drvdata(pdev, g); dev_info(dev, "FTGPIO010 @%p registered\n", g->base); From ac1213b7d79580ca52d7517e61e1ec4120134f0c Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 31 Jul 2019 16:13:42 +0100 Subject: [PATCH 50/82] gpio/ixp4xx: Register the base PA instead of its VA in fwnode Do not expose the base VA (it appears in debugfs). Instead, record the PA, which at least can be used to precisely identify the associated irqchip and domain. Reviewed-by: Linus Walleij Acked-by: Thomas Gleixner Signed-off-by: Marc Zyngier Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ixp4xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c index 8bd23e80c61f..1a57e74fdb91 100644 --- a/drivers/gpio/gpio-ixp4xx.c +++ b/drivers/gpio/gpio-ixp4xx.c @@ -231,7 +231,7 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev) g->fwnode = of_node_to_fwnode(np); } else { parent = ixp4xx_get_irq_domain(); - g->fwnode = irq_domain_alloc_fwnode(g->base); + g->fwnode = irq_domain_alloc_fwnode(&res->start); if (!g->fwnode) { dev_err(dev, "no domain base\n"); return -ENODEV; From ff6cd68d6601f9aae3eccd691af68f47cf81ec7d Mon Sep 17 00:00:00 2001 From: Song Hui Date: Thu, 8 Aug 2019 18:16:26 +0800 Subject: [PATCH 51/82] gpio: mpc8xxx: add ls1088a platform gpio node DT binding description ls1088a and ls1028a platform share common gpio node. Signed-off-by: Song Hui Link: https://lore.kernel.org/r/20190808101628.36782-1-hui.song_1@nxp.com Reviewed-by: Rob Herring Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt index baf95d93f85d..cd28e932bf50 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt @@ -4,7 +4,7 @@ Required properties: - compatible : Should be "fsl,-gpio" The following s are known to be supported: mpc5121, mpc5125, mpc8349, mpc8572, mpc8610, pq3, qoriq, - ls1021a, ls1043a, ls2080a, ls1028a. + ls1021a, ls1043a, ls2080a, ls1028a, ls1088a. - reg : Address and length of the register set for the device - interrupts : Should be the port interrupt shared by all 32 pins. - #gpio-cells : Should be two. The first cell is the pin number and @@ -39,10 +39,10 @@ gpio0: gpio@2300000 { }; -Example of gpio-controller node for a ls1028a SoC: +Example of gpio-controller node for a ls1028a/ls1088a SoC: gpio1: gpio@2300000 { - compatible = "fsl,ls1028a-gpio","fsl,qoriq-gpio"; + compatible = "fsl,ls1028a-gpio", "fsl,ls1088a-gpio", "fsl,qoriq-gpio"; reg = <0x0 0x2300000 0x0 0x10000>; interrupts = ; gpio-controller; From 7b732209eb5d78ab114ae5e2a480d7417f30a2b1 Mon Sep 17 00:00:00 2001 From: Song Hui Date: Thu, 8 Aug 2019 18:16:28 +0800 Subject: [PATCH 52/82] gpio: mpc8xxx: add ls1088a platform special function ls1028a and ls1088a platform share common special function. The gpio hardware what they use is the same version. Signed-off-by: Song Hui Link: https://lore.kernel.org/r/20190808101628.36782-3-hui.song_1@nxp.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mpc8xxx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index 1a680aa28769..16a47de29c94 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -319,6 +319,7 @@ static const struct of_device_id mpc8xxx_gpio_ids[] = { { .compatible = "fsl,mpc5125-gpio", .data = &mpc5125_gpio_devtype, }, { .compatible = "fsl,pq3-gpio", }, { .compatible = "fsl,ls1028a-gpio", .data = &ls1028a_gpio_devtype, }, + { .compatible = "fsl,ls1088a-gpio", .data = &ls1028a_gpio_devtype, }, { .compatible = "fsl,qoriq-gpio", }, {} }; From 49751efbf63024816d2791e2a173b35c3112f32d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 9 Aug 2019 15:38:45 +0200 Subject: [PATCH 53/82] gpio: zx: Pass irqchip when adding gpiochip We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. Cc: Jonas Gorski Cc: Jun Nie Cc: Thierry Reding Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190809133845.30991-1-linus.walleij@linaro.org --- drivers/gpio/gpio-zx.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpio-zx.c b/drivers/gpio/gpio-zx.c index 8d9b9bf8510a..98cbaf0e415e 100644 --- a/drivers/gpio/gpio-zx.c +++ b/drivers/gpio/gpio-zx.c @@ -215,6 +215,7 @@ static int zx_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct zx_gpio *chip; + struct gpio_irq_chip *girq; int irq, id, ret; chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); @@ -242,31 +243,30 @@ static int zx_gpio_probe(struct platform_device *pdev) chip->gc.parent = dev; chip->gc.owner = THIS_MODULE; - ret = gpiochip_add_data(&chip->gc, chip); - if (ret) - return ret; - /* * irq_chip support */ writew_relaxed(0xffff, chip->base + ZX_GPIO_IM); writew_relaxed(0, chip->base + ZX_GPIO_IE); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - gpiochip_remove(&chip->gc); - return -ENODEV; - } + if (irq < 0) + return irq; + girq = &chip->gc.irq; + girq->chip = &zx_irqchip; + girq->parent_handler = zx_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->dev, 1, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; - ret = gpiochip_irqchip_add(&chip->gc, &zx_irqchip, - 0, handle_simple_irq, - IRQ_TYPE_NONE); - if (ret) { - dev_err(dev, "could not add irqchip\n"); - gpiochip_remove(&chip->gc); + ret = gpiochip_add_data(&chip->gc, chip); + if (ret) return ret; - } - gpiochip_set_chained_irqchip(&chip->gc, &zx_irqchip, - irq, zx_irq_handler); platform_set_drvdata(pdev, chip); dev_info(dev, "ZX GPIO chip registered\n"); From e599256ab78b99614b361b551145f3f95c9b3041 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 9 Aug 2019 16:19:16 +0200 Subject: [PATCH 54/82] gpio: vf610: Pass irqchip when adding gpiochip We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. Cc: Andrey Smirnov Cc: Andrew Lunn Cc: Dong Aisheng Cc: Stefan Agner Cc: Thierry Reding Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190809141916.20999-1-linus.walleij@linaro.org --- drivers/gpio/gpio-vf610.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 7ba668db171b..58776f2d69ff 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -243,6 +243,7 @@ static int vf610_gpio_probe(struct platform_device *pdev) struct device_node *np = dev->of_node; struct vf610_gpio_port *port; struct gpio_chip *gc; + struct gpio_irq_chip *girq; struct irq_chip *ic; int i; int ret; @@ -318,10 +319,6 @@ static int vf610_gpio_probe(struct platform_device *pdev) ic->irq_set_type = vf610_gpio_irq_set_type; ic->irq_set_wake = vf610_gpio_irq_set_wake; - ret = devm_gpiochip_add_data(dev, gc, port); - if (ret < 0) - return ret; - /* Mask all GPIO interrupts */ for (i = 0; i < gc->ngpio; i++) vf610_gpio_writel(0, port->base + PORT_PCR(i)); @@ -329,15 +326,20 @@ static int vf610_gpio_probe(struct platform_device *pdev) /* Clear the interrupt status register for all GPIO's */ vf610_gpio_writel(~0, port->base + PORT_ISFR); - ret = gpiochip_irqchip_add(gc, ic, 0, handle_edge_irq, IRQ_TYPE_NONE); - if (ret) { - dev_err(dev, "failed to add irqchip\n"); - return ret; - } - gpiochip_set_chained_irqchip(gc, ic, port->irq, - vf610_gpio_irq_handler); + girq = &gc->irq; + girq->chip = ic; + girq->parent_handler = vf610_gpio_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->dev, 1, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = port->irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_edge_irq; - return 0; + return devm_gpiochip_add_data(dev, gc, port); } static struct platform_driver vf610_gpio_driver = { From 74639d66e1ec069d27eebb97b545916a86d983ea Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 9 Aug 2019 16:40:45 +0200 Subject: [PATCH 55/82] gpio: tqmx86: Pass irqchip when adding gpiochip We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. Cc: Andrew Lunn Cc: Thierry Reding Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190809144045.26018-1-linus.walleij@linaro.org --- drivers/gpio/gpio-tqmx86.c | 41 ++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpio-tqmx86.c b/drivers/gpio/gpio-tqmx86.c index d5880db7f9d4..07050cdbadb9 100644 --- a/drivers/gpio/gpio-tqmx86.c +++ b/drivers/gpio/gpio-tqmx86.c @@ -219,6 +219,7 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct tqmx86_gpio_data *gpio; struct gpio_chip *chip; + struct gpio_irq_chip *girq; void __iomem *io_base; struct resource *res; int ret, irq; @@ -264,12 +265,6 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); - ret = devm_gpiochip_add_data(dev, chip, gpio); - if (ret) { - dev_err(dev, "Could not register GPIO chip\n"); - goto out_pm_dis; - } - if (irq) { struct irq_chip *irq_chip = &gpio->irq_chip; u8 irq_status; @@ -287,23 +282,35 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) irq_status = tqmx86_gpio_read(gpio, TQMX86_GPIIS); tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS); - ret = gpiochip_irqchip_add(chip, irq_chip, - 0, handle_simple_irq, - IRQ_TYPE_EDGE_BOTH); - if (ret) { - dev_err(dev, "Could not add irq chip\n"); + girq = &chip->irq; + girq->chip = irq_chip; + girq->parent_handler = tqmx86_gpio_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->dev, 1, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) { + ret = -ENOMEM; goto out_pm_dis; } + girq->parents[0] = irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; + } - gpiochip_set_chained_irqchip(chip, irq_chip, - irq, tqmx86_gpio_irq_handler); + ret = devm_gpiochip_add_data(dev, chip, gpio); + if (ret) { + dev_err(dev, "Could not register GPIO chip\n"); + goto out_pm_dis; } /* Only GPIOs 4-7 are valid for interrupts. Clear the others */ - clear_bit(0, chip->irq.valid_mask); - clear_bit(1, chip->irq.valid_mask); - clear_bit(2, chip->irq.valid_mask); - clear_bit(3, chip->irq.valid_mask); + if (irq) { + clear_bit(0, girq->valid_mask); + clear_bit(1, girq->valid_mask); + clear_bit(2, girq->valid_mask); + clear_bit(3, girq->valid_mask); + } dev_info(dev, "GPIO functionality initialized with %d pins\n", chip->ngpio); From d5d4aa1ec1983911b0e1c656c97da16332f85fc9 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Tue, 13 Aug 2019 09:15:47 +0300 Subject: [PATCH 56/82] MAINTAINERS: Remove FMC subsystem Cleanup MAINTAINERS from FMC record since the subsystem was removed. Cc: Pat Riehecky Fixes: 6a80b30086b8 ("fmc: Delete the FMC subsystem") Signed-off-by: Denis Efremov Link: https://lore.kernel.org/r/20190813061547.17847-1-efremov@linux.com Reviewed-by: Federico Vaga Signed-off-by: Linus Walleij --- MAINTAINERS | 9 --------- 1 file changed, 9 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 783569e3c4b4..b9d8bc8241b8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6326,15 +6326,6 @@ S: Orphan L: linux-block@vger.kernel.org F: drivers/block/floppy.c -FMC SUBSYSTEM -M: Alessandro Rubini -W: http://www.ohwr.org/projects/fmc-bus -S: Supported -F: drivers/fmc/ -F: include/linux/fmc*.h -F: include/linux/ipmi-fru.h -K: fmc_d.*register - FPGA MANAGER FRAMEWORK M: Moritz Fischer L: linux-fpga@vger.kernel.org From 7db47faae79bbffe2da15af4d5e061a49a56169b Mon Sep 17 00:00:00 2001 From: Hongwei Zhang Date: Tue, 20 Aug 2019 17:05:28 -0400 Subject: [PATCH 57/82] gpio: aspeed: Add SGPIO driver Add SGPIO driver support for Aspeed AST2500 SoC. Signed-off-by: Hongwei Zhang Reviewed-by: Andrew Jeffery Link: https://lore.kernel.org/r/1566335128-31498-2-git-send-email-hongweiz@ami.com Signed-off-by: Linus Walleij --- drivers/gpio/sgpio-aspeed.c | 533 ++++++++++++++++++++++++++++++++++++ 1 file changed, 533 insertions(+) create mode 100644 drivers/gpio/sgpio-aspeed.c diff --git a/drivers/gpio/sgpio-aspeed.c b/drivers/gpio/sgpio-aspeed.c new file mode 100644 index 000000000000..7e99860ca447 --- /dev/null +++ b/drivers/gpio/sgpio-aspeed.c @@ -0,0 +1,533 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2019 American Megatrends International LLC. + * + * Author: Karthikeyan Mani + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_NR_SGPIO 80 + +#define ASPEED_SGPIO_CTRL 0x54 + +#define ASPEED_SGPIO_PINS_MASK GENMASK(9, 6) +#define ASPEED_SGPIO_CLK_DIV_MASK GENMASK(31, 16) +#define ASPEED_SGPIO_ENABLE BIT(0) + +struct aspeed_sgpio { + struct gpio_chip chip; + struct clk *pclk; + spinlock_t lock; + void __iomem *base; + uint32_t dir_in[3]; + int irq; +}; + +struct aspeed_sgpio_bank { + uint16_t val_regs; + uint16_t rdata_reg; + uint16_t irq_regs; + const char names[4][3]; +}; + +/* + * Note: The "value" register returns the input value when the GPIO is + * configured as an input. + * + * The "rdata" register returns the output value when the GPIO is + * configured as an output. + */ +static const struct aspeed_sgpio_bank aspeed_sgpio_banks[] = { + { + .val_regs = 0x0000, + .rdata_reg = 0x0070, + .irq_regs = 0x0004, + .names = { "A", "B", "C", "D" }, + }, + { + .val_regs = 0x001C, + .rdata_reg = 0x0074, + .irq_regs = 0x0020, + .names = { "E", "F", "G", "H" }, + }, + { + .val_regs = 0x0038, + .rdata_reg = 0x0078, + .irq_regs = 0x003C, + .names = { "I", "J" }, + }, +}; + +enum aspeed_sgpio_reg { + reg_val, + reg_rdata, + reg_irq_enable, + reg_irq_type0, + reg_irq_type1, + reg_irq_type2, + reg_irq_status, +}; + +#define GPIO_VAL_VALUE 0x00 +#define GPIO_IRQ_ENABLE 0x00 +#define GPIO_IRQ_TYPE0 0x04 +#define GPIO_IRQ_TYPE1 0x08 +#define GPIO_IRQ_TYPE2 0x0C +#define GPIO_IRQ_STATUS 0x10 + +static void __iomem *bank_reg(struct aspeed_sgpio *gpio, + const struct aspeed_sgpio_bank *bank, + const enum aspeed_sgpio_reg reg) +{ + switch (reg) { + case reg_val: + return gpio->base + bank->val_regs + GPIO_VAL_VALUE; + case reg_rdata: + return gpio->base + bank->rdata_reg; + case reg_irq_enable: + return gpio->base + bank->irq_regs + GPIO_IRQ_ENABLE; + case reg_irq_type0: + return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE0; + case reg_irq_type1: + return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE1; + case reg_irq_type2: + return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE2; + case reg_irq_status: + return gpio->base + bank->irq_regs + GPIO_IRQ_STATUS; + default: + /* acturally if code runs to here, it's an error case */ + BUG_ON(1); + } +} + +#define GPIO_BANK(x) ((x) >> 5) +#define GPIO_OFFSET(x) ((x) & 0x1f) +#define GPIO_BIT(x) BIT(GPIO_OFFSET(x)) + +static const struct aspeed_sgpio_bank *to_bank(unsigned int offset) +{ + unsigned int bank = GPIO_BANK(offset); + + WARN_ON(bank >= ARRAY_SIZE(aspeed_sgpio_banks)); + return &aspeed_sgpio_banks[bank]; +} + +static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset) +{ + struct aspeed_sgpio *gpio = gpiochip_get_data(gc); + const struct aspeed_sgpio_bank *bank = to_bank(offset); + unsigned long flags; + enum aspeed_sgpio_reg reg; + bool is_input; + int rc = 0; + + spin_lock_irqsave(&gpio->lock, flags); + + is_input = gpio->dir_in[GPIO_BANK(offset)] & GPIO_BIT(offset); + reg = is_input ? reg_val : reg_rdata; + rc = !!(ioread32(bank_reg(gpio, bank, reg)) & GPIO_BIT(offset)); + + spin_unlock_irqrestore(&gpio->lock, flags); + + return rc; +} + +static void sgpio_set_value(struct gpio_chip *gc, unsigned int offset, int val) +{ + struct aspeed_sgpio *gpio = gpiochip_get_data(gc); + const struct aspeed_sgpio_bank *bank = to_bank(offset); + void __iomem *addr; + u32 reg = 0; + + addr = bank_reg(gpio, bank, reg_val); + reg = ioread32(addr); + + if (val) + reg |= GPIO_BIT(offset); + else + reg &= ~GPIO_BIT(offset); + + iowrite32(reg, addr); +} + +static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val) +{ + struct aspeed_sgpio *gpio = gpiochip_get_data(gc); + unsigned long flags; + + spin_lock_irqsave(&gpio->lock, flags); + + sgpio_set_value(gc, offset, val); + + spin_unlock_irqrestore(&gpio->lock, flags); +} + +static int aspeed_sgpio_dir_in(struct gpio_chip *gc, unsigned int offset) +{ + struct aspeed_sgpio *gpio = gpiochip_get_data(gc); + unsigned long flags; + + spin_lock_irqsave(&gpio->lock, flags); + gpio->dir_in[GPIO_BANK(offset)] |= GPIO_BIT(offset); + spin_unlock_irqrestore(&gpio->lock, flags); + + return 0; +} + +static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, int val) +{ + struct aspeed_sgpio *gpio = gpiochip_get_data(gc); + unsigned long flags; + + spin_lock_irqsave(&gpio->lock, flags); + + gpio->dir_in[GPIO_BANK(offset)] &= ~GPIO_BIT(offset); + sgpio_set_value(gc, offset, val); + + spin_unlock_irqrestore(&gpio->lock, flags); + + return 0; +} + +static int aspeed_sgpio_get_direction(struct gpio_chip *gc, unsigned int offset) +{ + int dir_status; + struct aspeed_sgpio *gpio = gpiochip_get_data(gc); + unsigned long flags; + + spin_lock_irqsave(&gpio->lock, flags); + dir_status = gpio->dir_in[GPIO_BANK(offset)] & GPIO_BIT(offset); + spin_unlock_irqrestore(&gpio->lock, flags); + + return dir_status; + +} + +static void irqd_to_aspeed_sgpio_data(struct irq_data *d, + struct aspeed_sgpio **gpio, + const struct aspeed_sgpio_bank **bank, + u32 *bit, int *offset) +{ + struct aspeed_sgpio *internal; + + *offset = irqd_to_hwirq(d); + internal = irq_data_get_irq_chip_data(d); + WARN_ON(!internal); + + *gpio = internal; + *bank = to_bank(*offset); + *bit = GPIO_BIT(*offset); +} + +static void aspeed_sgpio_irq_ack(struct irq_data *d) +{ + const struct aspeed_sgpio_bank *bank; + struct aspeed_sgpio *gpio; + unsigned long flags; + void __iomem *status_addr; + int offset; + u32 bit; + + irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset); + + status_addr = bank_reg(gpio, bank, reg_irq_status); + + spin_lock_irqsave(&gpio->lock, flags); + + iowrite32(bit, status_addr); + + spin_unlock_irqrestore(&gpio->lock, flags); +} + +static void aspeed_sgpio_irq_set_mask(struct irq_data *d, bool set) +{ + const struct aspeed_sgpio_bank *bank; + struct aspeed_sgpio *gpio; + unsigned long flags; + u32 reg, bit; + void __iomem *addr; + int offset; + + irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset); + addr = bank_reg(gpio, bank, reg_irq_enable); + + spin_lock_irqsave(&gpio->lock, flags); + + reg = ioread32(addr); + if (set) + reg |= bit; + else + reg &= ~bit; + + iowrite32(reg, addr); + + spin_unlock_irqrestore(&gpio->lock, flags); +} + +static void aspeed_sgpio_irq_mask(struct irq_data *d) +{ + aspeed_sgpio_irq_set_mask(d, false); +} + +static void aspeed_sgpio_irq_unmask(struct irq_data *d) +{ + aspeed_sgpio_irq_set_mask(d, true); +} + +static int aspeed_sgpio_set_type(struct irq_data *d, unsigned int type) +{ + u32 type0 = 0; + u32 type1 = 0; + u32 type2 = 0; + u32 bit, reg; + const struct aspeed_sgpio_bank *bank; + irq_flow_handler_t handler; + struct aspeed_sgpio *gpio; + unsigned long flags; + void __iomem *addr; + int offset; + + irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset); + + switch (type & IRQ_TYPE_SENSE_MASK) { + case IRQ_TYPE_EDGE_BOTH: + type2 |= bit; + /* fall through */ + case IRQ_TYPE_EDGE_RISING: + type0 |= bit; + /* fall through */ + case IRQ_TYPE_EDGE_FALLING: + handler = handle_edge_irq; + break; + case IRQ_TYPE_LEVEL_HIGH: + type0 |= bit; + /* fall through */ + case IRQ_TYPE_LEVEL_LOW: + type1 |= bit; + handler = handle_level_irq; + break; + default: + return -EINVAL; + } + + spin_lock_irqsave(&gpio->lock, flags); + + addr = bank_reg(gpio, bank, reg_irq_type0); + reg = ioread32(addr); + reg = (reg & ~bit) | type0; + iowrite32(reg, addr); + + addr = bank_reg(gpio, bank, reg_irq_type1); + reg = ioread32(addr); + reg = (reg & ~bit) | type1; + iowrite32(reg, addr); + + addr = bank_reg(gpio, bank, reg_irq_type2); + reg = ioread32(addr); + reg = (reg & ~bit) | type2; + iowrite32(reg, addr); + + spin_unlock_irqrestore(&gpio->lock, flags); + + irq_set_handler_locked(d, handler); + + return 0; +} + +static void aspeed_sgpio_irq_handler(struct irq_desc *desc) +{ + struct gpio_chip *gc = irq_desc_get_handler_data(desc); + struct irq_chip *ic = irq_desc_get_chip(desc); + struct aspeed_sgpio *data = gpiochip_get_data(gc); + unsigned int i, p, girq; + unsigned long reg; + + chained_irq_enter(ic, desc); + + for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) { + const struct aspeed_sgpio_bank *bank = &aspeed_sgpio_banks[i]; + + reg = ioread32(bank_reg(data, bank, reg_irq_status)); + + for_each_set_bit(p, ®, 32) { + girq = irq_find_mapping(gc->irq.domain, i * 32 + p); + generic_handle_irq(girq); + } + + } + + chained_irq_exit(ic, desc); +} + +static struct irq_chip aspeed_sgpio_irqchip = { + .name = "aspeed-sgpio", + .irq_ack = aspeed_sgpio_irq_ack, + .irq_mask = aspeed_sgpio_irq_mask, + .irq_unmask = aspeed_sgpio_irq_unmask, + .irq_set_type = aspeed_sgpio_set_type, +}; + +static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio, + struct platform_device *pdev) +{ + int rc, i; + const struct aspeed_sgpio_bank *bank; + struct gpio_irq_chip *irq; + + rc = platform_get_irq(pdev, 0); + if (rc < 0) + return rc; + + gpio->irq = rc; + + /* Disable IRQ and clear Interrupt status registers for all SPGIO Pins. */ + for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) { + bank = &aspeed_sgpio_banks[i]; + /* disable irq enable bits */ + iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_enable)); + /* clear status bits */ + iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_status)); + } + + irq = &gpio->chip.irq; + irq->chip = &aspeed_sgpio_irqchip; + irq->handler = handle_bad_irq; + irq->default_type = IRQ_TYPE_NONE; + irq->parent_handler = aspeed_sgpio_irq_handler; + irq->parent_handler_data = gpio; + irq->parents = &gpio->irq; + irq->num_parents = 1; + + /* set IRQ settings and Enable Interrupt */ + for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) { + bank = &aspeed_sgpio_banks[i]; + /* set falling or level-low irq */ + iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type0)); + /* trigger type is edge */ + iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type1)); + /* dual edge trigger mode. */ + iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_type2)); + /* enable irq */ + iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_enable)); + } + + return 0; +} + +static const struct of_device_id aspeed_sgpio_of_table[] = { + { .compatible = "aspeed,ast2400-sgpio" }, + { .compatible = "aspeed,ast2500-sgpio" }, + {} +}; + +MODULE_DEVICE_TABLE(of, aspeed_sgpio_of_table); + +static int __init aspeed_sgpio_probe(struct platform_device *pdev) +{ + struct aspeed_sgpio *gpio; + u32 nr_gpios, sgpio_freq, sgpio_clk_div; + int rc; + unsigned long apb_freq; + + gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); + if (!gpio) + return -ENOMEM; + + gpio->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(gpio->base)) + return PTR_ERR(gpio->base); + + rc = of_property_read_u32(pdev->dev.of_node, "ngpios", &nr_gpios); + if (rc < 0) { + dev_err(&pdev->dev, "Could not read ngpios property\n"); + return -EINVAL; + } else if (nr_gpios > MAX_NR_SGPIO) { + dev_err(&pdev->dev, "Number of GPIOs exceeds the maximum of %d: %d\n", + MAX_NR_SGPIO, nr_gpios); + return -EINVAL; + } + + rc = of_property_read_u32(pdev->dev.of_node, "bus-frequency", &sgpio_freq); + if (rc < 0) { + dev_err(&pdev->dev, "Could not read bus-frequency property\n"); + return -EINVAL; + } + + gpio->pclk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(gpio->pclk)) { + dev_err(&pdev->dev, "devm_clk_get failed\n"); + return PTR_ERR(gpio->pclk); + } + + apb_freq = clk_get_rate(gpio->pclk); + + /* + * From the datasheet, + * SGPIO period = 1/PCLK * 2 * (GPIO254[31:16] + 1) + * period = 2 * (GPIO254[31:16] + 1) / PCLK + * frequency = 1 / (2 * (GPIO254[31:16] + 1) / PCLK) + * frequency = PCLK / (2 * (GPIO254[31:16] + 1)) + * frequency * 2 * (GPIO254[31:16] + 1) = PCLK + * GPIO254[31:16] = PCLK / (frequency * 2) - 1 + */ + if (sgpio_freq == 0) + return -EINVAL; + + sgpio_clk_div = (apb_freq / (sgpio_freq * 2)) - 1; + + if (sgpio_clk_div > (1 << 16) - 1) + return -EINVAL; + + iowrite32(FIELD_PREP(ASPEED_SGPIO_CLK_DIV_MASK, sgpio_clk_div) | + FIELD_PREP(ASPEED_SGPIO_PINS_MASK, (nr_gpios / 8)) | + ASPEED_SGPIO_ENABLE, + gpio->base + ASPEED_SGPIO_CTRL); + + spin_lock_init(&gpio->lock); + + gpio->chip.parent = &pdev->dev; + gpio->chip.ngpio = nr_gpios; + gpio->chip.direction_input = aspeed_sgpio_dir_in; + gpio->chip.direction_output = aspeed_sgpio_dir_out; + gpio->chip.get_direction = aspeed_sgpio_get_direction; + gpio->chip.request = NULL; + gpio->chip.free = NULL; + gpio->chip.get = aspeed_sgpio_get; + gpio->chip.set = aspeed_sgpio_set; + gpio->chip.set_config = NULL; + gpio->chip.label = dev_name(&pdev->dev); + gpio->chip.base = -1; + + /* set all SGPIO pins as input (1). */ + memset(gpio->dir_in, 0xff, sizeof(gpio->dir_in)); + + aspeed_sgpio_setup_irqs(gpio, pdev); + + rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); + if (rc < 0) + return rc; + + return 0; +} + +static struct platform_driver aspeed_sgpio_driver = { + .driver = { + .name = KBUILD_MODNAME, + .of_match_table = aspeed_sgpio_of_table, + }, +}; + +module_platform_driver_probe(aspeed_sgpio_driver, aspeed_sgpio_probe); +MODULE_DESCRIPTION("Aspeed Serial GPIO Driver"); +MODULE_LICENSE("GPL"); From c7663fa2a6631e5dddc1b7b2ba2e905ddffaff90 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 22 Aug 2019 11:18:17 +0800 Subject: [PATCH 58/82] gpio: Move gpiochip_lock/unlock_as_irq to gpio/driver.h If CONFIG_GPIOLIB is not, gpiochip_lock/unlock_as_irq will conflict as this: In file included from sound/soc/codecs/wm5100.c:18:0: ./include/linux/gpio.h:224:19: error: static declaration of gpiochip_lock_as_irq follows non-static declaration static inline int gpiochip_lock_as_irq(struct gpio_chip *chip, ^~~~~~~~~~~~~~~~~~~~ In file included from sound/soc/codecs/wm5100.c:17:0: ./include/linux/gpio/driver.h:494:5: note: previous declaration of gpiochip_lock_as_irq was here int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset); ^~~~~~~~~~~~~~~~~~~~ In file included from sound/soc/codecs/wm5100.c:18:0: ./include/linux/gpio.h:231:20: error: static declaration of gpiochip_unlock_as_irq follows non-static declaration static inline void gpiochip_unlock_as_irq(struct gpio_chip *chip, ^~~~~~~~~~~~~~~~~~~~~~ In file included from sound/soc/codecs/wm5100.c:17:0: ./include/linux/gpio/driver.h:495:6: note: previous declaration of gpiochip_unlock_as_irq was here void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset); ^~~~~~~~~~~~~~~~~~~~~~ Move them to gpio/driver.h and use CONFIG_GPIOLIB guard this. Reported-by: Hulk Robot Fixes: d74be6dfea1b ("gpio: remove gpiod_lock/unlock_as_irq()") Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190822031817.32888-1-yuehaibing@huawei.com Signed-off-by: Linus Walleij --- include/linux/gpio.h | 13 ------------- include/linux/gpio/driver.h | 19 ++++++++++++++++--- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 40915b461f18..d20e224804e6 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -221,19 +221,6 @@ static inline int gpio_to_irq(unsigned gpio) return -EINVAL; } -static inline int gpiochip_lock_as_irq(struct gpio_chip *chip, - unsigned int offset) -{ - WARN_ON(1); - return -EINVAL; -} - -static inline void gpiochip_unlock_as_irq(struct gpio_chip *chip, - unsigned int offset) -{ - WARN_ON(1); -} - static inline int irq_to_gpio(unsigned irq) { /* irq can never have been returned from gpio_to_irq() */ diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 340121c7d2fb..8d06a054abc8 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -495,9 +495,6 @@ extern int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *chip, extern struct gpio_chip *gpiochip_find(void *data, int (*match)(struct gpio_chip *chip, void *data)); -/* lock/unlock as IRQ */ -int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset); -void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset); bool gpiochip_line_is_irq(struct gpio_chip *chip, unsigned int offset); int gpiochip_reqres_irq(struct gpio_chip *chip, unsigned int offset); void gpiochip_relres_irq(struct gpio_chip *chip, unsigned int offset); @@ -723,6 +720,10 @@ void gpiochip_free_own_desc(struct gpio_desc *desc); void devprop_gpiochip_set_names(struct gpio_chip *chip, const struct fwnode_handle *fwnode); +/* lock/unlock as IRQ */ +int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset); +void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset); + #else /* CONFIG_GPIOLIB */ static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) @@ -732,6 +733,18 @@ static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) return ERR_PTR(-ENODEV); } +static inline int gpiochip_lock_as_irq(struct gpio_chip *chip, + unsigned int offset) +{ + WARN_ON(1); + return -EINVAL; +} + +static inline void gpiochip_unlock_as_irq(struct gpio_chip *chip, + unsigned int offset) +{ + WARN_ON(1); +} #endif /* CONFIG_GPIOLIB */ #endif From b1d64c7139c1ec673bac8be88b27caf02cf73118 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 22 Aug 2019 22:45:38 +0200 Subject: [PATCH 59/82] gpio: ftgpio: Fix an error handling path in 'ftgpio_gpio_probe()' If 'devm_kcalloc()' fails, we should go through the error handling path, should some clean-up be needed. Fixes: 42d9fc7176eb ("gpio: ftgpio: Pass irqchip when adding gpiochip") Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/20190822204538.4791-1-christophe.jaillet@wanadoo.fr Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ftgpio010.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-ftgpio010.c b/drivers/gpio/gpio-ftgpio010.c index 3118d282514a..fbddb1662428 100644 --- a/drivers/gpio/gpio-ftgpio010.c +++ b/drivers/gpio/gpio-ftgpio010.c @@ -290,8 +290,10 @@ static int ftgpio_gpio_probe(struct platform_device *pdev) girq->num_parents = 1; girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents), GFP_KERNEL); - if (!girq->parents) - return -ENOMEM; + if (!girq->parents) { + ret = -ENOMEM; + goto dis_clk; + } girq->default_type = IRQ_TYPE_NONE; girq->handler = handle_bad_irq; girq->parents[0] = irq; From f4e9bcc05f4e8d543afbfc0ca1fd4435a2204776 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 9 Aug 2019 16:11:16 +0200 Subject: [PATCH 60/82] gpio: mt7621: Pass irqchip when adding gpiochip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. This driver requests the IRQ directly in the driver so it differs a bit from the others. Cc: Greg Ungerer Cc: Nicholas Mc Guire Cc: Sergio Paracuellos Cc: Thierry Reding Signed-off-by: Linus Walleij Tested-by: René van Dorst Link: https://lore.kernel.org/r/20190809141116.16403-1-linus.walleij@linaro.org --- drivers/gpio/gpio-mt7621.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/gpio/gpio-mt7621.c b/drivers/gpio/gpio-mt7621.c index 79654fb2e50f..d1d785f983a7 100644 --- a/drivers/gpio/gpio-mt7621.c +++ b/drivers/gpio/gpio-mt7621.c @@ -241,13 +241,6 @@ mediatek_gpio_bank_probe(struct device *dev, if (!rg->chip.label) return -ENOMEM; - ret = devm_gpiochip_add_data(dev, &rg->chip, mtk); - if (ret < 0) { - dev_err(dev, "Could not register gpio %d, ret=%d\n", - rg->chip.ngpio, ret); - return ret; - } - rg->irq_chip.name = dev_name(dev); rg->irq_chip.parent_device = dev; rg->irq_chip.irq_unmask = mediatek_gpio_irq_unmask; @@ -256,8 +249,10 @@ mediatek_gpio_bank_probe(struct device *dev, rg->irq_chip.irq_set_type = mediatek_gpio_irq_type; if (mtk->gpio_irq) { + struct gpio_irq_chip *girq; + /* - * Manually request the irq here instead of passing + * Directly request the irq here instead of passing * a flow-handler to gpiochip_set_chained_irqchip, * because the irq is shared. */ @@ -271,15 +266,21 @@ mediatek_gpio_bank_probe(struct device *dev, return ret; } - ret = gpiochip_irqchip_add(&rg->chip, &rg->irq_chip, - 0, handle_simple_irq, IRQ_TYPE_NONE); - if (ret) { - dev_err(dev, "failed to add gpiochip_irqchip\n"); - return ret; - } + girq = &rg->chip.irq; + girq->chip = &rg->irq_chip; + /* This will let us handle the parent IRQ in the driver */ + girq->parent_handler = NULL; + girq->num_parents = 0; + girq->parents = NULL; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; + } - gpiochip_set_chained_irqchip(&rg->chip, &rg->irq_chip, - mtk->gpio_irq, NULL); + ret = devm_gpiochip_add_data(dev, &rg->chip, mtk); + if (ret < 0) { + dev_err(dev, "Could not register gpio %d, ret=%d\n", + rg->chip.ngpio, ret); + return ret; } /* set polarity to low for all gpios */ From 85af79659f455ddbdc5b6b6e2a888a430cb58948 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 22 Aug 2019 11:42:52 +0300 Subject: [PATCH 61/82] MAINTAINERS: Remove stale record for gpio-intel-mid.c David Cohen seems left Intel few years back. Remove the stale record in MAINTAINERS data base. The file is anyway listed under my maintainership. Reported-by: Dave Hansen Signed-off-by: Andy Shevchenko --- MAINTAINERS | 6 ------ 1 file changed, 6 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 783569e3c4b4..5a8da707fc59 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8371,12 +8371,6 @@ F: Documentation/x86/intel_txt.rst F: include/linux/tboot.h F: arch/x86/kernel/tboot.c -INTEL-MID GPIO DRIVER -M: David Cohen -L: linux-gpio@vger.kernel.org -S: Maintained -F: drivers/gpio/gpio-intel-mid.c - INTERCONNECT API M: Georgi Djakov L: linux-pm@vger.kernel.org From f6a7053ddcf1c05c443715d627507f0ab9a0b491 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 9 Aug 2019 15:26:49 +0200 Subject: [PATCH 62/82] gpio: zynq: Pass irqchip when adding gpiochip We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. Cc: Michal Simek Cc: Shubhrajyoti Datta Cc: Thierry Reding Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190809132649.25176-1-linus.walleij@linaro.org --- drivers/gpio/gpio-zynq.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 86b0bd256c13..cd475ff4bcad 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -830,6 +830,7 @@ static int zynq_gpio_probe(struct platform_device *pdev) int ret, bank_num; struct zynq_gpio *gpio; struct gpio_chip *chip; + struct gpio_irq_chip *girq; const struct of_device_id *match; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); @@ -885,6 +886,27 @@ static int zynq_gpio_probe(struct platform_device *pdev) if (ret < 0) goto err_pm_dis; + /* disable interrupts for all banks */ + for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) + writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr + + ZYNQ_GPIO_INTDIS_OFFSET(bank_num)); + + /* Set up the GPIO irqchip */ + girq = &chip->irq; + girq->chip = &zynq_gpio_edge_irqchip; + girq->parent_handler = zynq_gpio_irqhandler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->dev, 1, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) { + ret = -ENOMEM; + goto err_pm_put; + } + girq->parents[0] = gpio->irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_level_irq; + /* report a bug if gpio chip registration fails */ ret = gpiochip_add_data(chip, gpio); if (ret) { @@ -892,27 +914,10 @@ static int zynq_gpio_probe(struct platform_device *pdev) goto err_pm_put; } - /* disable interrupts for all banks */ - for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) - writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr + - ZYNQ_GPIO_INTDIS_OFFSET(bank_num)); - - ret = gpiochip_irqchip_add(chip, &zynq_gpio_edge_irqchip, 0, - handle_level_irq, IRQ_TYPE_NONE); - if (ret) { - dev_err(&pdev->dev, "Failed to add irq chip\n"); - goto err_rm_gpiochip; - } - - gpiochip_set_chained_irqchip(chip, &zynq_gpio_edge_irqchip, gpio->irq, - zynq_gpio_irqhandler); - pm_runtime_put(&pdev->dev); return 0; -err_rm_gpiochip: - gpiochip_remove(chip); err_pm_put: pm_runtime_put(&pdev->dev); err_pm_dis: From d2b0919615108ea2da7749f8b6b4ca6a0fce0baa Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 12 Aug 2019 15:00:00 +0200 Subject: [PATCH 63/82] gpio: ep93xx: Pass irqchip when adding gpiochip We need to convert all old gpio irqchips to pass the irqchip setup along when adding the gpio_chip. For more info see drivers/gpio/TODO. For chained irqchips this is a pretty straight-forward conversion. Cc: Alexander Sverdlin Cc: H Hartley Sweeten Cc: Thierry Reding Tested-by: Alexander Sverdlin Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190812130000.22252-1-linus.walleij@linaro.org --- drivers/gpio/gpio-ep93xx.c | 140 +++++++++++++++++++------------------ 1 file changed, 73 insertions(+), 67 deletions(-) diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c index a90870a60c15..226da8df6f10 100644 --- a/drivers/gpio/gpio-ep93xx.c +++ b/drivers/gpio/gpio-ep93xx.c @@ -269,56 +269,6 @@ static struct irq_chip ep93xx_gpio_irq_chip = { .irq_set_type = ep93xx_gpio_irq_type, }; -static int ep93xx_gpio_init_irq(struct platform_device *pdev, - struct ep93xx_gpio *epg) -{ - int ab_parent_irq = platform_get_irq(pdev, 0); - struct device *dev = &pdev->dev; - int gpio_irq; - int ret; - int i; - - /* The A bank */ - ret = gpiochip_irqchip_add(&epg->gc[0], &ep93xx_gpio_irq_chip, - 64, handle_level_irq, - IRQ_TYPE_NONE); - if (ret) { - dev_err(dev, "Could not add irqchip 0\n"); - return ret; - } - gpiochip_set_chained_irqchip(&epg->gc[0], &ep93xx_gpio_irq_chip, - ab_parent_irq, - ep93xx_gpio_ab_irq_handler); - - /* The B bank */ - ret = gpiochip_irqchip_add(&epg->gc[1], &ep93xx_gpio_irq_chip, - 72, handle_level_irq, - IRQ_TYPE_NONE); - if (ret) { - dev_err(dev, "Could not add irqchip 1\n"); - return ret; - } - gpiochip_set_chained_irqchip(&epg->gc[1], &ep93xx_gpio_irq_chip, - ab_parent_irq, - ep93xx_gpio_ab_irq_handler); - - /* The F bank */ - for (i = 0; i < 8; i++) { - gpio_irq = EP93XX_GPIO_F_IRQ_BASE + i; - irq_set_chip_data(gpio_irq, &epg->gc[5]); - irq_set_chip_and_handler(gpio_irq, &ep93xx_gpio_irq_chip, - handle_level_irq); - irq_clear_status_flags(gpio_irq, IRQ_NOREQUEST); - } - - for (i = 1; i <= 8; i++) - irq_set_chained_handler_and_data(platform_get_irq(pdev, i), - ep93xx_gpio_f_irq_handler, - &epg->gc[i]); - return 0; -} - - /************************************************************************* * gpiolib interface for EP93xx on-chip GPIOs *************************************************************************/ @@ -328,26 +278,33 @@ struct ep93xx_gpio_bank { int dir; int base; bool has_irq; + bool has_hierarchical_irq; + unsigned int irq_base; }; -#define EP93XX_GPIO_BANK(_label, _data, _dir, _base, _has_irq) \ +#define EP93XX_GPIO_BANK(_label, _data, _dir, _base, _has_irq, _has_hier, _irq_base) \ { \ .label = _label, \ .data = _data, \ .dir = _dir, \ .base = _base, \ .has_irq = _has_irq, \ + .has_hierarchical_irq = _has_hier, \ + .irq_base = _irq_base, \ } static struct ep93xx_gpio_bank ep93xx_gpio_banks[] = { - EP93XX_GPIO_BANK("A", 0x00, 0x10, 0, true), /* Bank A has 8 IRQs */ - EP93XX_GPIO_BANK("B", 0x04, 0x14, 8, true), /* Bank B has 8 IRQs */ - EP93XX_GPIO_BANK("C", 0x08, 0x18, 40, false), - EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24, false), - EP93XX_GPIO_BANK("E", 0x20, 0x24, 32, false), - EP93XX_GPIO_BANK("F", 0x30, 0x34, 16, true), /* Bank F has 8 IRQs */ - EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48, false), - EP93XX_GPIO_BANK("H", 0x40, 0x44, 56, false), + /* Bank A has 8 IRQs */ + EP93XX_GPIO_BANK("A", 0x00, 0x10, 0, true, false, 64), + /* Bank B has 8 IRQs */ + EP93XX_GPIO_BANK("B", 0x04, 0x14, 8, true, false, 72), + EP93XX_GPIO_BANK("C", 0x08, 0x18, 40, false, false, 0), + EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24, false, false, 0), + EP93XX_GPIO_BANK("E", 0x20, 0x24, 32, false, false, 0), + /* Bank F has 8 IRQs */ + EP93XX_GPIO_BANK("F", 0x30, 0x34, 16, false, true, 0), + EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48, false, false, 0), + EP93XX_GPIO_BANK("H", 0x40, 0x44, 56, false, false, 0), }; static int ep93xx_gpio_set_config(struct gpio_chip *gc, unsigned offset, @@ -369,12 +326,15 @@ static int ep93xx_gpio_f_to_irq(struct gpio_chip *gc, unsigned offset) return EP93XX_GPIO_F_IRQ_BASE + offset; } -static int ep93xx_gpio_add_bank(struct gpio_chip *gc, struct device *dev, +static int ep93xx_gpio_add_bank(struct gpio_chip *gc, + struct platform_device *pdev, struct ep93xx_gpio *epg, struct ep93xx_gpio_bank *bank) { void __iomem *data = epg->base + bank->data; void __iomem *dir = epg->base + bank->dir; + struct device *dev = &pdev->dev; + struct gpio_irq_chip *girq; int err; err = bgpio_init(gc, dev, 1, data, NULL, NULL, dir, NULL, 0); @@ -384,8 +344,59 @@ static int ep93xx_gpio_add_bank(struct gpio_chip *gc, struct device *dev, gc->label = bank->label; gc->base = bank->base; - if (bank->has_irq) + girq = &gc->irq; + if (bank->has_irq || bank->has_hierarchical_irq) { gc->set_config = ep93xx_gpio_set_config; + girq->chip = &ep93xx_gpio_irq_chip; + } + + if (bank->has_irq) { + int ab_parent_irq = platform_get_irq(pdev, 0); + + girq->parent_handler = ep93xx_gpio_ab_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(dev, 1, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_level_irq; + girq->parents[0] = ab_parent_irq; + girq->first = bank->irq_base; + } + + /* Only bank F has especially funky IRQ handling */ + if (bank->has_hierarchical_irq) { + int gpio_irq; + int i; + + /* + * FIXME: convert this to use hierarchical IRQ support! + * this requires fixing the root irqchip to be hierarchial. + */ + girq->parent_handler = ep93xx_gpio_f_irq_handler; + girq->num_parents = 8; + girq->parents = devm_kcalloc(dev, 8, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + /* Pick resources 1..8 for these IRQs */ + for (i = 1; i <= 8; i++) + girq->parents[i - 1] = platform_get_irq(pdev, i); + for (i = 0; i < 8; i++) { + gpio_irq = EP93XX_GPIO_F_IRQ_BASE + i; + irq_set_chip_data(gpio_irq, &epg->gc[5]); + irq_set_chip_and_handler(gpio_irq, + &ep93xx_gpio_irq_chip, + handle_level_irq); + irq_clear_status_flags(gpio_irq, IRQ_NOREQUEST); + } + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_level_irq; + gc->to_irq = ep93xx_gpio_f_to_irq; + } return devm_gpiochip_add_data(dev, gc, epg); } @@ -407,16 +418,11 @@ static int ep93xx_gpio_probe(struct platform_device *pdev) struct gpio_chip *gc = &epg->gc[i]; struct ep93xx_gpio_bank *bank = &ep93xx_gpio_banks[i]; - if (ep93xx_gpio_add_bank(gc, &pdev->dev, epg, bank)) + if (ep93xx_gpio_add_bank(gc, pdev, epg, bank)) dev_warn(&pdev->dev, "Unable to add gpio bank %s\n", bank->label); - /* Only bank F has especially funky IRQ handling */ - if (i == 5) - gc->to_irq = ep93xx_gpio_f_to_irq; } - ep93xx_gpio_init_irq(pdev, epg); - return 0; } From d377f56f34f5bc549c3aabfe27320f3c31235c05 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 16 Jul 2019 11:11:45 +0200 Subject: [PATCH 64/82] gpio: gpiolib: Normalize return code variable name It is confusing to name return variables mixedly "status", "err" or "ret". I just changed them all to "ret", by personal preference, to lower cognitive stress. Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190716091145.8235-1-linus.walleij@linaro.org --- drivers/gpio/gpiolib.c | 220 ++++++++++++++++++++--------------------- 1 file changed, 110 insertions(+), 110 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 01aa5440454c..5163e87969e7 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -214,7 +214,7 @@ int gpiod_get_direction(struct gpio_desc *desc) { struct gpio_chip *chip; unsigned offset; - int status; + int ret; chip = gpiod_to_chip(desc); offset = gpio_chip_hwgpio(desc); @@ -222,17 +222,17 @@ int gpiod_get_direction(struct gpio_desc *desc) if (!chip->get_direction) return -ENOTSUPP; - status = chip->get_direction(chip, offset); - if (status > 0) { + ret = chip->get_direction(chip, offset); + if (ret > 0) { /* GPIOF_DIR_IN, or other positive */ - status = 1; + ret = 1; clear_bit(FLAG_IS_OUT, &desc->flags); } - if (status == 0) { + if (ret == 0) { /* GPIOF_DIR_OUT */ set_bit(FLAG_IS_OUT, &desc->flags); } - return status; + return ret; } EXPORT_SYMBOL_GPL(gpiod_get_direction); @@ -1166,21 +1166,21 @@ static void gpiodevice_release(struct device *dev) static int gpiochip_setup_dev(struct gpio_device *gdev) { - int status; + int ret; cdev_init(&gdev->chrdev, &gpio_fileops); gdev->chrdev.owner = THIS_MODULE; gdev->dev.devt = MKDEV(MAJOR(gpio_devt), gdev->id); - status = cdev_device_add(&gdev->chrdev, &gdev->dev); - if (status) - return status; + ret = cdev_device_add(&gdev->chrdev, &gdev->dev); + if (ret) + return ret; chip_dbg(gdev->chip, "added GPIO chardev (%d:%d)\n", MAJOR(gpio_devt), gdev->id); - status = gpiochip_sysfs_register(gdev); - if (status) + ret = gpiochip_sysfs_register(gdev); + if (ret) goto err_remove_device; /* From this point, the .release() function cleans up gpio_device */ @@ -1193,7 +1193,7 @@ static int gpiochip_setup_dev(struct gpio_device *gdev) err_remove_device: cdev_device_del(&gdev->chrdev, &gdev->dev); - return status; + return ret; } static void gpiochip_machine_hog(struct gpio_chip *chip, struct gpiod_hog *hog) @@ -1234,13 +1234,13 @@ static void machine_gpiochip_add(struct gpio_chip *chip) static void gpiochip_setup_devs(void) { struct gpio_device *gdev; - int err; + int ret; list_for_each_entry(gdev, &gpio_devices, list) { - err = gpiochip_setup_dev(gdev); - if (err) + ret = gpiochip_setup_dev(gdev); + if (ret) pr_err("%s: Failed to initialize gpio device (%d)\n", - dev_name(&gdev->dev), err); + dev_name(&gdev->dev), ret); } } @@ -1249,7 +1249,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, struct lock_class_key *request_key) { unsigned long flags; - int status = 0; + int ret = 0; unsigned i; int base = chip->base; struct gpio_device *gdev; @@ -1279,7 +1279,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, gdev->id = ida_simple_get(&gpio_ida, 0, 0, GFP_KERNEL); if (gdev->id < 0) { - status = gdev->id; + ret = gdev->id; goto err_free_gdev; } dev_set_name(&gdev->dev, "gpiochip%d", gdev->id); @@ -1295,13 +1295,13 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, gdev->descs = kcalloc(chip->ngpio, sizeof(gdev->descs[0]), GFP_KERNEL); if (!gdev->descs) { - status = -ENOMEM; + ret = -ENOMEM; goto err_free_ida; } if (chip->ngpio == 0) { chip_err(chip, "tried to insert a GPIO chip with zero lines\n"); - status = -EINVAL; + ret = -EINVAL; goto err_free_descs; } @@ -1311,7 +1311,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, gdev->label = kstrdup_const(chip->label ?: "unknown", GFP_KERNEL); if (!gdev->label) { - status = -ENOMEM; + ret = -ENOMEM; goto err_free_descs; } @@ -1330,7 +1330,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, if (base < 0) { base = gpiochip_find_base(chip->ngpio); if (base < 0) { - status = base; + ret = base; spin_unlock_irqrestore(&gpio_lock, flags); goto err_free_label; } @@ -1344,8 +1344,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, } gdev->base = base; - status = gpiodev_add_to_list(gdev); - if (status) { + ret = gpiodev_add_to_list(gdev); + if (ret) { spin_unlock_irqrestore(&gpio_lock, flags); goto err_free_label; } @@ -1359,28 +1359,28 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, INIT_LIST_HEAD(&gdev->pin_ranges); #endif - status = gpiochip_set_desc_names(chip); - if (status) + ret = gpiochip_set_desc_names(chip); + if (ret) goto err_remove_from_list; - status = gpiochip_irqchip_init_valid_mask(chip); - if (status) + ret = gpiochip_irqchip_init_valid_mask(chip); + if (ret) goto err_remove_from_list; - status = gpiochip_alloc_valid_mask(chip); - if (status) + ret = gpiochip_alloc_valid_mask(chip); + if (ret) goto err_remove_irqchip_mask; - status = gpiochip_add_irqchip(chip, lock_key, request_key); - if (status) + ret = gpiochip_add_irqchip(chip, lock_key, request_key); + if (ret) goto err_free_gpiochip_mask; - status = of_gpiochip_add(chip); - if (status) + ret = of_gpiochip_add(chip); + if (ret) goto err_remove_chip; - status = gpiochip_init_valid_mask(chip); - if (status) + ret = gpiochip_init_valid_mask(chip); + if (ret) goto err_remove_of_chip; for (i = 0; i < chip->ngpio; i++) { @@ -1407,8 +1407,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, * Otherwise, defer until later. */ if (gpiolib_initialized) { - status = gpiochip_setup_dev(gdev); - if (status) + ret = gpiochip_setup_dev(gdev); + if (ret) goto err_remove_acpi_chip; } return 0; @@ -1438,9 +1438,9 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, /* failures here can mean systems won't boot... */ pr_err("%s: GPIOs %d..%d (%s) failed to register, %d\n", __func__, gdev->base, gdev->base + gdev->ngpio - 1, - chip->label ? : "generic", status); + chip->label ? : "generic", ret); kfree(gdev); - return status; + return ret; } EXPORT_SYMBOL_GPL(gpiochip_add_data_with_key); @@ -2001,7 +2001,7 @@ int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq) { struct gpio_chip *chip = d->host_data; - int err = 0; + int ret = 0; if (!gpiochip_irqchip_irq_valid(chip, hwirq)) return -ENXIO; @@ -2019,12 +2019,12 @@ int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, irq_set_noprobe(irq); if (chip->irq.num_parents == 1) - err = irq_set_parent(irq, chip->irq.parents[0]); + ret = irq_set_parent(irq, chip->irq.parents[0]); else if (chip->irq.map) - err = irq_set_parent(irq, chip->irq.map[hwirq]); + ret = irq_set_parent(irq, chip->irq.map[hwirq]); - if (err < 0) - return err; + if (ret < 0) + return ret; /* * No set-up of the hardware will happen if IRQ_TYPE_NONE @@ -2611,7 +2611,7 @@ EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges); static int gpiod_request_commit(struct gpio_desc *desc, const char *label) { struct gpio_chip *chip = desc->gdev->chip; - int status; + int ret; unsigned long flags; unsigned offset; @@ -2629,10 +2629,10 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label) if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) { desc_set_label(desc, label ? : "?"); - status = 0; + ret = 0; } else { kfree_const(label); - status = -EBUSY; + ret = -EBUSY; goto done; } @@ -2641,12 +2641,12 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label) spin_unlock_irqrestore(&gpio_lock, flags); offset = gpio_chip_hwgpio(desc); if (gpiochip_line_is_valid(chip, offset)) - status = chip->request(chip, offset); + ret = chip->request(chip, offset); else - status = -EINVAL; + ret = -EINVAL; spin_lock_irqsave(&gpio_lock, flags); - if (status < 0) { + if (ret < 0) { desc_set_label(desc, NULL); kfree_const(label); clear_bit(FLAG_REQUESTED, &desc->flags); @@ -2661,7 +2661,7 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label) } done: spin_unlock_irqrestore(&gpio_lock, flags); - return status; + return ret; } /* @@ -2704,24 +2704,24 @@ static int validate_desc(const struct gpio_desc *desc, const char *func) int gpiod_request(struct gpio_desc *desc, const char *label) { - int status = -EPROBE_DEFER; + int ret = -EPROBE_DEFER; struct gpio_device *gdev; VALIDATE_DESC(desc); gdev = desc->gdev; if (try_module_get(gdev->owner)) { - status = gpiod_request_commit(desc, label); - if (status < 0) + ret = gpiod_request_commit(desc, label); + if (ret < 0) module_put(gdev->owner); else get_device(&gdev->dev); } - if (status) - gpiod_dbg(desc, "%s: status %d\n", __func__, status); + if (ret) + gpiod_dbg(desc, "%s: status %d\n", __func__, ret); - return status; + return ret; } static bool gpiod_free_commit(struct gpio_desc *desc) @@ -2823,22 +2823,22 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip, u16 hwnum, enum gpiod_flags dflags) { struct gpio_desc *desc = gpiochip_get_desc(chip, hwnum); - int err; + int ret; if (IS_ERR(desc)) { chip_err(chip, "failed to get GPIO descriptor\n"); return desc; } - err = gpiod_request_commit(desc, label); - if (err < 0) - return ERR_PTR(err); + ret = gpiod_request_commit(desc, label); + if (ret < 0) + return ERR_PTR(ret); - err = gpiod_configure_flags(desc, label, lflags, dflags); - if (err) { + ret = gpiod_configure_flags(desc, label, lflags, dflags); + if (ret) { chip_err(chip, "setup of own GPIO %s failed\n", label); gpiod_free_commit(desc); - return ERR_PTR(err); + return ERR_PTR(ret); } return desc; @@ -2901,7 +2901,7 @@ static int gpio_set_config(struct gpio_chip *gc, unsigned offset, int gpiod_direction_input(struct gpio_desc *desc) { struct gpio_chip *chip; - int status = 0; + int ret = 0; VALIDATE_DESC(desc); chip = desc->gdev->chip; @@ -2925,7 +2925,7 @@ int gpiod_direction_input(struct gpio_desc *desc) * assume we are in input mode after this. */ if (chip->direction_input) { - status = chip->direction_input(chip, gpio_chip_hwgpio(desc)); + ret = chip->direction_input(chip, gpio_chip_hwgpio(desc)); } else if (chip->get_direction && (chip->get_direction(chip, gpio_chip_hwgpio(desc)) != 1)) { gpiod_warn(desc, @@ -2933,7 +2933,7 @@ int gpiod_direction_input(struct gpio_desc *desc) __func__); return -EIO; } - if (status == 0) + if (ret == 0) clear_bit(FLAG_IS_OUT, &desc->flags); if (test_bit(FLAG_PULL_UP, &desc->flags)) @@ -2943,9 +2943,9 @@ int gpiod_direction_input(struct gpio_desc *desc) gpio_set_config(chip, gpio_chip_hwgpio(desc), PIN_CONFIG_BIAS_PULL_DOWN); - trace_gpio_direction(desc_to_gpio(desc), 1, status); + trace_gpio_direction(desc_to_gpio(desc), 1, ret); - return status; + return ret; } EXPORT_SYMBOL_GPL(gpiod_direction_input); @@ -3217,7 +3217,7 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, struct gpio_array *array_info, unsigned long *value_bitmap) { - int err, i = 0; + int ret, i = 0; /* * Validate array_info against desc_array and its size. @@ -3230,11 +3230,11 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, if (!can_sleep) WARN_ON(array_info->chip->can_sleep); - err = gpio_chip_get_multiple(array_info->chip, + ret = gpio_chip_get_multiple(array_info->chip, array_info->get_mask, value_bitmap); - if (err) - return err; + if (ret) + return ret; if (!raw && !bitmap_empty(array_info->invert_mask, array_size)) bitmap_xor(value_bitmap, value_bitmap, @@ -3422,24 +3422,24 @@ EXPORT_SYMBOL_GPL(gpiod_get_array_value); */ static void gpio_set_open_drain_value_commit(struct gpio_desc *desc, bool value) { - int err = 0; + int ret = 0; struct gpio_chip *chip = desc->gdev->chip; int offset = gpio_chip_hwgpio(desc); if (value) { - err = chip->direction_input(chip, offset); - if (!err) + ret = chip->direction_input(chip, offset); + if (!ret) clear_bit(FLAG_IS_OUT, &desc->flags); } else { - err = chip->direction_output(chip, offset, 0); - if (!err) + ret = chip->direction_output(chip, offset, 0); + if (!ret) set_bit(FLAG_IS_OUT, &desc->flags); } - trace_gpio_direction(desc_to_gpio(desc), value, err); - if (err < 0) + trace_gpio_direction(desc_to_gpio(desc), value, ret); + if (ret < 0) gpiod_err(desc, "%s: Error in set_value for open drain err %d\n", - __func__, err); + __func__, ret); } /* @@ -3449,24 +3449,24 @@ static void gpio_set_open_drain_value_commit(struct gpio_desc *desc, bool value) */ static void gpio_set_open_source_value_commit(struct gpio_desc *desc, bool value) { - int err = 0; + int ret = 0; struct gpio_chip *chip = desc->gdev->chip; int offset = gpio_chip_hwgpio(desc); if (value) { - err = chip->direction_output(chip, offset, 1); - if (!err) + ret = chip->direction_output(chip, offset, 1); + if (!ret) set_bit(FLAG_IS_OUT, &desc->flags); } else { - err = chip->direction_input(chip, offset); - if (!err) + ret = chip->direction_input(chip, offset); + if (!ret) clear_bit(FLAG_IS_OUT, &desc->flags); } - trace_gpio_direction(desc_to_gpio(desc), !value, err); - if (err < 0) + trace_gpio_direction(desc_to_gpio(desc), !value, ret); + if (ret < 0) gpiod_err(desc, "%s: Error in set_value for open source err %d\n", - __func__, err); + __func__, ret); } static void gpiod_set_raw_value_commit(struct gpio_desc *desc, bool value) @@ -4377,7 +4377,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_optional); int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id, unsigned long lflags, enum gpiod_flags dflags) { - int status; + int ret; if (lflags & GPIO_ACTIVE_LOW) set_bit(FLAG_ACTIVE_LOW, &desc->flags); @@ -4410,9 +4410,9 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id, else if (lflags & GPIO_PULL_DOWN) set_bit(FLAG_PULL_DOWN, &desc->flags); - status = gpiod_set_transitory(desc, (lflags & GPIO_TRANSITORY)); - if (status < 0) - return status; + ret = gpiod_set_transitory(desc, (lflags & GPIO_TRANSITORY)); + if (ret < 0) + return ret; /* No particular flag request, return here... */ if (!(dflags & GPIOD_FLAGS_BIT_DIR_SET)) { @@ -4422,12 +4422,12 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id, /* Process flags */ if (dflags & GPIOD_FLAGS_BIT_DIR_OUT) - status = gpiod_direction_output(desc, + ret = gpiod_direction_output(desc, !!(dflags & GPIOD_FLAGS_BIT_DIR_VAL)); else - status = gpiod_direction_input(desc); + ret = gpiod_direction_input(desc); - return status; + return ret; } /** @@ -4451,7 +4451,7 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, { unsigned long lookupflags = GPIO_LOOKUP_FLAGS_DEFAULT; struct gpio_desc *desc = NULL; - int status; + int ret; /* Maybe we have a device name, maybe not */ const char *devname = dev ? dev_name(dev) : "?"; @@ -4486,9 +4486,9 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, * If a connection label was passed use that, else attempt to use * the device name as label */ - status = gpiod_request(desc, con_id ? con_id : devname); - if (status < 0) { - if (status == -EBUSY && flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) { + ret = gpiod_request(desc, con_id ? con_id : devname); + if (ret < 0) { + if (ret == -EBUSY && flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) { /* * This happens when there are several consumers for * the same GPIO line: we just return here without @@ -4501,15 +4501,15 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, con_id ? con_id : devname); return desc; } else { - return ERR_PTR(status); + return ERR_PTR(ret); } } - status = gpiod_configure_flags(desc, con_id, lookupflags, flags); - if (status < 0) { + ret = gpiod_configure_flags(desc, con_id, lookupflags, flags); + if (ret < 0) { dev_dbg(dev, "setup of GPIO %s failed\n", con_id); gpiod_put(desc); - return ERR_PTR(status); + return ERR_PTR(ret); } return desc; @@ -4624,7 +4624,7 @@ int gpiod_hog(struct gpio_desc *desc, const char *name, struct gpio_chip *chip; struct gpio_desc *local_desc; int hwnum; - int status; + int ret; chip = gpiod_to_chip(desc); hwnum = gpio_chip_hwgpio(desc); @@ -4632,10 +4632,10 @@ int gpiod_hog(struct gpio_desc *desc, const char *name, local_desc = gpiochip_request_own_desc(chip, hwnum, name, lflags, dflags); if (IS_ERR(local_desc)) { - status = PTR_ERR(local_desc); + ret = PTR_ERR(local_desc); pr_err("requesting hog GPIO %s (chip %s, offset %d) failed, %d\n", - name, chip->label, hwnum, status); - return status; + name, chip->label, hwnum, ret); + return ret; } /* Mark GPIO as hogged so it can be identified and removed later */ From f0d1ab0526408c28f40836254a5e7be794074b6d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 16 Jul 2019 13:58:54 +0200 Subject: [PATCH 65/82] gpio: of: Normalize return code variable name It is confusing to name return variables mixedly "status", "err" or "ret". I just changed them all to "ret", by personal preference, to lower cognitive stress. Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20190716115854.12098-1-linus.walleij@linaro.org --- drivers/gpio/gpiolib-of.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index e39b4290b80c..28233d3772f4 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -848,7 +848,7 @@ static int of_gpiochip_add_pin_range(struct gpio_chip *chip) { return 0; } int of_gpiochip_add(struct gpio_chip *chip) { - int status; + int ret; if (!chip->of_node) return 0; @@ -863,9 +863,9 @@ int of_gpiochip_add(struct gpio_chip *chip) of_gpiochip_init_valid_mask(chip); - status = of_gpiochip_add_pin_range(chip); - if (status) - return status; + ret = of_gpiochip_add_pin_range(chip); + if (ret) + return ret; /* If the chip defines names itself, these take precedence */ if (!chip->names) @@ -874,13 +874,13 @@ int of_gpiochip_add(struct gpio_chip *chip) of_node_get(chip->of_node); - status = of_gpiochip_scan_gpios(chip); - if (status) { + ret = of_gpiochip_scan_gpios(chip); + if (ret) { of_node_put(chip->of_node); gpiochip_remove_pin_ranges(chip); } - return status; + return ret; } void of_gpiochip_remove(struct gpio_chip *chip) From ae0755b56da9db4190288155ea884331993ed51b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 5 Sep 2019 11:20:25 +0200 Subject: [PATCH 66/82] gpio: Fix up merge collision in include file The merge of two different patch sets cleaning around in the main driver include file collided making the function declarations for gpiochip_[un]lock_as_irq() be defined twice when gpiolib was unselected. Fix it up. Cc: YueHaibing Cc: Masahiro Yamada Reported-by: kbuild test robot Signed-off-by: Linus Walleij --- include/linux/gpio/driver.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index b74a3bee85e5..c667ad0c099d 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -702,11 +702,12 @@ void gpiochip_free_own_desc(struct gpio_desc *desc); void devprop_gpiochip_set_names(struct gpio_chip *chip, const struct fwnode_handle *fwnode); +#ifdef CONFIG_GPIOLIB + /* lock/unlock as IRQ */ int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset); void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset); -#ifdef CONFIG_GPIOLIB struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc); From fbdf8d4bef4917713e7ec2fc006041a2b449605a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 6 Sep 2019 12:05:35 +0200 Subject: [PATCH 67/82] gpio: Fix further merge errors The previous merge of v5.3-rc7 was struggle enough, now it gave rise to new errors and now I fix those too. Fixes: 151a41014bff ("Merge tag 'v5.3-rc7' into devel") Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5b351f87c50a..56d0898d94aa 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1399,12 +1399,12 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, machine_gpiochip_add(chip); - status = gpiochip_irqchip_init_valid_mask(chip); - if (status) + ret = gpiochip_irqchip_init_valid_mask(chip); + if (ret) goto err_remove_acpi_chip; - status = gpiochip_add_irqchip(chip, lock_key, request_key); - if (status) + ret = gpiochip_add_irqchip(chip, lock_key, request_key); + if (ret) goto err_remove_irqchip_mask; /* From 4f78d91c722345de94a3c72da49b9d0d49cb76b8 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 4 Sep 2019 10:26:24 -0700 Subject: [PATCH 68/82] gpiolib: acpi: make acpi_can_fallback_to_crs() static It is not used outside gpiolib-acpi.c module, so there is no need to export it. Signed-off-by: Dmitry Torokhov Link: https://lore.kernel.org/r/20190904172624.GA76617@dtor-ws Reviewed-by: Andy Shevchenko Acked-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 19 ++++++++++--------- drivers/gpio/gpiolib-acpi.h | 8 -------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index fdee8afa5339..2b6fdc9947f7 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -728,6 +728,16 @@ static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, return ret ? ERR_PTR(ret) : lookup.desc; } +static bool acpi_can_fallback_to_crs(struct acpi_device *adev, + const char *con_id) +{ + /* Never allow fallback if the device has properties */ + if (acpi_dev_has_props(adev) || adev->driver_gpios) + return false; + + return con_id == NULL; +} + struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id, unsigned int idx, @@ -1264,15 +1274,6 @@ int acpi_gpio_count(struct device *dev, const char *con_id) return count ? count : -ENOENT; } -bool acpi_can_fallback_to_crs(struct acpi_device *adev, const char *con_id) -{ - /* Never allow fallback if the device has properties */ - if (acpi_dev_has_props(adev) || adev->driver_gpios) - return false; - - return con_id == NULL; -} - /* Run deferred acpi_gpiochip_request_irqs() */ static int acpi_gpio_handle_deferred_request_irqs(void) { diff --git a/drivers/gpio/gpiolib-acpi.h b/drivers/gpio/gpiolib-acpi.h index d7241b432b8b..1c6d65cf0629 100644 --- a/drivers/gpio/gpiolib-acpi.h +++ b/drivers/gpio/gpiolib-acpi.h @@ -52,8 +52,6 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, struct acpi_gpio_info *info); int acpi_gpio_count(struct device *dev, const char *con_id); - -bool acpi_can_fallback_to_crs(struct acpi_device *adev, const char *con_id); #else static inline void acpi_gpiochip_add(struct gpio_chip *chip) { } static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { } @@ -93,12 +91,6 @@ static inline int acpi_gpio_count(struct device *dev, const char *con_id) { return -ENODEV; } - -static inline bool acpi_can_fallback_to_crs(struct acpi_device *adev, - const char *con_id) -{ - return false; -} #endif #endif /* GPIOLIB_ACPI_H */ From 5fbe5b5883f847363ff1b7280e8b1d2980526b8e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 4 Sep 2019 16:01:04 +0200 Subject: [PATCH 69/82] gpio: Initialize the irqchip valid_mask with a callback After changing the valid_mask for the struct gpio_chip to detect the need and presence of a valid mask with the presence of a .init_valid_mask() callback to fill it in, we augment the gpio_irq_chip to use the same logic. Switch all driver using the gpio_irq_chio valid_mask over to this new method. This makes sure the valid_mask for the gpio_irq_chip gets filled in when we add the gpio_chip, which makes it a little easier to switch over drivers using the old way of setting up gpio_irq_chip over to the new method of passing the gpio_irq_chip along with the gpio_chip. (See drivers/gpio/TODO for details.) Cc: Joel Stanley Cc: Thierry Reding Signed-off-by: Linus Walleij Reviewed-by: Andy Shevchenko Tested-by: Hans de Goede Reviewed-by: Andrew Jeffery Acked-by: Mika Westerberg Reviewed-by: Andrew Lunn Reviewed-by: Patrice Chotard Link: https://lore.kernel.org/r/20190904140104.32426-1-linus.walleij@linaro.org --- drivers/gpio/gpio-aspeed.c | 13 ++++--- drivers/gpio/gpio-stmpe.c | 36 +++++++++++++------ drivers/gpio/gpio-tqmx86.c | 21 ++++++----- drivers/gpio/gpiolib.c | 12 ++++--- drivers/pinctrl/intel/pinctrl-baytrail.c | 16 ++++++++- drivers/pinctrl/intel/pinctrl-cherryview.c | 42 +++++++++++++--------- drivers/platform/x86/intel_int0002_vgpio.c | 11 ++++-- include/linux/gpio/driver.h | 14 +++++--- 8 files changed, 111 insertions(+), 54 deletions(-) diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index 9defe25d4721..7bcd83dbc3e3 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -689,8 +689,11 @@ static struct irq_chip aspeed_gpio_irqchip = { .irq_set_type = aspeed_gpio_set_type, }; -static void set_irq_valid_mask(struct aspeed_gpio *gpio) +static void aspeed_init_irq_valid_mask(struct gpio_chip *gc, + unsigned long *valid_mask, + unsigned int ngpios) { + struct aspeed_gpio *gpio = gpiochip_get_data(gc); const struct aspeed_bank_props *props = gpio->config->props; while (!is_bank_props_sentinel(props)) { @@ -704,7 +707,7 @@ static void set_irq_valid_mask(struct aspeed_gpio *gpio) if (i >= gpio->config->nr_gpios) break; - clear_bit(i, gpio->chip.irq.valid_mask); + clear_bit(i, valid_mask); } props++; @@ -1203,7 +1206,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) girq->parents[0] = gpio->irq; girq->default_type = IRQ_TYPE_NONE; girq->handler = handle_bad_irq; - girq->need_valid_mask = true; + girq->init_valid_mask = aspeed_init_irq_valid_mask; } gpio->offset_timer = @@ -1215,10 +1218,6 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) if (rc < 0) return rc; - /* Now the valid mask is allocated */ - if (gpio->irq) - set_irq_valid_mask(gpio); - return 0; } diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index dbf9cbe36b2b..994d542daf53 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c @@ -429,6 +429,23 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev) return IRQ_HANDLED; } +static void stmpe_init_irq_valid_mask(struct gpio_chip *gc, + unsigned long *valid_mask, + unsigned int ngpios) +{ + struct stmpe_gpio *stmpe_gpio = gpiochip_get_data(gc); + int i; + + if (!stmpe_gpio->norequest_mask) + return; + + /* Forbid unused lines to be mapped as IRQs */ + for (i = 0; i < sizeof(u32); i++) { + if (stmpe_gpio->norequest_mask & BIT(i)) + clear_bit(i, valid_mask); + } +} + static int stmpe_gpio_probe(struct platform_device *pdev) { struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); @@ -454,14 +471,21 @@ static int stmpe_gpio_probe(struct platform_device *pdev) stmpe_gpio->chip.parent = &pdev->dev; stmpe_gpio->chip.of_node = np; stmpe_gpio->chip.base = -1; + /* + * REVISIT: this makes sure the valid mask gets allocated and + * filled in when adding the gpio_chip, but the rest of the + * gpio_irqchip is still filled in using the old method + * in gpiochip_irqchip_add_nested() so clean this up once we + * get the gpio_irqchip to initialize while adding the + * gpio_chip also for threaded irqchips. + */ + stmpe_gpio->chip.irq.init_valid_mask = stmpe_init_irq_valid_mask; if (IS_ENABLED(CONFIG_DEBUG_FS)) stmpe_gpio->chip.dbg_show = stmpe_dbg_show; of_property_read_u32(np, "st,norequest-mask", &stmpe_gpio->norequest_mask); - if (stmpe_gpio->norequest_mask) - stmpe_gpio->chip.irq.need_valid_mask = true; irq = platform_get_irq(pdev, 0); if (irq < 0) @@ -487,14 +511,6 @@ static int stmpe_gpio_probe(struct platform_device *pdev) dev_err(&pdev->dev, "unable to get irq: %d\n", ret); goto out_disable; } - if (stmpe_gpio->norequest_mask) { - int i; - - /* Forbid unused lines to be mapped as IRQs */ - for (i = 0; i < sizeof(u32); i++) - if (stmpe_gpio->norequest_mask & BIT(i)) - clear_bit(i, stmpe_gpio->chip.irq.valid_mask); - } ret = gpiochip_irqchip_add_nested(&stmpe_gpio->chip, &stmpe_gpio_irq_chip, 0, diff --git a/drivers/gpio/gpio-tqmx86.c b/drivers/gpio/gpio-tqmx86.c index 07050cdbadb9..a3109bcaa0ac 100644 --- a/drivers/gpio/gpio-tqmx86.c +++ b/drivers/gpio/gpio-tqmx86.c @@ -214,6 +214,17 @@ static const struct dev_pm_ops tqmx86_gpio_dev_pm_ops = { tqmx86_gpio_runtime_resume, NULL) }; +static void tqmx86_init_irq_valid_mask(struct gpio_chip *chip, + unsigned long *valid_mask, + unsigned int ngpios) +{ + /* Only GPIOs 4-7 are valid for interrupts. Clear the others */ + clear_bit(0, valid_mask); + clear_bit(1, valid_mask); + clear_bit(2, valid_mask); + clear_bit(3, valid_mask); +} + static int tqmx86_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -260,7 +271,6 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) chip->get = tqmx86_gpio_get; chip->set = tqmx86_gpio_set; chip->ngpio = TQMX86_NGPIO; - chip->irq.need_valid_mask = true; chip->parent = pdev->dev.parent; pm_runtime_enable(&pdev->dev); @@ -296,6 +306,7 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) girq->parents[0] = irq; girq->default_type = IRQ_TYPE_NONE; girq->handler = handle_simple_irq; + girq->init_valid_mask = tqmx86_init_irq_valid_mask; } ret = devm_gpiochip_add_data(dev, chip, gpio); @@ -304,14 +315,6 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) goto out_pm_dis; } - /* Only GPIOs 4-7 are valid for interrupts. Clear the others */ - if (irq) { - clear_bit(0, girq->valid_mask); - clear_bit(1, girq->valid_mask); - clear_bit(2, girq->valid_mask); - clear_bit(3, girq->valid_mask); - } - dev_info(dev, "GPIO functionality initialized with %d pins\n", chip->ngpio); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 56d0898d94aa..f5b2649e2893 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1615,15 +1615,19 @@ static struct gpio_chip *find_chip_by_name(const char *name) * The following is irqchip helper code for gpiochips. */ -static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip) +static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gc) { - if (!gpiochip->irq.need_valid_mask) + struct gpio_irq_chip *girq = &gc->irq; + + if (!girq->init_valid_mask) return 0; - gpiochip->irq.valid_mask = gpiochip_allocate_mask(gpiochip); - if (!gpiochip->irq.valid_mask) + girq->valid_mask = gpiochip_allocate_mask(gc); + if (!girq->valid_mask) return -ENOMEM; + girq->init_valid_mask(gc, girq->valid_mask, gc->ngpio); + return 0; } diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index e5a112a8e067..297b7b5fcb28 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -1455,6 +1455,20 @@ static void byt_gpio_irq_handler(struct irq_desc *desc) chip->irq_eoi(data); } +static void byt_init_irq_valid_mask(struct gpio_chip *chip, + unsigned long *valid_mask, + unsigned int ngpios) +{ + /* + * FIXME: currently the valid_mask is filled in as part of + * initializing the irq_chip below in byt_gpio_irq_init_hw(). + * when converting this driver to the new way of passing the + * gpio_irq_chip along when adding the gpio_chip, move the + * mask initialization into this callback instead. Right now + * this callback is here to make sure the mask gets allocated. + */ +} + static void byt_gpio_irq_init_hw(struct byt_gpio *vg) { struct gpio_chip *gc = &vg->chip; @@ -1525,7 +1539,7 @@ static int byt_gpio_probe(struct byt_gpio *vg) gc->can_sleep = false; gc->parent = &vg->pdev->dev; gc->ngpio = vg->soc_data->npins; - gc->irq.need_valid_mask = true; + gc->irq.init_valid_mask = byt_init_irq_valid_mask; #ifdef CONFIG_PM_SLEEP vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio, diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 03ec7a5d9d0b..ab681d1a3a74 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -1543,6 +1543,30 @@ static const struct dmi_system_id chv_no_valid_mask[] = { {} }; +static void chv_init_irq_valid_mask(struct gpio_chip *chip, + unsigned long *valid_mask, + unsigned int ngpios) +{ + struct chv_pinctrl *pctrl = gpiochip_get_data(chip); + const struct chv_community *community = pctrl->community; + int i; + + /* Do not add GPIOs that can only generate GPEs to the IRQ domain */ + for (i = 0; i < community->npins; i++) { + const struct pinctrl_pin_desc *desc; + u32 intsel; + + desc = &community->pins[i]; + + intsel = readl(chv_padreg(pctrl, desc->number, CHV_PADCTRL0)); + intsel &= CHV_PADCTRL0_INTSEL_MASK; + intsel >>= CHV_PADCTRL0_INTSEL_SHIFT; + + if (intsel >= community->nirqs) + clear_bit(i, valid_mask); + } +} + static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq) { const struct chv_gpio_pinrange *range; @@ -1557,7 +1581,8 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq) chip->label = dev_name(pctrl->dev); chip->parent = pctrl->dev; chip->base = -1; - chip->irq.need_valid_mask = need_valid_mask; + if (need_valid_mask) + chip->irq.init_valid_mask = chv_init_irq_valid_mask; ret = devm_gpiochip_add_data(pctrl->dev, chip, pctrl); if (ret) { @@ -1576,21 +1601,6 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq) } } - /* Do not add GPIOs that can only generate GPEs to the IRQ domain */ - for (i = 0; i < community->npins; i++) { - const struct pinctrl_pin_desc *desc; - u32 intsel; - - desc = &community->pins[i]; - - intsel = readl(chv_padreg(pctrl, desc->number, CHV_PADCTRL0)); - intsel &= CHV_PADCTRL0_INTSEL_MASK; - intsel >>= CHV_PADCTRL0_INTSEL_SHIFT; - - if (need_valid_mask && intsel >= community->nirqs) - clear_bit(i, chip->irq.valid_mask); - } - /* * The same set of machines in chv_no_valid_mask[] have incorrectly * configured GPIOs that generate spurious interrupts so we use diff --git a/drivers/platform/x86/intel_int0002_vgpio.c b/drivers/platform/x86/intel_int0002_vgpio.c index d9542c661ddc..f57bbbeb2495 100644 --- a/drivers/platform/x86/intel_int0002_vgpio.c +++ b/drivers/platform/x86/intel_int0002_vgpio.c @@ -152,6 +152,13 @@ static const struct x86_cpu_id int0002_cpu_ids[] = { {} }; +static void int0002_init_irq_valid_mask(struct gpio_chip *chip, + unsigned long *valid_mask, + unsigned int ngpios) +{ + bitmap_clear(valid_mask, 0, GPE0A_PME_B0_VIRT_GPIO_PIN); +} + static int int0002_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -184,7 +191,7 @@ static int int0002_probe(struct platform_device *pdev) chip->direction_output = int0002_gpio_direction_output; chip->base = -1; chip->ngpio = GPE0A_PME_B0_VIRT_GPIO_PIN + 1; - chip->irq.need_valid_mask = true; + chip->irq.init_valid_mask = int0002_init_irq_valid_mask; ret = devm_gpiochip_add_data(&pdev->dev, chip, NULL); if (ret) { @@ -192,8 +199,6 @@ static int int0002_probe(struct platform_device *pdev) return ret; } - bitmap_clear(chip->irq.valid_mask, 0, GPE0A_PME_B0_VIRT_GPIO_PIN); - /* * We manually request the irq here instead of passing a flow-handler * to gpiochip_set_chained_irqchip, because the irq is shared. diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index c667ad0c099d..f8245d67f070 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -202,11 +202,17 @@ struct gpio_irq_chip { bool threaded; /** - * @need_valid_mask: - * - * If set core allocates @valid_mask with all bits set to one. + * @init_valid_mask: optional routine to initialize @valid_mask, to be + * used if not all GPIO lines are valid interrupts. Sometimes some + * lines just cannot fire interrupts, and this routine, when defined, + * is passed a bitmap in "valid_mask" and it will have ngpios + * bits from 0..(ngpios-1) set to "1" as in valid. The callback can + * then directly set some bits to "0" if they cannot be used for + * interrupts. */ - bool need_valid_mask; + void (*init_valid_mask)(struct gpio_chip *chip, + unsigned long *valid_mask, + unsigned int ngpios); /** * @valid_mask: From da04c425e9f738d7d143f509d519e1eaa4b5c2d6 Mon Sep 17 00:00:00 2001 From: Rashmica Gupta Date: Fri, 6 Sep 2019 16:25:47 +1000 Subject: [PATCH 70/82] gpio: aspeed: Update documentation with ast2600 controllers The ast2600 is a new generation of SoC from ASPEED. Similarly to the ast2400 and ast2500, it has a GPIO controller for it's 3.3V GPIO pins. Additionally, it has a GPIO controller for 36 1.8V GPIO pins. We use the ngpio property to differentiate between these controllers. Signed-off-by: Rashmica Gupta Link: https://lore.kernel.org/r/20190906062547.13264-1-rashmica.g@gmail.com Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/gpio/gpio-aspeed.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt b/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt index 7e9b586770b0..b2033fc3a71a 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-aspeed.txt @@ -2,7 +2,8 @@ Aspeed GPIO controller Device Tree Bindings ------------------------------------------- Required properties: -- compatible : Either "aspeed,ast2400-gpio" or "aspeed,ast2500-gpio" +- compatible : Either "aspeed,ast2400-gpio", "aspeed,ast2500-gpio", + or "aspeed,ast2600-gpio". - #gpio-cells : Should be two - First cell is the GPIO line number @@ -17,7 +18,9 @@ Required properties: Optional properties: -- clocks : A phandle to the clock to use for debounce timings +- clocks : A phandle to the clock to use for debounce timings +- ngpios : Number of GPIOs controlled by this controller. Should be set + when there are multiple GPIO controllers on a SoC (ast2600). The gpio and interrupt properties are further described in their respective bindings documentation: From 3c4710ae6f883f9c6e3df5e27e274702a1221c57 Mon Sep 17 00:00:00 2001 From: Rashmica Gupta Date: Fri, 6 Sep 2019 16:26:22 +1000 Subject: [PATCH 71/82] gpio/aspeed: Fix incorrect number of banks The current calculation for the number of GPIO banks is only correct if the number of GPIOs is a multiple of 32 (if there were 31 GPIOs we would currently say there are 0 banks, which is incorrect). Fixes: 361b79119a4b7 ('gpio: Add Aspeed driver') Signed-off-by: Rashmica Gupta Reviewed-by: Andrew Jeffery Link: https://lore.kernel.org/r/20190906062623.13354-1-rashmica.g@gmail.com Reviewed-by: Joel Stanley Signed-off-by: Linus Walleij --- drivers/gpio/gpio-aspeed.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index 7bcd83dbc3e3..854ed3bc66a7 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -1168,7 +1168,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) gpio->chip.base = -1; /* Allocate a cache of the output registers */ - banks = gpio->config->nr_gpios >> 5; + banks = DIV_ROUND_UP(gpio->config->nr_gpios, 32); gpio->dcache = devm_kcalloc(&pdev->dev, banks, sizeof(u32), GFP_KERNEL); if (!gpio->dcache) From 3d64a5a742ac95f2e6384605ea2825aa1c17e575 Mon Sep 17 00:00:00 2001 From: Rashmica Gupta Date: Fri, 6 Sep 2019 16:26:44 +1000 Subject: [PATCH 72/82] gpio: aspeed: Setup irqchip dynamically This is in preparation for adding ast2600 support. The ast2600 SoC requires two instances of the GPIO driver as it has two GPIO controllers. Each instance needs it's own irqchip. Signed-off-by: Rashmica Gupta Link: https://lore.kernel.org/r/20190906062644.13445-1-rashmica.g@gmail.com Reviewed-by: Joel Stanley Signed-off-by: Linus Walleij --- drivers/gpio/gpio-aspeed.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index 854ed3bc66a7..0da4cc786b99 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -52,6 +52,7 @@ struct aspeed_gpio_config { */ struct aspeed_gpio { struct gpio_chip chip; + struct irq_chip irqc; spinlock_t lock; void __iomem *base; int irq; @@ -681,14 +682,6 @@ static void aspeed_gpio_irq_handler(struct irq_desc *desc) chained_irq_exit(ic, desc); } -static struct irq_chip aspeed_gpio_irqchip = { - .name = "aspeed-gpio", - .irq_ack = aspeed_gpio_irq_ack, - .irq_mask = aspeed_gpio_irq_mask, - .irq_unmask = aspeed_gpio_irq_unmask, - .irq_set_type = aspeed_gpio_set_type, -}; - static void aspeed_init_irq_valid_mask(struct gpio_chip *gc, unsigned long *valid_mask, unsigned int ngpios) @@ -1195,7 +1188,12 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) gpio->irq = rc; girq = &gpio->chip.irq; - girq->chip = &aspeed_gpio_irqchip; + girq->chip = &gpio->irqc; + girq->chip->name = dev_name(&pdev->dev); + girq->chip->irq_ack = aspeed_gpio_irq_ack; + girq->chip->irq_mask = aspeed_gpio_irq_mask; + girq->chip->irq_unmask = aspeed_gpio_irq_unmask; + girq->chip->irq_set_type = aspeed_gpio_set_type; girq->parent_handler = aspeed_gpio_irq_handler; girq->num_parents = 1; girq->parents = devm_kcalloc(&pdev->dev, 1, From be2a7e2d5d98d288f00af4e9e2ba829aab1ebaef Mon Sep 17 00:00:00 2001 From: Rashmica Gupta Date: Fri, 6 Sep 2019 16:27:26 +1000 Subject: [PATCH 73/82] gpio: aspeed: Use ngpio property from device tree if available Use the ngpio property from the device tree if it exists. If it doesn't then fallback to the hardcoded value in the config. This is in preparation for adding ast2600 support. The ast2600 SoC has two GPIO controllers and so requires two instances of the GPIO driver. We use the ngpio property to different between them as they have different numbers of GPIOs. Signed-off-by: Rashmica Gupta Link: https://lore.kernel.org/r/20190906062727.13521-1-rashmica.g@gmail.com Reviewed-by: Joel Stanley Signed-off-by: Linus Walleij --- drivers/gpio/gpio-aspeed.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index 0da4cc786b99..f6b26f9bd287 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -697,7 +697,7 @@ static void aspeed_init_irq_valid_mask(struct gpio_chip *gc, for_each_clear_bit(offset, &input, 32) { unsigned int i = props->bank * 32 + offset; - if (i >= gpio->config->nr_gpios) + if (i >= gpio->chip.ngpio) break; clear_bit(i, valid_mask); @@ -1010,10 +1010,10 @@ int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc, unsigned long flags; if (!gpio->cf_copro_bankmap) - gpio->cf_copro_bankmap = kzalloc(gpio->config->nr_gpios >> 3, GFP_KERNEL); + gpio->cf_copro_bankmap = kzalloc(gpio->chip.ngpio >> 3, GFP_KERNEL); if (!gpio->cf_copro_bankmap) return -ENOMEM; - if (offset < 0 || offset > gpio->config->nr_gpios) + if (offset < 0 || offset > gpio->chip.ngpio) return -EINVAL; bindex = offset >> 3; @@ -1058,7 +1058,7 @@ int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc) if (!gpio->cf_copro_bankmap) return -ENXIO; - if (offset < 0 || offset > gpio->config->nr_gpios) + if (offset < 0 || offset > gpio->chip.ngpio) return -EINVAL; bindex = offset >> 3; @@ -1122,7 +1122,8 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) { const struct of_device_id *gpio_id; struct aspeed_gpio *gpio; - int rc, i, banks; + int rc, i, banks, err; + u32 ngpio; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) @@ -1148,7 +1149,10 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) gpio->config = gpio_id->data; gpio->chip.parent = &pdev->dev; - gpio->chip.ngpio = gpio->config->nr_gpios; + err = of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpio); + gpio->chip.ngpio = (u16) ngpio; + if (err) + gpio->chip.ngpio = gpio->config->nr_gpios; gpio->chip.direction_input = aspeed_gpio_dir_in; gpio->chip.direction_output = aspeed_gpio_dir_out; gpio->chip.get_direction = aspeed_gpio_get_direction; @@ -1161,7 +1165,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) gpio->chip.base = -1; /* Allocate a cache of the output registers */ - banks = DIV_ROUND_UP(gpio->config->nr_gpios, 32); + banks = DIV_ROUND_UP(gpio->chip.ngpio, 32); gpio->dcache = devm_kcalloc(&pdev->dev, banks, sizeof(u32), GFP_KERNEL); if (!gpio->dcache) From ab4a85534c3ee67e9f54d3d5dda6e36072fbed89 Mon Sep 17 00:00:00 2001 From: Rashmica Gupta Date: Fri, 6 Sep 2019 16:37:37 +1000 Subject: [PATCH 74/82] gpio: aspeed: Add in ast2600 details to Aspeed driver The ast2600 is a new generation of SoC from ASPEED. Similarly to the ast2400 and ast2500, it has a GPIO controller for it's 3.3V GPIO pins. Additionally, it has a GPIO controller for 1.8V GPIO pins. As the register names for both controllers are the same and the 36 1.8V GPIOs and the first 36 of the 3.3V GPIOs are all bidirectional, we can use the same configuration struct and use the ngpio property to differentiate between the two sets of GPIOs. Signed-off-by: Rashmica Gupta Link: https://lore.kernel.org/r/20190906063737.15428-1-rashmica.g@gmail.com Signed-off-by: Linus Walleij --- drivers/gpio/gpio-aspeed.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index f6b26f9bd287..09e53c5f3b0a 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -662,12 +662,14 @@ static void aspeed_gpio_irq_handler(struct irq_desc *desc) struct gpio_chip *gc = irq_desc_get_handler_data(desc); struct irq_chip *ic = irq_desc_get_chip(desc); struct aspeed_gpio *data = gpiochip_get_data(gc); - unsigned int i, p, girq; + unsigned int i, p, girq, banks; unsigned long reg; + struct aspeed_gpio *gpio = gpiochip_get_data(gc); chained_irq_enter(ic, desc); - for (i = 0; i < ARRAY_SIZE(aspeed_gpio_banks); i++) { + banks = DIV_ROUND_UP(gpio->chip.ngpio, 32); + for (i = 0; i < banks; i++) { const struct aspeed_gpio_bank *bank = &aspeed_gpio_banks[i]; reg = ioread32(bank_reg(data, bank, reg_irq_status)); @@ -1111,9 +1113,25 @@ static const struct aspeed_gpio_config ast2500_config = /* 232 for simplicity, actual number is 228 (4-GPIO hole in GPIOAB) */ { .nr_gpios = 232, .props = ast2500_bank_props, }; +static const struct aspeed_bank_props ast2600_bank_props[] = { + /* input output */ + {5, 0xffffffff, 0x0000ffff}, /* U/V/W/X */ + {6, 0xffff0000, 0x0fff0000}, /* Y/Z */ + { }, +}; + +static const struct aspeed_gpio_config ast2600_config = + /* + * ast2600 has two controllers one with 208 GPIOs and one with 36 GPIOs. + * We expect ngpio being set in the device tree and this is a fallback + * option. + */ + { .nr_gpios = 208, .props = ast2600_bank_props, }; + static const struct of_device_id aspeed_gpio_of_table[] = { { .compatible = "aspeed,ast2400-gpio", .data = &ast2400_config, }, { .compatible = "aspeed,ast2500-gpio", .data = &ast2500_config, }, + { .compatible = "aspeed,ast2600-gpio", .data = &ast2600_config, }, {} }; MODULE_DEVICE_TABLE(of, aspeed_gpio_of_table); From c83d3c77332e264ec77ceced614fe9630c7bfaad Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 6 Sep 2019 10:45:36 +0200 Subject: [PATCH 75/82] gpio: of: Make of_get_named_gpiod_flags() private Since commit f626d6dfb7098525 ("gpio: of: Break out OF-only code"), there are no more users of of_get_named_gpiod_flags() outside gpiolib-of.c. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20190906084539.21838-2-geert+renesas@glider.be Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 2 +- drivers/gpio/gpiolib-of.h | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 5c38ede43c7a..142033574f70 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -223,7 +223,7 @@ static void of_gpio_flags_quirks(struct device_node *np, * value on the error condition. If @flags is not NULL the function also fills * in flags for the GPIO. */ -struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, +static struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, const char *propname, int index, enum of_gpio_flags *flags) { struct of_phandle_args gpiospec; diff --git a/drivers/gpio/gpiolib-of.h b/drivers/gpio/gpiolib-of.h index 454d1658ee2d..9768831b1fe2 100644 --- a/drivers/gpio/gpiolib-of.h +++ b/drivers/gpio/gpiolib-of.h @@ -11,8 +11,6 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, unsigned int idx, unsigned long *lookupflags); -struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, - const char *list_name, int index, enum of_gpio_flags *flags); int of_gpiochip_add(struct gpio_chip *gc); void of_gpiochip_remove(struct gpio_chip *gc); int of_gpio_get_count(struct device *dev, const char *con_id); @@ -25,11 +23,6 @@ static inline struct gpio_desc *of_find_gpio(struct device *dev, { return ERR_PTR(-ENOENT); } -static inline struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, - const char *list_name, int index, enum of_gpio_flags *flags) -{ - return ERR_PTR(-ENOENT); -} static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; } static inline void of_gpiochip_remove(struct gpio_chip *gc) { } static inline int of_gpio_get_count(struct device *dev, const char *con_id) From b0c7e73b51dcdc8980a245f89278815ce1837d06 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 6 Sep 2019 10:45:37 +0200 Subject: [PATCH 76/82] gpio: of: Make of_gpio_simple_xlate() private Since commit 9a95e8d25a140ba9 ("gpio: remove etraxfs driver"), there are no more users of of_gpio_simple_xlate() outside gpiolib-of.c. All GPIO drivers that need it now rely on of_gpiochip_add() setting it up as the default translate function. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20190906084539.21838-3-geert+renesas@glider.be Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 6 +++--- include/linux/of_gpio.h | 11 ----------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 142033574f70..add7e6f8819e 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -637,8 +637,9 @@ static int of_gpiochip_scan_gpios(struct gpio_chip *chip) * GPIO chips. This function performs only one sanity check: whether GPIO * is less than ngpios (that is specified in the gpio_chip). */ -int of_gpio_simple_xlate(struct gpio_chip *gc, - const struct of_phandle_args *gpiospec, u32 *flags) +static int of_gpio_simple_xlate(struct gpio_chip *gc, + const struct of_phandle_args *gpiospec, + u32 *flags) { /* * We're discouraging gpio_cells < 2, since that way you'll have to @@ -662,7 +663,6 @@ int of_gpio_simple_xlate(struct gpio_chip *gc, return gpiospec->args[0]; } -EXPORT_SYMBOL(of_gpio_simple_xlate); /** * of_mm_gpiochip_add_data - Add memory mapped GPIO chip (bank) diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h index f9737dea9d1f..16967390a3fe 100644 --- a/include/linux/of_gpio.h +++ b/include/linux/of_gpio.h @@ -61,10 +61,6 @@ static inline int of_mm_gpiochip_add(struct device_node *np, } extern void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc); -extern int of_gpio_simple_xlate(struct gpio_chip *gc, - const struct of_phandle_args *gpiospec, - u32 *flags); - #else /* CONFIG_OF_GPIO */ /* Drivers may not strictly depend on the GPIO support, so let them link. */ @@ -77,13 +73,6 @@ static inline int of_get_named_gpio_flags(struct device_node *np, return -ENOSYS; } -static inline int of_gpio_simple_xlate(struct gpio_chip *gc, - const struct of_phandle_args *gpiospec, - u32 *flags) -{ - return -ENOSYS; -} - #endif /* CONFIG_OF_GPIO */ /** From 6d6624554da4a623fd047d15790157a0572ab091 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 6 Sep 2019 10:45:38 +0200 Subject: [PATCH 77/82] gpio: of: Switch to EXPORT_SYMBOL_GPL() All exported functions provide genuine Linux-specific functionality. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20190906084539.21838-4-geert+renesas@glider.be Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index add7e6f8819e..d5b98b48eb5d 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -274,7 +274,7 @@ int of_get_named_gpio_flags(struct device_node *np, const char *list_name, else return desc_to_gpio(desc); } -EXPORT_SYMBOL(of_get_named_gpio_flags); +EXPORT_SYMBOL_GPL(of_get_named_gpio_flags); /** * gpiod_get_from_of_node() - obtain a GPIO from an OF node @@ -343,7 +343,7 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, return desc; } -EXPORT_SYMBOL(gpiod_get_from_of_node); +EXPORT_SYMBOL_GPL(gpiod_get_from_of_node); /* * The SPI GPIO bindings happened before we managed to establish that GPIO @@ -719,7 +719,7 @@ int of_mm_gpiochip_add_data(struct device_node *np, pr_err("%pOF: GPIO chip registration failed with status %d\n", np, ret); return ret; } -EXPORT_SYMBOL(of_mm_gpiochip_add_data); +EXPORT_SYMBOL_GPL(of_mm_gpiochip_add_data); /** * of_mm_gpiochip_remove - Remove memory mapped GPIO chip (bank) @@ -736,7 +736,7 @@ void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc) iounmap(mm_gc->regs); kfree(gc->label); } -EXPORT_SYMBOL(of_mm_gpiochip_remove); +EXPORT_SYMBOL_GPL(of_mm_gpiochip_remove); static void of_gpiochip_init_valid_mask(struct gpio_chip *chip) { From ac57199180a041e8c66d20265b1a072ce3af4325 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 6 Sep 2019 10:45:39 +0200 Subject: [PATCH 78/82] gpio: devres: Switch to EXPORT_SYMBOL_GPL() Change all exported symbols for managed GPIO functions from EXPORT_SYMBOL() to EXPORT_SYMBOL_GPL(), like is used for their non-managed counterparts. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20190906084539.21838-5-geert+renesas@glider.be Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-devres.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/gpiolib-devres.c b/drivers/gpio/gpiolib-devres.c index 0acc2cc6e868..98e3c20d9730 100644 --- a/drivers/gpio/gpiolib-devres.c +++ b/drivers/gpio/gpiolib-devres.c @@ -59,7 +59,7 @@ struct gpio_desc *__must_check devm_gpiod_get(struct device *dev, { return devm_gpiod_get_index(dev, con_id, 0, flags); } -EXPORT_SYMBOL(devm_gpiod_get); +EXPORT_SYMBOL_GPL(devm_gpiod_get); /** * devm_gpiod_get_optional - Resource-managed gpiod_get_optional() @@ -77,7 +77,7 @@ struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev, { return devm_gpiod_get_index_optional(dev, con_id, 0, flags); } -EXPORT_SYMBOL(devm_gpiod_get_optional); +EXPORT_SYMBOL_GPL(devm_gpiod_get_optional); /** * devm_gpiod_get_index - Resource-managed gpiod_get_index() @@ -127,7 +127,7 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev, return desc; } -EXPORT_SYMBOL(devm_gpiod_get_index); +EXPORT_SYMBOL_GPL(devm_gpiod_get_index); /** * devm_gpiod_get_from_of_node() - obtain a GPIO from an OF node @@ -182,7 +182,7 @@ struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, return desc; } -EXPORT_SYMBOL(devm_gpiod_get_from_of_node); +EXPORT_SYMBOL_GPL(devm_gpiod_get_from_of_node); /** * devm_fwnode_get_index_gpiod_from_child - get a GPIO descriptor from a @@ -239,7 +239,7 @@ struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev, return desc; } -EXPORT_SYMBOL(devm_fwnode_get_index_gpiod_from_child); +EXPORT_SYMBOL_GPL(devm_fwnode_get_index_gpiod_from_child); /** * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional() @@ -268,7 +268,7 @@ struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev, return desc; } -EXPORT_SYMBOL(devm_gpiod_get_index_optional); +EXPORT_SYMBOL_GPL(devm_gpiod_get_index_optional); /** * devm_gpiod_get_array - Resource-managed gpiod_get_array() @@ -303,7 +303,7 @@ struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev, return descs; } -EXPORT_SYMBOL(devm_gpiod_get_array); +EXPORT_SYMBOL_GPL(devm_gpiod_get_array); /** * devm_gpiod_get_array_optional - Resource-managed gpiod_get_array_optional() @@ -328,7 +328,7 @@ devm_gpiod_get_array_optional(struct device *dev, const char *con_id, return descs; } -EXPORT_SYMBOL(devm_gpiod_get_array_optional); +EXPORT_SYMBOL_GPL(devm_gpiod_get_array_optional); /** * devm_gpiod_put - Resource-managed gpiod_put() @@ -344,7 +344,7 @@ void devm_gpiod_put(struct device *dev, struct gpio_desc *desc) WARN_ON(devres_release(dev, devm_gpiod_release, devm_gpiod_match, &desc)); } -EXPORT_SYMBOL(devm_gpiod_put); +EXPORT_SYMBOL_GPL(devm_gpiod_put); /** * devm_gpiod_unhinge - Remove resource management from a gpio descriptor @@ -374,7 +374,7 @@ void devm_gpiod_unhinge(struct device *dev, struct gpio_desc *desc) /* Anything else we should warn about */ WARN_ON(ret); } -EXPORT_SYMBOL(devm_gpiod_unhinge); +EXPORT_SYMBOL_GPL(devm_gpiod_unhinge); /** * devm_gpiod_put_array - Resource-managed gpiod_put_array() @@ -390,7 +390,7 @@ void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs) WARN_ON(devres_release(dev, devm_gpiod_release_array, devm_gpiod_match_array, &descs)); } -EXPORT_SYMBOL(devm_gpiod_put_array); +EXPORT_SYMBOL_GPL(devm_gpiod_put_array); @@ -444,7 +444,7 @@ int devm_gpio_request(struct device *dev, unsigned gpio, const char *label) return 0; } -EXPORT_SYMBOL(devm_gpio_request); +EXPORT_SYMBOL_GPL(devm_gpio_request); /** * devm_gpio_request_one - request a single GPIO with initial setup @@ -474,7 +474,7 @@ int devm_gpio_request_one(struct device *dev, unsigned gpio, return 0; } -EXPORT_SYMBOL(devm_gpio_request_one); +EXPORT_SYMBOL_GPL(devm_gpio_request_one); /** * devm_gpio_free - free a GPIO @@ -492,4 +492,4 @@ void devm_gpio_free(struct device *dev, unsigned int gpio) WARN_ON(devres_release(dev, devm_gpio_release, devm_gpio_match, &gpio)); } -EXPORT_SYMBOL(devm_gpio_free); +EXPORT_SYMBOL_GPL(devm_gpio_free); From aba30f6f312ccb82b44eaf53db1047e023a97d5c Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 6 Sep 2019 21:10:32 +0800 Subject: [PATCH 79/82] gpio: creg-snps: use devm_platform_ioremap_resource() to simplify code Use devm_platform_ioremap_resource() to simplify the code a bit. This is detected by coccinelle. Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190906131032.22148-1-yuehaibing@huawei.com Acked-by: Eugeniy Paltsev Signed-off-by: Linus Walleij --- drivers/gpio/gpio-creg-snps.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-creg-snps.c b/drivers/gpio/gpio-creg-snps.c index 8cbc94d0d424..ff19a8ad5663 100644 --- a/drivers/gpio/gpio-creg-snps.c +++ b/drivers/gpio/gpio-creg-snps.c @@ -137,7 +137,6 @@ static int creg_gpio_probe(struct platform_device *pdev) const struct of_device_id *match; struct device *dev = &pdev->dev; struct creg_gpio *hcg; - struct resource *mem; u32 ngpios; int ret; @@ -145,8 +144,7 @@ static int creg_gpio_probe(struct platform_device *pdev) if (!hcg) return -ENOMEM; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hcg->regs = devm_ioremap_resource(dev, mem); + hcg->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(hcg->regs)) return PTR_ERR(hcg->regs); From 2efc6bfadb0b9c873e11ab8da37f4f69aa215d25 Mon Sep 17 00:00:00 2001 From: Saiyam Doshi Date: Sat, 7 Sep 2019 23:09:10 +0530 Subject: [PATCH 80/82] gpio: remove explicit comparison with 0 No need to compare return value with 0. In case of non-zero return value, the if condition will be true. This makes intent a bit more clear to the reader. "if (x) then", compared to "if (x is not zero) then". Signed-off-by: Saiyam Doshi Link: https://lore.kernel.org/r/20190907173910.GA9547@SD Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index f5b2649e2893..158e327a1285 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -851,7 +851,7 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p) } ret = kfifo_put(&le->events, ge); - if (ret != 0) + if (ret) wake_up_poll(&le->wait, EPOLLIN); return IRQ_HANDLED; From c34a024e4ee087b6d9e534160990082c3d9e7103 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 10 Sep 2019 16:15:29 +0200 Subject: [PATCH 81/82] gpio: htc-egpio: Remove unused exported htc_egpio_get_wakeup_irq() This function was never used upstream, and is a relic of the original handhelds.org code the htc-egpio driver was based on. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20190910141529.21030-1-geert+renesas@glider.be Signed-off-by: Linus Walleij --- drivers/gpio/gpio-htc-egpio.c | 14 -------------- include/linux/platform_data/gpio-htc-egpio.h | 3 --- 2 files changed, 17 deletions(-) diff --git a/drivers/gpio/gpio-htc-egpio.c b/drivers/gpio/gpio-htc-egpio.c index 9d3ac51a765c..6eb56f7ab9c9 100644 --- a/drivers/gpio/gpio-htc-egpio.c +++ b/drivers/gpio/gpio-htc-egpio.c @@ -118,20 +118,6 @@ static void egpio_handler(struct irq_desc *desc) } } -int htc_egpio_get_wakeup_irq(struct device *dev) -{ - struct egpio_info *ei = dev_get_drvdata(dev); - - /* Read current pins. */ - u16 readval = egpio_readw(ei, ei->ack_register); - /* Ack/unmask interrupts. */ - ack_irqs(ei); - /* Return first set pin. */ - readval &= ei->irqs_enabled; - return ei->irq_start + ffs(readval) - 1; -} -EXPORT_SYMBOL(htc_egpio_get_wakeup_irq); - static inline int egpio_pos(struct egpio_info *ei, int bit) { return bit >> ei->reg_shift; diff --git a/include/linux/platform_data/gpio-htc-egpio.h b/include/linux/platform_data/gpio-htc-egpio.h index 9a3e78082883..eaefba0b6465 100644 --- a/include/linux/platform_data/gpio-htc-egpio.h +++ b/include/linux/platform_data/gpio-htc-egpio.h @@ -50,7 +50,4 @@ struct htc_egpio_platform_data { int num_chips; }; -/* Determine the wakeup irq, to be called during early resume */ -extern int htc_egpio_get_wakeup_irq(struct device *dev); - #endif From 11c43bb022b373d2fdb84950ebf1911362f3f010 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 11 Sep 2019 00:52:05 -0700 Subject: [PATCH 82/82] gpiolib: of: add a fallback for wlf,reset GPIO name The old Arizona binding did not use -gpio or -gpios suffix, so devm_gpiod_get() does not work for it. As it is the one of a few users of devm_gpiod_get_from_of_node() API that I want to remove, I'd rather have a small quirk in the gpiolib OF handler, and switch Arizona driver to devm_gpiod_get(). Signed-off-by: Dmitry Torokhov Link: https://lore.kernel.org/r/20190911075215.78047-2-dmitry.torokhov@gmail.com Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index d5b98b48eb5d..3b18240acb0a 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -438,6 +438,19 @@ static struct gpio_desc *of_find_regulator_gpio(struct device *dev, const char * return desc; } +static struct gpio_desc *of_find_arizona_gpio(struct device *dev, + const char *con_id, + enum of_gpio_flags *of_flags) +{ + if (!IS_ENABLED(CONFIG_MFD_ARIZONA)) + return ERR_PTR(-ENOENT); + + if (!con_id || strcmp(con_id, "wlf,reset")) + return ERR_PTR(-ENOENT); + + return of_get_named_gpiod_flags(dev->of_node, con_id, 0, of_flags); +} + struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, unsigned int idx, unsigned long *flags) { @@ -488,6 +501,9 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, if (IS_ERR(desc) && PTR_ERR(desc) != -EPROBE_DEFER) desc = of_find_regulator_gpio(dev, con_id, &of_flags); + if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) + desc = of_find_arizona_gpio(dev, con_id, &of_flags); + if (IS_ERR(desc)) return desc;