From f314af5de980064e0caa1ef8e3187a557e215abd Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 15 Apr 2020 17:15:32 +0300 Subject: [PATCH 1/4] gpio: dwapb: Split out dwapb_get_irq() helper [Upstream commit 4c2b54f73aba9c8428c1c8025f91d69ca77e1e6e] Split out dwapb_get_irq() helper for better readability and maintenance. Signed-off-by: Andy Shevchenko Tested-by: Serge Semin Reviewed-by: Serge Semin Link: https://lore.kernel.org/r/20200415141534.31240-13-andriy.shevchenko@linux.intel.com Signed-off-by: Linus Walleij Signed-off-by: huwentao --- drivers/gpio/gpio-dwapb.c | 56 ++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index ed6061b5cca1..26af7360d019 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -564,14 +564,38 @@ static void dwapb_gpio_unregister(struct dwapb_gpio *gpio) } } -static struct dwapb_platform_data * -dwapb_gpio_get_pdata(struct device *dev) +static void dwapb_get_irq(struct device *dev, struct fwnode_handle *fwnode, + struct dwapb_port_property *pp) +{ + struct device_node *np = NULL; + int j; + + if (fwnode_property_read_bool(fwnode, "interrupt-controller")) + np = to_of_node(fwnode); + + for (j = 0; j < pp->ngpio; j++) { + pp->irq[j] = -ENXIO; + + if (np) + pp->irq[j] = of_irq_get(np, j); + else if (has_acpi_companion(dev)) + pp->irq[j] = platform_get_irq(to_platform_device(dev), j); + + if (pp->irq[j] >= 0) + pp->has_irq = true; + } + + if (!pp->has_irq) + dev_warn(dev, "no irq for port%d\n", pp->idx); +} + +static struct dwapb_platform_data *dwapb_gpio_get_pdata(struct device *dev) { struct fwnode_handle *fwnode; struct dwapb_platform_data *pdata; struct dwapb_port_property *pp; int nports; - int i, j; + int i; nports = device_get_child_node_count(dev); if (nports == 0) @@ -589,8 +613,6 @@ dwapb_gpio_get_pdata(struct device *dev) i = 0; device_for_each_child_node(dev, fwnode) { - struct device_node *np = NULL; - pp = &pdata->properties[i++]; pp->fwnode = fwnode; @@ -617,28 +639,8 @@ dwapb_gpio_get_pdata(struct device *dev) * Only port A can provide interrupts in all configurations of * the IP. */ - if (pp->idx != 0) - continue; - - if (dev->of_node && fwnode_property_read_bool(fwnode, - "interrupt-controller")) { - np = to_of_node(fwnode); - } - - for (j = 0; j < pp->ngpio; j++) { - pp->irq[j] = -ENXIO; - - if (np) - pp->irq[j] = of_irq_get(np, j); - else if (has_acpi_companion(dev)) - pp->irq[j] = platform_get_irq(to_platform_device(dev), j); - - if (pp->irq[j] >= 0) - pp->has_irq = true; - } - - if (!pp->has_irq) - dev_warn(dev, "no irq for port%d\n", pp->idx); + if (pp->idx == 0) + dwapb_get_irq(dev, fwnode, pp); } return pdata; -- Gitee From 4cf186d1d5f163e1de5b2df2c2b6b1cb3ac6bf5c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 19 May 2020 16:12:31 +0300 Subject: [PATCH 2/4] gpio: dwapb: avoid error message for optional IRQ [Upstream commit d7cc23604f367c0d0f272f0af55e2032de50a053] platform_get_irq() will generate an error message if the requested IRQ is not present. Use platform_get_irq_optional() to avoid the error message being generated. Signed-off-by: Andy Shevchenko Tested-by: Serge Semin Reviewed-by: Serge Semin Acked-by: Serge Semin Link: https://lore.kernel.org/r/20200519131233.59032-2-andriy.shevchenko@linux.intel.com Signed-off-by: Linus Walleij Signed-off-by: huwentao --- drivers/gpio/gpio-dwapb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 26af7360d019..d7eb6c25e34d 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -579,7 +579,7 @@ static void dwapb_get_irq(struct device *dev, struct fwnode_handle *fwnode, if (np) pp->irq[j] = of_irq_get(np, j); else if (has_acpi_companion(dev)) - pp->irq[j] = platform_get_irq(to_platform_device(dev), j); + pp->irq[j] = platform_get_irq_optional(to_platform_device(dev), j); if (pp->irq[j] >= 0) pp->has_irq = true; -- Gitee From ef4e1aa675137b885ce4b30143b47ea34b1108d8 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 19 May 2020 16:12:32 +0300 Subject: [PATCH 3/4] gpio: dwapb: Don't use IRQ 0 as valid Linux interrupt [Upstream commit aa90939d22973765cc6318c6748c272b954e202f] IRQ 0 is not valid in Linux interrupt number space. Refactor the code with this kept in mind. Signed-off-by: Andy Shevchenko Tested-by: Serge Semin Acked-by: Serge Semin Link: https://lore.kernel.org/r/20200519131233.59032-3-andriy.shevchenko@linux.intel.com Signed-off-by: Linus Walleij Signed-off-by: huwentao --- drivers/gpio/gpio-dwapb.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index d7eb6c25e34d..f7079e4a8b40 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -446,7 +446,7 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio, int i; for (i = 0; i < pp->ngpio; i++) { - if (pp->irq[i] >= 0) + if (pp->irq[i]) irq_set_chained_handler_and_data(pp->irq[i], dwapb_irq_handler, gpio); } @@ -568,20 +568,20 @@ static void dwapb_get_irq(struct device *dev, struct fwnode_handle *fwnode, struct dwapb_port_property *pp) { struct device_node *np = NULL; - int j; + int irq = -ENXIO, j; if (fwnode_property_read_bool(fwnode, "interrupt-controller")) np = to_of_node(fwnode); for (j = 0; j < pp->ngpio; j++) { - pp->irq[j] = -ENXIO; - if (np) - pp->irq[j] = of_irq_get(np, j); + irq = of_irq_get(np, j); else if (has_acpi_companion(dev)) - pp->irq[j] = platform_get_irq_optional(to_platform_device(dev), j); + irq = platform_get_irq_optional(to_platform_device(dev), j); + if (irq > 0) + pp->irq[j] = irq; - if (pp->irq[j] >= 0) + if (pp->irq[j]) pp->has_irq = true; } -- Gitee From 6be8168ac94f24b27b47b9a2a982a6fad1118adb Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 19 May 2020 16:12:33 +0300 Subject: [PATCH 4/4] gpio: dwapb: Remove unneeded has_irq member in struct dwapb_port_property [Upstream commit 551cb86cbb7d85a3d16d10f6fb4fb954f13a7556] has_irq member of struct dwapb_port_property is used only in one place, so, make it local test instead and remove from the structure. This local test is using memchr_inv() which is quite efficient in comparison to the original loop and possible little overhead can be neglected. Signed-off-by: Andy Shevchenko Tested-by: Serge Semin Acked-by: Lee Jones Acked-by: Serge Semin Link: https://lore.kernel.org/r/20200519131233.59032-4-andriy.shevchenko@linux.intel.com Signed-off-by: Linus Walleij Signed-off-by: huwentao --- drivers/gpio/gpio-dwapb.c | 14 +++++++------- drivers/mfd/intel_quark_i2c_gpio.c | 1 - include/linux/platform_data/gpio-dwapb.h | 1 - 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index f7079e4a8b40..e693f876fa57 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -394,6 +394,11 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio, struct irq_chip_type *ct; int err, i; + if (memchr_inv(pp->irq, 0, sizeof(pp->irq)) == NULL) { + dev_warn(gpio->dev, "no IRQ for port%d\n", pp->idx); + return; + } + gpio->domain = irq_domain_create_linear(fwnode, ngpio, &irq_generic_chip_ops, gpio); if (!gpio->domain) @@ -531,7 +536,8 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, if (pp->idx == 0) port->gc.set_config = dwapb_gpio_set_config; - if (pp->has_irq) + /* Only port A can provide interrupts in all configurations of the IP */ + if (pp->idx == 0) dwapb_configure_irqs(gpio, port, pp); err = gpiochip_add_data(&port->gc, port); @@ -580,13 +586,7 @@ static void dwapb_get_irq(struct device *dev, struct fwnode_handle *fwnode, irq = platform_get_irq_optional(to_platform_device(dev), j); if (irq > 0) pp->irq[j] = irq; - - if (pp->irq[j]) - pp->has_irq = true; } - - if (!pp->has_irq) - dev_warn(dev, "no irq for port%d\n", pp->idx); } static struct dwapb_platform_data *dwapb_gpio_get_pdata(struct device *dev) diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c index 41326b48da55..84ca7902e1df 100644 --- a/drivers/mfd/intel_quark_i2c_gpio.c +++ b/drivers/mfd/intel_quark_i2c_gpio.c @@ -216,7 +216,6 @@ static int intel_quark_gpio_setup(struct pci_dev *pdev, struct mfd_cell *cell) pdata->properties->ngpio = INTEL_QUARK_MFD_NGPIO; pdata->properties->gpio_base = INTEL_QUARK_MFD_GPIO_BASE; pdata->properties->irq[0] = pdev->irq; - pdata->properties->has_irq = true; pdata->properties->irq_shared = true; cell->platform_data = pdata; diff --git a/include/linux/platform_data/gpio-dwapb.h b/include/linux/platform_data/gpio-dwapb.h index 3c606c450d05..ff1be737bad6 100644 --- a/include/linux/platform_data/gpio-dwapb.h +++ b/include/linux/platform_data/gpio-dwapb.h @@ -12,7 +12,6 @@ struct dwapb_port_property { unsigned int ngpio; unsigned int gpio_base; int irq[32]; - bool has_irq; bool irq_shared; }; -- Gitee