From 338aa10750ba24d04beeaf5dc5efc032e5cf343f Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Sun, 10 Mar 2019 23:27:31 -0700 Subject: [PATCH 01/85] gpio: vf610: Do not share irq_chip Fix the warning produced by gpiochip_set_irq_hooks() by allocating a dedicated IRQ chip per GPIO chip/port. Signed-off-by: Andrey Smirnov Cc: Linus Walleij Cc: Bartosz Golaszewski Cc: Chris Healy Cc: Andrew Lunn Cc: Heiner Kallweit Cc: Fabio Estevam Cc: linux-gpio@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-imx@nxp.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-vf610.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 541fa6ac399d..7e9451f47efe 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -29,6 +29,7 @@ struct fsl_gpio_soc_data { struct vf610_gpio_port { struct gpio_chip gc; + struct irq_chip ic; void __iomem *base; void __iomem *gpio_base; const struct fsl_gpio_soc_data *sdata; @@ -60,8 +61,6 @@ struct vf610_gpio_port { #define PORT_INT_EITHER_EDGE 0xb #define PORT_INT_LOGIC_ONE 0xc -static struct irq_chip vf610_gpio_irq_chip; - static const struct fsl_gpio_soc_data imx_data = { .have_paddr = true, }; @@ -237,15 +236,6 @@ static int vf610_gpio_irq_set_wake(struct irq_data *d, u32 enable) return 0; } -static struct irq_chip vf610_gpio_irq_chip = { - .name = "gpio-vf610", - .irq_ack = vf610_gpio_irq_ack, - .irq_mask = vf610_gpio_irq_mask, - .irq_unmask = vf610_gpio_irq_unmask, - .irq_set_type = vf610_gpio_irq_set_type, - .irq_set_wake = vf610_gpio_irq_set_wake, -}; - static int vf610_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -253,6 +243,7 @@ static int vf610_gpio_probe(struct platform_device *pdev) struct vf610_gpio_port *port; struct resource *iores; struct gpio_chip *gc; + struct irq_chip *ic; int i; int ret; @@ -316,6 +307,14 @@ static int vf610_gpio_probe(struct platform_device *pdev) gc->direction_output = vf610_gpio_direction_output; gc->set = vf610_gpio_set; + ic = &port->ic; + ic->name = "gpio-vf610"; + ic->irq_ack = vf610_gpio_irq_ack; + ic->irq_mask = vf610_gpio_irq_mask; + ic->irq_unmask = vf610_gpio_irq_unmask; + ic->irq_set_type = vf610_gpio_irq_set_type; + ic->irq_set_wake = vf610_gpio_irq_set_wake; + ret = gpiochip_add_data(gc, port); if (ret < 0) return ret; @@ -327,14 +326,13 @@ 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, &vf610_gpio_irq_chip, 0, - handle_edge_irq, IRQ_TYPE_NONE); + ret = gpiochip_irqchip_add(gc, ic, 0, handle_edge_irq, IRQ_TYPE_NONE); if (ret) { dev_err(dev, "failed to add irqchip\n"); gpiochip_remove(gc); return ret; } - gpiochip_set_chained_irqchip(gc, &vf610_gpio_irq_chip, port->irq, + gpiochip_set_chained_irqchip(gc, ic, port->irq, vf610_gpio_irq_handler); return 0; From a262555bc68561dc861cb24d3bd432fd6ce4f868 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Sun, 10 Mar 2019 23:27:32 -0700 Subject: [PATCH 02/85] gpio: vf610: Simplify vf610_gpio_set() The only difference between two codepaths is register offset used. Simplify the code a bit by replacing explicit calls with a single call with a variable offset. No functional change intended. Signed-off-by: Andrey Smirnov Cc: Linus Walleij Cc: Bartosz Golaszewski Cc: Chris Healy Cc: Andrew Lunn Cc: Heiner Kallweit Cc: Fabio Estevam Cc: linux-gpio@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-imx@nxp.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-vf610.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 7e9451f47efe..2ea17870e9da 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -102,11 +102,9 @@ static void vf610_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { struct vf610_gpio_port *port = gpiochip_get_data(gc); unsigned long mask = BIT(gpio); + unsigned long offset = val ? GPIO_PSOR : GPIO_PCOR; - if (val) - vf610_gpio_writel(mask, port->gpio_base + GPIO_PSOR); - else - vf610_gpio_writel(mask, port->gpio_base + GPIO_PCOR); + vf610_gpio_writel(mask, port->gpio_base + offset); } static int vf610_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) From 4a8909d0228133ec02ffac76590c055e593e8185 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Sun, 10 Mar 2019 23:27:33 -0700 Subject: [PATCH 03/85] gpio: vf610: Simplify vf610_gpio_get() Both branches of the if statement do exactly the same thing, just at different offsets. Simplify the code a bit by moving shared action code outside of the if statement. No functional change intended. Signed-off-by: Andrey Smirnov Cc: Linus Walleij Cc: Bartosz Golaszewski Cc: Chris Healy Cc: Andrew Lunn Cc: Heiner Kallweit Cc: Fabio Estevam Cc: linux-gpio@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-imx@nxp.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-vf610.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 2ea17870e9da..bb35cedd05e3 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -85,17 +85,15 @@ static int vf610_gpio_get(struct gpio_chip *gc, unsigned int gpio) { struct vf610_gpio_port *port = gpiochip_get_data(gc); unsigned long mask = BIT(gpio); - void __iomem *addr; + unsigned long offset = GPIO_PDIR; if (port->sdata && port->sdata->have_paddr) { mask &= vf610_gpio_readl(port->gpio_base + GPIO_PDDR); - addr = mask ? port->gpio_base + GPIO_PDOR : - port->gpio_base + GPIO_PDIR; - return !!(vf610_gpio_readl(addr) & BIT(gpio)); - } else { - return !!(vf610_gpio_readl(port->gpio_base + GPIO_PDIR) - & BIT(gpio)); + if (mask) + offset = GPIO_PDOR; } + + return !!(vf610_gpio_readl(port->gpio_base + offset) & BIT(gpio)); } static void vf610_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) From db9ed63ca510ecb3df0b4fec170830a96017b7d1 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Sun, 10 Mar 2019 23:27:34 -0700 Subject: [PATCH 04/85] gpio: vf610: Use devres to disable clk_port Clk_port should be disabled in all error paths in the code that follws, including the case when either gpiochip_add_data() or gpiochip_irqchip_add() fail. To simplify things fix this by using devm_add_action_or_reset() to disable corresponding clock in case of any erros as well as driver/device removal. Signed-off-by: Andrey Smirnov Cc: Linus Walleij Cc: Bartosz Golaszewski Cc: Chris Healy Cc: Andrew Lunn Cc: Heiner Kallweit Cc: Fabio Estevam Cc: linux-gpio@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-imx@nxp.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-vf610.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index bb35cedd05e3..78c1f8ebbe8f 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -232,6 +232,11 @@ static int vf610_gpio_irq_set_wake(struct irq_data *d, u32 enable) return 0; } +static void vf610_gpio_disable_clk(void *data) +{ + clk_disable_unprepare(data); +} + static int vf610_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -267,6 +272,10 @@ static int vf610_gpio_probe(struct platform_device *pdev) ret = clk_prepare_enable(port->clk_port); if (ret) return ret; + ret = devm_add_action_or_reset(dev, vf610_gpio_disable_clk, + port->clk_port); + if (ret) + return ret; } else if (port->clk_port == ERR_PTR(-EPROBE_DEFER)) { /* * Percolate deferrals, for anything else, @@ -278,12 +287,9 @@ static int vf610_gpio_probe(struct platform_device *pdev) port->clk_gpio = devm_clk_get(&pdev->dev, "gpio"); if (!IS_ERR(port->clk_gpio)) { ret = clk_prepare_enable(port->clk_gpio); - if (ret) { - clk_disable_unprepare(port->clk_port); + if (ret) return ret; - } } else if (port->clk_gpio == ERR_PTR(-EPROBE_DEFER)) { - clk_disable_unprepare(port->clk_port); return PTR_ERR(port->clk_gpio); } @@ -339,8 +345,6 @@ static int vf610_gpio_remove(struct platform_device *pdev) struct vf610_gpio_port *port = platform_get_drvdata(pdev); gpiochip_remove(&port->gc); - if (!IS_ERR(port->clk_port)) - clk_disable_unprepare(port->clk_port); if (!IS_ERR(port->clk_gpio)) clk_disable_unprepare(port->clk_gpio); From fc57949cfd1f1060a6154e45ebeeb80ac85bd499 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Sun, 10 Mar 2019 23:27:35 -0700 Subject: [PATCH 05/85] gpio: vf610: Use devres to disable clk_gpio Clk_gpio should be disabled in all error paths in the code that follws, including the case when either gpiochip_add_data() or gpiochip_irqchip_add() fail. To simplify things fix this by using devm_add_action() to disable corresponding clock in case of any erros as well as driver/device removal. Signed-off-by: Andrey Smirnov Cc: Linus Walleij Cc: Bartosz Golaszewski Cc: Chris Healy Cc: Andrew Lunn Cc: Heiner Kallweit Cc: Fabio Estevam Cc: linux-gpio@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-imx@nxp.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-vf610.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 78c1f8ebbe8f..f7445468677d 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -289,6 +289,10 @@ static int vf610_gpio_probe(struct platform_device *pdev) ret = clk_prepare_enable(port->clk_gpio); if (ret) return ret; + ret = devm_add_action_or_reset(dev, vf610_gpio_disable_clk, + port->clk_gpio); + if (ret) + return ret; } else if (port->clk_gpio == ERR_PTR(-EPROBE_DEFER)) { return PTR_ERR(port->clk_gpio); } @@ -345,8 +349,6 @@ static int vf610_gpio_remove(struct platform_device *pdev) struct vf610_gpio_port *port = platform_get_drvdata(pdev); gpiochip_remove(&port->gc); - if (!IS_ERR(port->clk_gpio)) - clk_disable_unprepare(port->clk_gpio); return 0; } From a74b4b11541a1c262713452a723833ffe7c123c3 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Sun, 10 Mar 2019 23:27:36 -0700 Subject: [PATCH 06/85] gpio: vf610: Use devres to remove gpiochip Now that the driver's custom remove hook contains only a single action, replace it by converting the code to use devm_gpiochip_add_data() to simplify things. Signed-off-by: Andrey Smirnov Cc: Linus Walleij Cc: Bartosz Golaszewski Cc: Chris Healy Cc: Andrew Lunn Cc: Heiner Kallweit Cc: Fabio Estevam Cc: linux-gpio@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-imx@nxp.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-vf610.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index f7445468677d..7db2fa229035 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -297,8 +297,6 @@ static int vf610_gpio_probe(struct platform_device *pdev) return PTR_ERR(port->clk_gpio); } - platform_set_drvdata(pdev, port); - gc = &port->gc; gc->of_node = np; gc->parent = dev; @@ -321,7 +319,7 @@ 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 = gpiochip_add_data(gc, port); + ret = devm_gpiochip_add_data(dev, gc, port); if (ret < 0) return ret; @@ -335,7 +333,6 @@ static int vf610_gpio_probe(struct platform_device *pdev) ret = gpiochip_irqchip_add(gc, ic, 0, handle_edge_irq, IRQ_TYPE_NONE); if (ret) { dev_err(dev, "failed to add irqchip\n"); - gpiochip_remove(gc); return ret; } gpiochip_set_chained_irqchip(gc, ic, port->irq, @@ -344,22 +341,12 @@ static int vf610_gpio_probe(struct platform_device *pdev) return 0; } -static int vf610_gpio_remove(struct platform_device *pdev) -{ - struct vf610_gpio_port *port = platform_get_drvdata(pdev); - - gpiochip_remove(&port->gc); - - return 0; -} - static struct platform_driver vf610_gpio_driver = { .driver = { .name = "gpio-vf610", .of_match_table = vf610_gpio_dt_ids, }, .probe = vf610_gpio_probe, - .remove = vf610_gpio_remove, }; builtin_platform_driver(vf610_gpio_driver); From 2e35bb6cd421fa2c488a82432a14ac2c894846fd Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Sun, 10 Mar 2019 23:27:37 -0700 Subject: [PATCH 07/85] gpio: vf610: Don't use explicit &pdev->dev in vf610_gpio_probe() The code already defines "dev" variable to help with that, so make sure all of the code uses it. Signed-off-by: Andrey Smirnov Cc: Linus Walleij Cc: Bartosz Golaszewski Cc: Chris Healy Cc: Andrew Lunn Cc: Heiner Kallweit Cc: Fabio Estevam Cc: linux-gpio@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-imx@nxp.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-vf610.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 7db2fa229035..6f6558715b88 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -248,7 +248,7 @@ static int vf610_gpio_probe(struct platform_device *pdev) int i; int ret; - port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL); + port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); if (!port) return -ENOMEM; @@ -267,7 +267,7 @@ static int vf610_gpio_probe(struct platform_device *pdev) if (port->irq < 0) return port->irq; - port->clk_port = devm_clk_get(&pdev->dev, "port"); + port->clk_port = devm_clk_get(dev, "port"); if (!IS_ERR(port->clk_port)) { ret = clk_prepare_enable(port->clk_port); if (ret) @@ -284,7 +284,7 @@ static int vf610_gpio_probe(struct platform_device *pdev) return PTR_ERR(port->clk_port); } - port->clk_gpio = devm_clk_get(&pdev->dev, "gpio"); + port->clk_gpio = devm_clk_get(dev, "gpio"); if (!IS_ERR(port->clk_gpio)) { ret = clk_prepare_enable(port->clk_gpio); if (ret) From 5c9f8cfe3cb67dcbf3e38a2b64c887200e363376 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 21 Mar 2019 10:21:44 +0100 Subject: [PATCH 08/85] dt-bindings: gpio: pca953x: Document onnn,cat9554 The ON Semiconductor CAT9554 is a variant of the PCA953x GPIO expander, with 8 GPIOs and interrupt functionality. Signed-off-by: Geert Uytterhoeven Signed-off-by: Bartosz Golaszewski --- Documentation/devicetree/bindings/gpio/gpio-pca953x.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt b/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt index fb144e2b6522..8678df2a5713 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt @@ -30,6 +30,7 @@ Required properties: ti,tca6424 ti,tca9539 ti,tca9554 + onnn,cat9554 onnn,pca9654 exar,xra1202 - gpio-controller: if used as gpio expander. From 932002f0028f1ada0f1948219f57b6cf7295ec24 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 21 Mar 2019 10:21:45 +0100 Subject: [PATCH 09/85] gpio: pca953x: Add support for CAT9554 The ON Semiconductor CAT9554 is a variant of the PCA953x GPIO expander, with 8 GPIOs and interrupt functionality. Signed-off-by: Geert Uytterhoeven Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pca953x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 7e76830b3368..88c94d155e21 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -1167,6 +1167,7 @@ static const struct of_device_id pca953x_dt_ids[] = { { .compatible = "ti,tca6416", .data = OF_953X(16, PCA_INT), }, { .compatible = "ti,tca6424", .data = OF_953X(24, PCA_INT), }, + { .compatible = "onnn,cat9554", .data = OF_953X( 8, PCA_INT), }, { .compatible = "onnn,pca9654", .data = OF_953X( 8, PCA_INT), }, { .compatible = "exar,xra1202", .data = OF_953X( 8, 0), }, From 6ada2f2269ce338d9ae1ae739ec58377dccfc2a3 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 13 Mar 2019 11:24:59 +0100 Subject: [PATCH 10/85] gpio: mockup: drop unneeded dependencies from Kconfig The testing module doesn't need GPIO irqchip nor does it depend on sysfs. Remove unnecessary dependencies from Kconfig. Signed-off-by: Bartosz Golaszewski --- drivers/gpio/Kconfig | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3f50526a771f..e9473e968d9a 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -332,9 +332,7 @@ config GPIO_MM_LANTIQ config GPIO_MOCKUP tristate "GPIO Testing Driver" - depends on GPIOLIB && SYSFS - select GPIO_SYSFS - select GPIOLIB_IRQCHIP + depends on GPIOLIB select IRQ_SIM help This enables GPIO Testing driver, which provides a way to test GPIO From 6e4484ee354872ecdc8dfa3e239c710cb5b7b7c5 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 13 Mar 2019 11:37:17 +0100 Subject: [PATCH 11/85] gpio: mockup: move the driver out of the IOMEM drivers section The testing driver doesn't really depend on HAS_IOMEM. We may want to build it for testing purposes on architectures not supporting IOMEM, for example: on user-mode linux. Move it out of the "Memory Mapped GPIO drivers" section. Signed-off-by: Bartosz Golaszewski --- drivers/gpio/Kconfig | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index e9473e968d9a..474ab3f7f9ce 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -330,18 +330,6 @@ config GPIO_MM_LANTIQ (EBU) found on Lantiq SoCs. The gpios are output only as they are created by attaching a 16bit latch to the bus. -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 - subsystem through sysfs(or char device) and debugfs. GPIO_SYSFS - must be selected for this test. - User could use it through the script in - tools/testing/selftests/gpio/gpio-mockup.sh. Reference the usage in - it. - config GPIO_MPC5200 def_bool y depends on PPC_MPC52xx @@ -1440,4 +1428,16 @@ config GPIO_VIPERBOARD 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 + subsystem through sysfs(or char device) and debugfs. GPIO_SYSFS + must be selected for this test. + User could use it through the script in + tools/testing/selftests/gpio/gpio-mockup.sh. Reference the usage in + it. + endif From 3c7469514dbe126a32d9d7452080570d89ff9d16 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 25 Mar 2019 15:47:46 +0200 Subject: [PATCH 12/85] gpio: 74x164: Make use of device properties ACPI-enabled platforms can use this device via unified device properties API. Convert driver to support this. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-74x164.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index fb7b620763a2..5f91d7618909 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -116,10 +117,9 @@ static int gen_74x164_probe(struct spi_device *spi) if (ret < 0) return ret; - if (of_property_read_u32(spi->dev.of_node, "registers-number", - &nregs)) { - dev_err(&spi->dev, - "Missing registers-number property in the DT.\n"); + ret = device_property_read_u32(&spi->dev, "registers-number", &nregs); + if (ret) { + dev_err(&spi->dev, "Missing 'registers-number' property.\n"); return -EINVAL; } From 517ec43927c85f4d1f67f3a51e8c36e28b2a41a4 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 25 Mar 2019 15:47:47 +0200 Subject: [PATCH 13/85] gpio: 74x164: Remove linux/init.h and sort headers There is no need to include linux/init.h when at the same time we include linux/module.h. Remove redundant inclusion. While here, sort header block alphabetically for easy maintenance. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-74x164.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index 5f91d7618909..fbd8478dae3d 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -9,14 +9,13 @@ * published by the Free Software Foundation. */ -#include -#include -#include -#include #include +#include +#include +#include #include #include -#include +#include #define GEN_74X164_NUMBER_GPIOS 8 From 9a9982d4601e34ef62fa970e3fca868ca61c22a8 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 25 Mar 2019 15:47:48 +0200 Subject: [PATCH 14/85] gpio: 74x164: Convert to use SPDX identifier Reduce size of duplicated comments by switching to use SPDX identifier. No functional change. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-74x164.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index fbd8478dae3d..e81307f9754e 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * 74Hx164 - Generic serial-in/parallel-out 8-bits shift register GPIO driver * * Copyright (C) 2010 Gabor Juhos * Copyright (C) 2010 Miguel Gaio - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include From c78c42d77165791c8198d7a86d1989ba65cf73a8 Mon Sep 17 00:00:00 2001 From: Shravan Kumar Ramani Date: Tue, 26 Mar 2019 10:42:48 -0400 Subject: [PATCH 15/85] gpio: add driver for Mellanox BlueField GPIO controller This patch adds support for the GPIO controller used by Mellanox BlueField SOCs. Reviewed-by: David Woods Signed-off-by: Shravan Kumar Ramani Signed-off-by: Bartosz Golaszewski --- drivers/gpio/Kconfig | 7 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-mlxbf.c | 153 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 drivers/gpio/gpio-mlxbf.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 474ab3f7f9ce..362da433593c 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1302,6 +1302,13 @@ config GPIO_MERRIFIELD help Say Y here to support Intel Merrifield GPIO. +config GPIO_MLXBF + tristate "Mellanox BlueField SoC GPIO" + depends on (MELLANOX_PLATFORM && ARM64 && ACPI) || COMPILE_TEST + select GPIO_GENERIC + help + Say Y here if you want GPIO support on Mellanox BlueField SoC. + config GPIO_ML_IOH tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support" depends on X86 || COMPILE_TEST diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 54d55274b93a..db8d854f9aea 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -85,6 +85,7 @@ obj-$(CONFIG_GPIO_MENZ127) += gpio-menz127.o obj-$(CONFIG_GPIO_MERRIFIELD) += gpio-merrifield.o obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o +obj-$(CONFIG_GPIO_MLXBF) += gpio-mlxbf.o obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o diff --git a/drivers/gpio/gpio-mlxbf.c b/drivers/gpio/gpio-mlxbf.c new file mode 100644 index 000000000000..d428f42be74f --- /dev/null +++ b/drivers/gpio/gpio-mlxbf.c @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Number of pins on BlueField */ +#define MLXBF_GPIO_NR 54 + +/* Pad Electrical Controls. */ +#define MLXBF_GPIO_PAD_CONTROL_FIRST_WORD 0x0700 +#define MLXBF_GPIO_PAD_CONTROL_1_FIRST_WORD 0x0708 +#define MLXBF_GPIO_PAD_CONTROL_2_FIRST_WORD 0x0710 +#define MLXBF_GPIO_PAD_CONTROL_3_FIRST_WORD 0x0718 + +#define MLXBF_GPIO_PIN_DIR_I 0x1040 +#define MLXBF_GPIO_PIN_DIR_O 0x1048 +#define MLXBF_GPIO_PIN_STATE 0x1000 +#define MLXBF_GPIO_SCRATCHPAD 0x20 + +#ifdef CONFIG_PM +struct mlxbf_gpio_context_save_regs { + u64 scratchpad; + u64 pad_control[MLXBF_GPIO_NR]; + u64 pin_dir_i; + u64 pin_dir_o; +}; +#endif + +/* Device state structure. */ +struct mlxbf_gpio_state { + struct gpio_chip gc; + + /* Memory Address */ + void __iomem *base; + +#ifdef CONFIG_PM + struct mlxbf_gpio_context_save_regs csave_regs; +#endif +}; + +static int mlxbf_gpio_probe(struct platform_device *pdev) +{ + struct mlxbf_gpio_state *gs; + struct device *dev = &pdev->dev; + struct gpio_chip *gc; + int ret; + + gs = devm_kzalloc(&pdev->dev, sizeof(*gs), GFP_KERNEL); + if (!gs) + return -ENOMEM; + + gs->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(gs->base)) + return PTR_ERR(gs->base); + + gc = &gs->gc; + ret = bgpio_init(gc, dev, 8, + gs->base + MLXBF_GPIO_PIN_STATE, + NULL, + NULL, + gs->base + MLXBF_GPIO_PIN_DIR_O, + gs->base + MLXBF_GPIO_PIN_DIR_I, + 0); + if (ret) + return -ENODEV; + + gc->owner = THIS_MODULE; + gc->ngpio = MLXBF_GPIO_NR; + + ret = devm_gpiochip_add_data(dev, &gs->gc, gs); + if (ret) { + dev_err(&pdev->dev, "Failed adding memory mapped gpiochip\n"); + return ret; + } + + platform_set_drvdata(pdev, gs); + dev_info(&pdev->dev, "registered Mellanox BlueField GPIO"); + return 0; +} + +#ifdef CONFIG_PM +static int mlxbf_gpio_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct mlxbf_gpio_state *gs = platform_get_drvdata(pdev); + + gs->csave_regs.scratchpad = readq(gs->base + MLXBF_GPIO_SCRATCHPAD); + gs->csave_regs.pad_control[0] = + readq(gs->base + MLXBF_GPIO_PAD_CONTROL_FIRST_WORD); + gs->csave_regs.pad_control[1] = + readq(gs->base + MLXBF_GPIO_PAD_CONTROL_1_FIRST_WORD); + gs->csave_regs.pad_control[2] = + readq(gs->base + MLXBF_GPIO_PAD_CONTROL_2_FIRST_WORD); + gs->csave_regs.pad_control[3] = + readq(gs->base + MLXBF_GPIO_PAD_CONTROL_3_FIRST_WORD); + gs->csave_regs.pin_dir_i = readq(gs->base + MLXBF_GPIO_PIN_DIR_I); + gs->csave_regs.pin_dir_o = readq(gs->base + MLXBF_GPIO_PIN_DIR_O); + + return 0; +} + +static int mlxbf_gpio_resume(struct platform_device *pdev) +{ + struct mlxbf_gpio_state *gs = platform_get_drvdata(pdev); + + writeq(gs->csave_regs.scratchpad, gs->base + MLXBF_GPIO_SCRATCHPAD); + writeq(gs->csave_regs.pad_control[0], + gs->base + MLXBF_GPIO_PAD_CONTROL_FIRST_WORD); + writeq(gs->csave_regs.pad_control[1], + gs->base + MLXBF_GPIO_PAD_CONTROL_1_FIRST_WORD); + writeq(gs->csave_regs.pad_control[2], + gs->base + MLXBF_GPIO_PAD_CONTROL_2_FIRST_WORD); + writeq(gs->csave_regs.pad_control[3], + gs->base + MLXBF_GPIO_PAD_CONTROL_3_FIRST_WORD); + writeq(gs->csave_regs.pin_dir_i, gs->base + MLXBF_GPIO_PIN_DIR_I); + writeq(gs->csave_regs.pin_dir_o, gs->base + MLXBF_GPIO_PIN_DIR_O); + + return 0; +} +#endif + +static const struct acpi_device_id mlxbf_gpio_acpi_match[] = { + { "MLNXBF02", 0 }, + {} +}; +MODULE_DEVICE_TABLE(acpi, mlxbf_gpio_acpi_match); + +static struct platform_driver mlxbf_gpio_driver = { + .driver = { + .name = "mlxbf_gpio", + .acpi_match_table = ACPI_PTR(mlxbf_gpio_acpi_match), + }, + .probe = mlxbf_gpio_probe, +#ifdef CONFIG_PM + .suspend = mlxbf_gpio_suspend, + .resume = mlxbf_gpio_resume, +#endif +}; + +module_platform_driver(mlxbf_gpio_driver); + +MODULE_DESCRIPTION("Mellanox BlueField GPIO Driver"); +MODULE_AUTHOR("Mellanox Technologies"); +MODULE_LICENSE("GPL"); From 21e2118f470302f16bee7ebd1444505eadbc2c20 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 25 Mar 2019 15:43:16 -0700 Subject: [PATCH 16/85] gpio: gpio-omap: limit errata 1.101 handling to wkup domain gpios only We need to only apply errata 1.101 handling to clear non-wakeup edge gpios for idle to the gpio bank(s) in the wkup domain to prevent spurious wake-up events. And we must restore what we did after idle manually as the gpio bank in wkup domain is not restored otherwise. Let's keep bank->saved_datain register reading separate, that's not related to the 1.101 errata and is used separately on restore. Cc: Aaro Koskinen Cc: Grygorii Strashko Cc: Keerthy Cc: Peter Ujfalusi Cc: Russell King Cc: Tero Kristo Reported-by: Grygorii Strashko Signed-off-by: Tony Lindgren Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-omap.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 7f33024b6d83..6375364f6623 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1444,7 +1444,10 @@ static void omap_gpio_restore_context(struct gpio_bank *bank); static void omap_gpio_idle(struct gpio_bank *bank, bool may_lose_context) { struct device *dev = bank->chip.parent; - u32 l1 = 0, l2 = 0; + void __iomem *base = bank->base; + u32 nowake; + + bank->saved_datain = readl_relaxed(base + bank->regs->datain); if (bank->funcs.idle_enable_level_quirk) bank->funcs.idle_enable_level_quirk(bank); @@ -1456,20 +1459,15 @@ static void omap_gpio_idle(struct gpio_bank *bank, bool may_lose_context) goto update_gpio_context_count; /* - * If going to OFF, remove triggering for all + * If going to OFF, remove triggering for all wkup domain * non-wakeup GPIOs. Otherwise spurious IRQs will be * generated. See OMAP2420 Errata item 1.101. */ - bank->saved_datain = readl_relaxed(bank->base + - bank->regs->datain); - l1 = bank->context.fallingdetect; - l2 = bank->context.risingdetect; - - l1 &= ~bank->enabled_non_wakeup_gpios; - l2 &= ~bank->enabled_non_wakeup_gpios; - - writel_relaxed(l1, bank->base + bank->regs->fallingdetect); - writel_relaxed(l2, bank->base + bank->regs->risingdetect); + if (!bank->loses_context && bank->enabled_non_wakeup_gpios) { + nowake = bank->enabled_non_wakeup_gpios; + omap_gpio_rmw(base, bank->regs->fallingdetect, nowake, ~nowake); + omap_gpio_rmw(base, bank->regs->risingdetect, nowake, ~nowake); + } bank->workaround_enabled = true; @@ -1518,6 +1516,12 @@ static void omap_gpio_unidle(struct gpio_bank *bank) return; } } + } else { + /* Restore changes done for OMAP2420 errata 1.101 */ + writel_relaxed(bank->context.fallingdetect, + bank->base + bank->regs->fallingdetect); + writel_relaxed(bank->context.risingdetect, + bank->base + bank->regs->risingdetect); } if (!bank->workaround_enabled) From 06dce84ec76bef5698acc498b76457e585b9efda Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 25 Mar 2019 15:43:17 -0700 Subject: [PATCH 17/85] gpio: gpio-omap: always scan for triggered non-wakeup capable interrupts The bank->workaround_enabled should be for omap24xx erratum 1.101 but is not needed any longer as erratum 1.101 handling only needs to happen based on !bank->loses_context with patch "gpio: omap: Limit errata 1.101 handling to wkup domain gpios only". Further Grygorii Strashko points out that we are now tagging all edge GPIOs as non-wakeup GPIOs and rely on original erratum 1.101 handling for scacnning for edge interrupts that have triggered during idle. Also the TI Android kernel tree has an earlier commit "GPIO: OMAP: Always scan gpios during runtime resume" by Tero Kristo saying: "This allows the driver to generate interrupts for GPIOs that can't wakeup but have changed state during runtime suspend. We cannot depend on the decision based on no need to restore, as the system state might change and pending events could gather up." So let's remove bank->workaround_enabled and always scan for triggered edge interrupts on resume. We do that based on bank->enabled_non_wakeup_gpios. Cc: Aaro Koskinen Cc: Grygorii Strashko Cc: Keerthy Cc: Peter Ujfalusi Cc: Russell King Cc: Tero Kristo Reported-by: Grygorii Strashko Signed-off-by: Tony Lindgren Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-omap.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 6375364f6623..a28196453029 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -83,7 +83,6 @@ struct gpio_bank { int stride; u32 width; int context_loss_count; - bool workaround_enabled; u32 quirks; void (*set_dataout)(struct gpio_bank *bank, unsigned gpio, int enable); @@ -1469,8 +1468,6 @@ static void omap_gpio_idle(struct gpio_bank *bank, bool may_lose_context) omap_gpio_rmw(base, bank->regs->risingdetect, nowake, ~nowake); } - bank->workaround_enabled = true; - update_gpio_context_count: if (bank->get_context_loss_count) bank->context_loss_count = @@ -1524,9 +1521,6 @@ static void omap_gpio_unidle(struct gpio_bank *bank) bank->base + bank->regs->risingdetect); } - if (!bank->workaround_enabled) - return; - l = readl_relaxed(bank->base + bank->regs->datain); /* @@ -1576,8 +1570,6 @@ static void omap_gpio_unidle(struct gpio_bank *bank) writel_relaxed(old0, bank->base + bank->regs->leveldetect0); writel_relaxed(old1, bank->base + bank->regs->leveldetect1); } - - bank->workaround_enabled = false; } static void omap_gpio_init_context(struct gpio_bank *p) From da38ef3ed10a09248e13ae16530c2c6d448dc47d Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 25 Mar 2019 15:43:18 -0700 Subject: [PATCH 18/85] gpio: gpio-omap: add check for off wake capable gpios We are currently assuming all GPIOs are non-wakeup capable GPIOs as we not configuring the bank->non_wakeup_gpios like we used to earlier with platform_data. Let's add omap_gpio_is_off_wakeup_capable() to make the handling clearer while considering that later patches may want to configure SoC specific bank->non_wakeup_gpios for the GPIOs in wakeup domain. Cc: Aaro Koskinen Cc: Grygorii Strashko Cc: Keerthy Cc: Peter Ujfalusi Cc: Russell King Cc: Tero Kristo Reported-by: Grygorii Strashko Signed-off-by: Tony Lindgren Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-omap.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index a28196453029..4d1bf884fcbc 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -352,6 +352,22 @@ static void omap_clear_gpio_debounce(struct gpio_bank *bank, unsigned offset) } } +/* + * Off mode wake-up capable GPIOs in bank(s) that are in the wakeup domain. + * See TRM section for GPIO for "Wake-Up Generation" for the list of GPIOs + * in wakeup domain. If bank->non_wakeup_gpios is not configured, assume none + * are capable waking up the system from off mode. + */ +static bool omap_gpio_is_off_wakeup_capable(struct gpio_bank *bank, u32 gpio_mask) +{ + u32 no_wake = bank->non_wakeup_gpios; + + if (no_wake) + return !!(~no_wake & gpio_mask); + + return false; +} + static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio, unsigned trigger) { @@ -383,13 +399,7 @@ static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio, } /* This part needs to be executed always for OMAP{34xx, 44xx} */ - if (!bank->regs->irqctrl) { - /* On omap24xx proceed only when valid GPIO bit is set */ - if (bank->non_wakeup_gpios) { - if (!(bank->non_wakeup_gpios & gpio_bit)) - goto exit; - } - + if (!bank->regs->irqctrl && !omap_gpio_is_off_wakeup_capable(bank, gpio)) { /* * Log the edge gpio and manually trigger the IRQ * after resume if the input level changes @@ -402,7 +412,6 @@ static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio, bank->enabled_non_wakeup_gpios &= ~gpio_bit; } -exit: bank->level_mask = readl_relaxed(bank->base + bank->regs->leveldetect0) | readl_relaxed(bank->base + bank->regs->leveldetect1); From cbe706b0526837a9dfd26e4492c399e8ab0df5aa Mon Sep 17 00:00:00 2001 From: Shravan Kumar Ramani Date: Wed, 27 Mar 2019 10:15:15 -0400 Subject: [PATCH 19/85] gpio: mlxbf: Add dependency on 64BIT to Kconfig entry Fixes a compile test failure Fixes: c78c42d77165 ("gpio: add driver for Mellanox BlueField GPIO controller") Signed-off-by: Shravan Kumar Ramani Signed-off-by: Bartosz Golaszewski --- drivers/gpio/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 362da433593c..c7a174edeaa3 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1304,7 +1304,7 @@ config GPIO_MERRIFIELD config GPIO_MLXBF tristate "Mellanox BlueField SoC GPIO" - depends on (MELLANOX_PLATFORM && ARM64 && ACPI) || COMPILE_TEST + depends on (MELLANOX_PLATFORM && ARM64 && ACPI) || (64BIT && COMPILE_TEST) select GPIO_GENERIC help Say Y here if you want GPIO support on Mellanox BlueField SoC. From 43c691e6232cef62daeca3d434e8729a725b2fe2 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Mon, 1 Apr 2019 05:09:50 +0000 Subject: [PATCH 20/85] gpio: mxc: use devm_platform_ioremap_resource() to simplify code Use the new helper devm_platform_ioremap_resource() which wraps the platform_get_resource() and devm_ioremap_resource() together, to simplify the code. Signed-off-by: Anson Huang Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-mxc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index e86e61dda4b7..b2813580c582 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -411,7 +411,6 @@ static int mxc_gpio_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct mxc_gpio_port *port; - struct resource *iores; int irq_base; int err; @@ -423,8 +422,7 @@ static int mxc_gpio_probe(struct platform_device *pdev) port->dev = &pdev->dev; - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - port->base = devm_ioremap_resource(&pdev->dev, iores); + port->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(port->base)) return PTR_ERR(port->base); From 85edcd01a902885fcb7bc02b7fc0f6e6a01b9386 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 30 Mar 2019 00:33:45 +0300 Subject: [PATCH 21/85] gpiolib: acpi: Fix references in kernel doc and amend This patch does the following bunch of changes: - append () to the functions for reference - convert gpiochip(s) -> GPIO chip(s) - add a note about returned error code type [acpi_find_gpio()] - move long summary to a description [acpi_gpio_count()] Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib-acpi.c | 45 ++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 30d0baf7ddae..e9ddf66f2d14 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -24,13 +24,13 @@ * * @node: list-entry of the events list of the struct acpi_gpio_chip * @handle: handle of ACPI method to execute when the IRQ triggers - * @handler: irq_handler to pass to request_irq when requesting the IRQ - * @pin: GPIO pin number on the gpio_chip - * @irq: Linux IRQ number for the event, for request_ / free_irq - * @irqflags: flags to pass to request_irq when requesting the IRQ + * @handler: handler function to pass to request_irq() when requesting the IRQ + * @pin: GPIO pin number on the struct gpio_chip + * @irq: Linux IRQ number for the event, for request_irq() / free_irq() + * @irqflags: flags to pass to request_irq() when requesting the IRQ * @irq_is_wake: If the ACPI flags indicate the IRQ is a wakeup source - * @irq_requested:True if request_irq has been done - * @desc: gpio_desc for the GPIO pin for this event + * @irq_requested:True if request_irq() has been done + * @desc: struct gpio_desc for the GPIO pin for this event */ struct acpi_gpio_event { struct list_head node; @@ -65,10 +65,10 @@ struct acpi_gpio_chip { }; /* - * For gpiochips which call acpi_gpiochip_request_interrupts() before late_init + * For GPIO chips which call acpi_gpiochip_request_interrupts() before late_init * (so builtin drivers) we register the ACPI GpioInt IRQ handlers from a - * late_initcall_sync handler, so that other builtin drivers can register their - * OpRegions before the event handlers can run. This list contains gpiochips + * late_initcall_sync() handler, so that other builtin drivers can register their + * OpRegions before the event handlers can run. This list contains GPIO chips * for which the acpi_gpiochip_request_irqs() call has been deferred. */ static DEFINE_MUTEX(acpi_gpio_deferred_req_irqs_lock); @@ -90,7 +90,7 @@ static int acpi_gpiochip_find(struct gpio_chip *gc, void *data) * * Return: GPIO descriptor to use with Linux generic GPIO API, or ERR_PTR * error value. Specifically returns %-EPROBE_DEFER if the referenced GPIO - * controller does not have gpiochip registered at the moment. This is to + * controller does not have GPIO chip registered at the moment. This is to * support probe deferral. */ static struct gpio_desc *acpi_get_gpiod(char *path, int pin) @@ -287,9 +287,9 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares, * * ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are * handled by ACPI event methods which need to be called from the GPIO - * chip's interrupt handler. acpi_gpiochip_request_interrupts finds out which - * gpio pins have acpi event methods and assigns interrupt handlers that calls - * the acpi event methods for those pins. + * chip's interrupt handler. acpi_gpiochip_request_interrupts() finds out which + * GPIO pins have ACPI event methods and assigns interrupt handlers that calls + * the ACPI event methods for those pins. */ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { @@ -653,7 +653,7 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode, * that case @index is used to select the GPIO entry in the property value * (in case of multiple). * - * If the GPIO cannot be translated or there is an error an ERR_PTR is + * If the GPIO cannot be translated or there is an error, an ERR_PTR is * returned. * * Note: if the GPIO resource has multiple entries in the pin list, this @@ -751,10 +751,13 @@ struct gpio_desc *acpi_find_gpio(struct device *dev, * @index: index of GpioIo/GpioInt resource (starting from %0) * @info: info pointer to fill in (optional) * - * If @fwnode is an ACPI device object, call %acpi_get_gpiod_by_index() for it. - * Otherwise (ie. it is a data-only non-device object), use the property-based + * If @fwnode is an ACPI device object, call acpi_get_gpiod_by_index() for it. + * Otherwise (i.e. it is a data-only non-device object), use the property-based * GPIO lookup to get to the GPIO resource with the relevant information and use * that to obtain the GPIO descriptor to return. + * + * If the GPIO cannot be translated or there is an error an ERR_PTR is + * returned. */ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname, int index, @@ -1158,11 +1161,13 @@ static int acpi_find_gpio_count(struct acpi_resource *ares, void *data) } /** - * acpi_gpio_count - return the number of GPIOs associated with a - * device / function or -ENOENT if no GPIO has been - * assigned to the requested function. - * @dev: GPIO consumer, can be NULL for system-global GPIOs + * acpi_gpio_count - count the GPIOs associated with a device / function + * @dev: GPIO consumer, can be %NULL for system-global GPIOs * @con_id: function within the GPIO consumer + * + * Return: + * The number of GPIOs associated with a device / function or %-ENOENT, + * if no GPIO has been assigned to the requested function. */ int acpi_gpio_count(struct device *dev, const char *con_id) { From 1d7765ba15aca68f3bc52f59434c1c34855bbb54 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 26 Mar 2019 17:21:14 +0200 Subject: [PATCH 22/85] gpiolib: Don't WARN on gpiod_put() for optional GPIO In case of debug and optional GPIO requested, the gpiod_put() is not aware of and will WARN, which is not the case. Make gpiod_put() NULL-aware to keep silent for optional GPIOs. Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 144af0733581..36445e24ee89 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -4616,7 +4616,8 @@ EXPORT_SYMBOL_GPL(gpiod_get_array_optional); */ void gpiod_put(struct gpio_desc *desc) { - gpiod_free(desc); + if (desc) + gpiod_free(desc); } EXPORT_SYMBOL_GPL(gpiod_put); From f69e00bd21aa6a1961c521b6eb199137fcb8a76a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 22 Feb 2019 11:14:44 +0100 Subject: [PATCH 23/85] gpio: mmio: Support two direction registers It turns out that one specific hardware has two direction registers: one to set a GPIO line as input and another one to set a GPIO line as output. So in theory a line can be configured as input and output at the same time. Make the MMIO GPIO helper deal with this: store both registers in the state container, use both in the generic code if present. Synchronize the input register to the output register when we register a GPIO chip, with the output settings taking precedence. Keep the helper variable to detect inverted direction semantics (only direction in register) but augment the code to be more straight-forward for the generic case when setting the registers. Fix some flunky with unreadable direction registers at the same time as we're touching this code. Cc: David Woods Cc: Shravan Kumar Ramani Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mmio.c | 85 ++++++++++++++++++++++++------------- include/linux/gpio/driver.h | 15 +++++-- 2 files changed, 67 insertions(+), 33 deletions(-) diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c index 50bdc29591c0..f172b4382d8d 100644 --- a/drivers/gpio/gpio-mmio.c +++ b/drivers/gpio/gpio-mmio.c @@ -372,11 +372,12 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) spin_lock_irqsave(&gc->bgpio_lock, flags); - if (gc->bgpio_dir_inverted) - gc->bgpio_dir |= bgpio_line2mask(gc, gpio); - else - gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio); - gc->write_reg(gc->reg_dir, gc->bgpio_dir); + gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio); + + if (gc->reg_dir_in) + gc->write_reg(gc->reg_dir_in, ~gc->bgpio_dir); + if (gc->reg_dir_out) + gc->write_reg(gc->reg_dir_out, gc->bgpio_dir); spin_unlock_irqrestore(&gc->bgpio_lock, flags); @@ -385,11 +386,16 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio) { - /* Return 0 if output, 1 of input */ - if (gc->bgpio_dir_inverted) - return !!(gc->read_reg(gc->reg_dir) & bgpio_line2mask(gc, gpio)); - else - return !(gc->read_reg(gc->reg_dir) & bgpio_line2mask(gc, gpio)); + /* Return 0 if output, 1 if input */ + if (gc->bgpio_dir_unreadable) + return !(gc->bgpio_dir & bgpio_line2mask(gc, gpio)); + if (gc->reg_dir_out) + return !(gc->read_reg(gc->reg_dir_out) & bgpio_line2mask(gc, gpio)); + if (gc->reg_dir_in) + return !!(gc->read_reg(gc->reg_dir_in) & bgpio_line2mask(gc, gpio)); + + /* This should not happen */ + return 1; } static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) @@ -400,11 +406,12 @@ static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) spin_lock_irqsave(&gc->bgpio_lock, flags); - if (gc->bgpio_dir_inverted) - gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio); - else - gc->bgpio_dir |= bgpio_line2mask(gc, gpio); - gc->write_reg(gc->reg_dir, gc->bgpio_dir); + gc->bgpio_dir |= bgpio_line2mask(gc, gpio); + + if (gc->reg_dir_in) + gc->write_reg(gc->reg_dir_in, ~gc->bgpio_dir); + if (gc->reg_dir_out) + gc->write_reg(gc->reg_dir_out, gc->bgpio_dir); spin_unlock_irqrestore(&gc->bgpio_lock, flags); @@ -537,19 +544,19 @@ static int bgpio_setup_direction(struct gpio_chip *gc, void __iomem *dirin, unsigned long flags) { - if (dirout && dirin) { - return -EINVAL; - } else if (dirout) { - gc->reg_dir = dirout; + if (dirout || dirin) { + gc->reg_dir_out = dirout; + gc->reg_dir_in = dirin; gc->direction_output = bgpio_dir_out; gc->direction_input = bgpio_dir_in; gc->get_direction = bgpio_get_dir; - } else if (dirin) { - gc->reg_dir = dirin; - gc->direction_output = bgpio_dir_out; - gc->direction_input = bgpio_dir_in; - gc->get_direction = bgpio_get_dir; - gc->bgpio_dir_inverted = true; + /* + * If only dirin is available, this means we need + * inverted semantics when handling get/set registers + * so detect this here. + */ + if (dirin && !dirout) + gc->bgpio_dir_inverted = true; } else { if (flags & BGPIOF_NO_OUTPUT) gc->direction_output = bgpio_dir_out_err; @@ -588,11 +595,11 @@ static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin) * @dirout: MMIO address for the register to set the line as OUTPUT. It is assumed * that setting a line to 1 in this register will turn that line into an * output line. Conversely, setting the line to 0 will turn that line into - * an input. Either this or @dirin can be defined, but never both. + * an input. * @dirin: MMIO address for the register to set this line as INPUT. It is assumed * that setting a line to 1 in this register will turn that line into an * input line. Conversely, setting the line to 0 will turn that line into - * an output. Either this or @dirout can be defined, but never both. + * an output. * @flags: Different flags that will affect the behaviour of the device, such as * endianness etc. */ @@ -634,8 +641,28 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev, if (gc->set == bgpio_set_set && !(flags & BGPIOF_UNREADABLE_REG_SET)) gc->bgpio_data = gc->read_reg(gc->reg_set); - if (gc->reg_dir && !(flags & BGPIOF_UNREADABLE_REG_DIR)) - gc->bgpio_dir = gc->read_reg(gc->reg_dir); + + if (flags & BGPIOF_UNREADABLE_REG_DIR) + gc->bgpio_dir_unreadable = true; + + /* + * Inspect hardware to find initial direction setting. + */ + if ((gc->reg_dir_out || gc->reg_dir_in) && + !(flags & BGPIOF_UNREADABLE_REG_DIR)) { + if (gc->reg_dir_out) + gc->bgpio_dir = gc->read_reg(gc->reg_dir_out); + else if (gc->reg_dir_in) + gc->bgpio_dir = ~gc->read_reg(gc->reg_dir_in); + /* + * If we have two direction registers, synchronise + * input setting to output setting, the library + * can not handle a line being input and output at + * the same time. + */ + if (gc->reg_dir_out && gc->reg_dir_in) + gc->write_reg(gc->reg_dir_in, ~gc->bgpio_dir); + } return ret; } diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 01497910f023..95a51794c24a 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -227,9 +227,13 @@ struct gpio_irq_chip { * @reg_dat: data (in) register for generic GPIO * @reg_set: output set register (out=high) for generic GPIO * @reg_clr: output clear register (out=low) for generic GPIO - * @reg_dir: direction setting register for generic GPIO + * @reg_dir_out: direction out setting register for generic GPIO + * @reg_dir_in: direction in setting register for generic GPIO * @bgpio_dir_inverted: indicates that the direction register is inverted - * (gpiolib private state variable) + * (gpiolib private state variable) this means @reg_dir_in is + * available but not @reg_dir_out. + * @bgpio_dir_unreadable: indicates that the direction register(s) cannot + * be read and we need to rely on out internal state tracking. * @bgpio_bits: number of register bits used for a generic GPIO i.e. * * 8 * @bgpio_lock: used to lock chip->bgpio_data. Also, this is needed to keep @@ -237,7 +241,8 @@ struct gpio_irq_chip { * @bgpio_data: shadowed data register for generic GPIO to clear/set bits * safely. * @bgpio_dir: shadowed direction register for generic GPIO to clear/set - * direction safely. + * direction safely. A "1" in this word means the line is set as + * output. * * A gpio_chip can help platforms abstract various sources of GPIOs so * they can all be accessed through a common programing interface. @@ -298,8 +303,10 @@ struct gpio_chip { void __iomem *reg_dat; void __iomem *reg_set; void __iomem *reg_clr; - void __iomem *reg_dir; + void __iomem *reg_dir_out; + void __iomem *reg_dir_in; bool bgpio_dir_inverted; + bool bgpio_dir_unreadable; int bgpio_bits; spinlock_t bgpio_lock; unsigned long bgpio_data; From 7e9fa3c9d3e3d4f5f13f66383666cd0f32ef3b81 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 28 Mar 2019 14:13:49 +0100 Subject: [PATCH 24/85] gpio: Remove obsolete comment about gpiochip_free_hogs() usage gpiochip_free_hogs() was always called from gpiochip_remove(), not of_gpiochip_remove(). It is now also called from the failure patch in gpiochip_add_data_with_key(). Fixes: f625d4601759f1cf ("gpio: add GPIO hogging mechanism") Signed-off-by: Geert Uytterhoeven Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 144af0733581..f41ad889124f 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -4445,8 +4445,6 @@ int gpiod_hog(struct gpio_desc *desc, const char *name, /** * gpiochip_free_hogs - Scan gpio-controller chip and release GPIO hog * @chip: gpio chip to act on - * - * This is only used by of_gpiochip_remove to free hogged gpios */ static void gpiochip_free_hogs(struct gpio_chip *chip) { From c42e34c9fdbaf28857825a4f58834c967c2c967a Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Tue, 5 Mar 2019 01:35:31 +0100 Subject: [PATCH 25/85] drivers: gpio: Kconfig: pedantic formatting cleanups Align the Kconfig formatting with the vast majority of the Kconfig files, to make it a bit easier / more pleasant to read ;-) Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 50 ++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3f50526a771f..c5420e6c9e4d 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -27,12 +27,12 @@ config GPIOLIB_FASTPATH_LIMIT range 32 512 default 512 help - This adjusts the point at which certain APIs will switch from - using a stack allocated buffer to a dynamically allocated buffer. + This adjusts the point at which certain APIs will switch from + using a stack allocated buffer to a dynamically allocated buffer. - You shouldn't need to change this unless you really need to - optimize either stack space or performance. Change this carefully - since setting an incorrect value could cause stack corruption. + You shouldn't need to change this unless you really need to + optimize either stack space or performance. Change this carefully + since setting an incorrect value could cause stack corruption. config OF_GPIO def_bool y @@ -320,7 +320,7 @@ config GPIO_MENZ127 depends on MCB select GPIO_GENERIC help - Say yes here to support the MEN 16Z127 GPIO Controller + Say yes here to support the MEN 16Z127 GPIO Controller config GPIO_MM_LANTIQ bool "Lantiq Memory mapped GPIOs" @@ -862,11 +862,11 @@ config GPIO_MAX732X Input and Output (designed by 'P'). The combinations are listed below: - 8 bits: max7319 (8I), max7320 (8O), max7321 (8P), - max7322 (4I4O), max7323 (4P4O) + 8 bits: max7319 (8I), max7320 (8O), max7321 (8P), + max7322 (4I4O), max7323 (4P4O) - 16 bits: max7324 (8I8O), max7325 (8P8O), - max7326 (4I12O), max7327 (4P12O) + 16 bits: max7324 (8I8O), max7325 (8P8O), + max7326 (4I12O), max7327 (4P12O) Board setup code must specify the model to use, and the start number for these GPIOs. @@ -893,17 +893,17 @@ config GPIO_PCA953X SMBus I/O expanders, made mostly by NXP or TI. Compatible models include: - 4 bits: pca9536, pca9537 + 4 bits: pca9536, pca9537 - 8 bits: max7310, max7315, pca6107, pca9534, pca9538, pca9554, - pca9556, pca9557, pca9574, tca6408, tca9554, xra1202 + 8 bits: max7310, max7315, pca6107, pca9534, pca9538, pca9554, + pca9556, pca9557, pca9574, tca6408, tca9554, xra1202 - 16 bits: max7312, max7313, pca9535, pca9539, pca9555, pca9575, - tca6416 + 16 bits: max7312, max7313, pca9535, pca9539, pca9555, pca9575, + tca6416 - 24 bits: tca6424 + 24 bits: tca6424 - 40 bits: pca9505, pca9698 + 40 bits: pca9505, pca9698 config GPIO_PCA953X_IRQ bool "Interrupt controller support for PCA953x" @@ -925,7 +925,7 @@ config GPIO_PCF857X 8 bits: pcf8574, pcf8574a, pca8574, pca8574a, pca9670, pca9672, pca9674, pca9674a, - max7328, max7329 + max7328, max7329 16 bits: pcf8575, pcf8575c, pca8575, pca9671, pca9673, pca9675 @@ -1047,9 +1047,9 @@ config HTC_EGPIO bool "HTC EGPIO support" depends on GPIOLIB && ARM help - This driver supports the CPLD egpio chip present on - several HTC phones. It provides basic support for input - pins, output pins, and irqs. + This driver supports the CPLD egpio chip present on + several HTC phones. It provides basic support for input + pins, output pins, and irqs. config GPIO_JANZ_TTL tristate "Janz VMOD-TTL Digital IO Module" @@ -1085,7 +1085,7 @@ config GPIO_LP873X on LP873X PMICs. This driver can also be built as a module. If so, the module will be - called gpio-lp873x. + called gpio-lp873x. config GPIO_LP87565 tristate "TI LP87565 GPIO" @@ -1436,9 +1436,9 @@ config GPIO_VIPERBOARD Say yes here to access the GPIO signals of Nano River Technologies Viperboard. There are two GPIO chips on the board: gpioa and gpiob. - See viperboard API specification and Nano - River Tech's viperboard.h for detailed meaning - of the module parameters. + See viperboard API specification and Nano + River Tech's viperboard.h for detailed meaning + of the module parameters. endmenu From 3faf1e6f7e368a944691a3f9b60f095ca503b283 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:54:40 +0100 Subject: [PATCH 26/85] drivers: gpio: 74xx-mmio: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-74xx-mmio.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-74xx-mmio.c b/drivers/gpio/gpio-74xx-mmio.c index 49616ec815ee..04247075091d 100644 --- a/drivers/gpio/gpio-74xx-mmio.c +++ b/drivers/gpio/gpio-74xx-mmio.c @@ -106,7 +106,6 @@ static int mmio_74xx_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) static int mmio_74xx_gpio_probe(struct platform_device *pdev) { struct mmio_74xx_gpio_priv *priv; - struct resource *res; void __iomem *dat; int err; @@ -116,8 +115,7 @@ static int mmio_74xx_gpio_probe(struct platform_device *pdev) priv->flags = (uintptr_t)of_device_get_match_data(&pdev->dev); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dat = devm_ioremap_resource(&pdev->dev, res); + dat = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(dat)) return PTR_ERR(dat); From bb17a27a5f48f70593e4d29137a258561733171a Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:54:41 +0100 Subject: [PATCH 27/85] drivers: gpio: amdpt: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-amdpt.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpio/gpio-amdpt.c b/drivers/gpio/gpio-amdpt.c index 9b78dc837603..1ffd7c2d1285 100644 --- a/drivers/gpio/gpio-amdpt.c +++ b/drivers/gpio/gpio-amdpt.c @@ -78,7 +78,6 @@ static int pt_gpio_probe(struct platform_device *pdev) struct acpi_device *acpi_dev; acpi_handle handle = ACPI_HANDLE(dev); struct pt_gpio_chip *pt_gpio; - struct resource *res_mem; int ret = 0; if (acpi_bus_get_device(handle, &acpi_dev)) { @@ -90,12 +89,7 @@ static int pt_gpio_probe(struct platform_device *pdev) if (!pt_gpio) return -ENOMEM; - res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res_mem) { - dev_err(&pdev->dev, "Failed to get MMIO resource for PT GPIO.\n"); - return -EINVAL; - } - pt_gpio->reg_base = devm_ioremap_resource(dev, res_mem); + pt_gpio->reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(pt_gpio->reg_base)) { dev_err(&pdev->dev, "Failed to map MMIO resource for PT GPIO.\n"); return PTR_ERR(pt_gpio->reg_base); From aee70b77fb992a465a420e89a067254a818dd9d9 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:54:43 +0100 Subject: [PATCH 28/85] drivers: gpio: aspeed: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-aspeed.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index 854bce4fb9e7..44aa843fbada 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -1156,15 +1156,13 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) { const struct of_device_id *gpio_id; struct aspeed_gpio *gpio; - struct resource *res; int rc, i, banks; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - gpio->base = devm_ioremap_resource(&pdev->dev, res); + gpio->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(gpio->base)) return PTR_ERR(gpio->base); From 72d8cb715477721106bc89248f3964d38cc0a2a0 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:54:44 +0100 Subject: [PATCH 29/85] drivers: gpio: bcm-kona: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Reviewed-by: Florian Fainelli Signed-off-by: Linus Walleij --- drivers/gpio/gpio-bcm-kona.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c index c5536a509b59..9fa6d3a967d2 100644 --- a/drivers/gpio/gpio-bcm-kona.c +++ b/drivers/gpio/gpio-bcm-kona.c @@ -568,7 +568,6 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; const struct of_device_id *match; - struct resource *res; struct bcm_kona_gpio_bank *bank; struct bcm_kona_gpio *kona_gpio; struct gpio_chip *chip; @@ -618,8 +617,7 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev) return -ENXIO; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - kona_gpio->reg_base = devm_ioremap_resource(dev, res); + kona_gpio->reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(kona_gpio->reg_base)) { ret = -ENXIO; goto err_irq_domain; From b2c09588f242b1414f4c7535f2bc390e66794743 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:54:45 +0100 Subject: [PATCH 30/85] drivers: gpio: cadence: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-cadence.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-cadence.c b/drivers/gpio/gpio-cadence.c index aec8d5df9f30..712ae212b0b4 100644 --- a/drivers/gpio/gpio-cadence.c +++ b/drivers/gpio/gpio-cadence.c @@ -148,7 +148,6 @@ static struct irq_chip cdns_gpio_irqchip = { static int cdns_gpio_probe(struct platform_device *pdev) { struct cdns_gpio_chip *cgpio; - struct resource *res; int ret, irq; u32 dir_prev; u32 num_gpios = 32; @@ -157,8 +156,7 @@ static int cdns_gpio_probe(struct platform_device *pdev) if (!cgpio) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - cgpio->regs = devm_ioremap_resource(&pdev->dev, res); + cgpio->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(cgpio->regs)) return PTR_ERR(cgpio->regs); From 09ec4735921498e9f3e368e079367225d74ab8a6 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:54:46 +0100 Subject: [PATCH 31/85] drivers: gpio: clps711x: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-clps711x.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c index 52fd63f02134..0fbbb0edc0ba 100644 --- a/drivers/gpio/gpio-clps711x.c +++ b/drivers/gpio/gpio-clps711x.c @@ -19,7 +19,6 @@ static int clps711x_gpio_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; void __iomem *dat, *dir; struct gpio_chip *gc; - struct resource *res; int err, id; if (!np) @@ -33,13 +32,11 @@ static int clps711x_gpio_probe(struct platform_device *pdev) if (!gc) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dat = devm_ioremap_resource(&pdev->dev, res); + dat = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(dat)) return PTR_ERR(dat); - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - dir = devm_ioremap_resource(&pdev->dev, res); + dir = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(dir)) return PTR_ERR(dir); From 2a7194e9759586dea43f3b76b2bf37c31e771726 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:54:47 +0100 Subject: [PATCH 32/85] drivers: gpio: dwap: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-dwapb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 84ae04402f70..d3eda65fd6d3 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -655,7 +655,6 @@ MODULE_DEVICE_TABLE(acpi, dwapb_acpi_match); static int dwapb_gpio_probe(struct platform_device *pdev) { unsigned int i; - struct resource *res; struct dwapb_gpio *gpio; int err; struct device *dev = &pdev->dev; @@ -688,8 +687,7 @@ static int dwapb_gpio_probe(struct platform_device *pdev) if (!gpio->ports) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - gpio->regs = devm_ioremap_resource(&pdev->dev, res); + gpio->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(gpio->regs)) return PTR_ERR(gpio->regs); From 94a2d4279924ca65df513cb5dbac803607f7279d Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:55:08 +0100 Subject: [PATCH 33/85] drivers: gpio: sprd: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Reviewed-by: Baolin Wang Signed-off-by: Linus Walleij --- drivers/gpio/gpio-sprd.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-sprd.c b/drivers/gpio/gpio-sprd.c index 55072d2b367f..f5c8b3a351d5 100644 --- a/drivers/gpio/gpio-sprd.c +++ b/drivers/gpio/gpio-sprd.c @@ -219,7 +219,6 @@ static int sprd_gpio_probe(struct platform_device *pdev) { struct gpio_irq_chip *irq; struct sprd_gpio *sprd_gpio; - struct resource *res; int ret; sprd_gpio = devm_kzalloc(&pdev->dev, sizeof(*sprd_gpio), GFP_KERNEL); @@ -232,8 +231,7 @@ static int sprd_gpio_probe(struct platform_device *pdev) return sprd_gpio->irq; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sprd_gpio->base = devm_ioremap_resource(&pdev->dev, res); + sprd_gpio->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sprd_gpio->base)) return PTR_ERR(sprd_gpio->base); From b35263db10a78519e07dd459669f8ea73cb15de0 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:54:50 +0100 Subject: [PATCH 34/85] drivers: gpio: ftgpio010: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ftgpio010.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-ftgpio010.c b/drivers/gpio/gpio-ftgpio010.c index 45fe125823a8..8ff8ce2970d9 100644 --- a/drivers/gpio/gpio-ftgpio010.c +++ b/drivers/gpio/gpio-ftgpio010.c @@ -225,7 +225,6 @@ static int ftgpio_gpio_set_config(struct gpio_chip *gc, unsigned int offset, static int ftgpio_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct resource *res; struct ftgpio_gpio *g; int irq; int ret; @@ -236,8 +235,7 @@ static int ftgpio_gpio_probe(struct platform_device *pdev) g->dev = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - g->base = devm_ioremap_resource(dev, res); + g->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(g->base)) return PTR_ERR(g->base); From 8f701e1dd64f078d616a271de026a4853f127c8f Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:54:52 +0100 Subject: [PATCH 35/85] drivers: gpio: hlwd: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-hlwd.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-hlwd.c b/drivers/gpio/gpio-hlwd.c index a7b17897356e..e5fa00f8145f 100644 --- a/drivers/gpio/gpio-hlwd.c +++ b/drivers/gpio/gpio-hlwd.c @@ -208,7 +208,6 @@ static int hlwd_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type) static int hlwd_gpio_probe(struct platform_device *pdev) { struct hlwd_gpio *hlwd; - struct resource *regs_resource; u32 ngpios; int res; @@ -216,8 +215,7 @@ static int hlwd_gpio_probe(struct platform_device *pdev) if (!hlwd) return -ENOMEM; - regs_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hlwd->regs = devm_ioremap_resource(&pdev->dev, regs_resource); + hlwd->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(hlwd->regs)) return PTR_ERR(hlwd->regs); From 30f8c521000213db30fca8afac4175e428509fe7 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:54:53 +0100 Subject: [PATCH 36/85] drivers: gpio: iop: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-iop.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-iop.c b/drivers/gpio/gpio-iop.c index 8d62db447ec1..11b77d868c89 100644 --- a/drivers/gpio/gpio-iop.c +++ b/drivers/gpio/gpio-iop.c @@ -21,7 +21,6 @@ static int iop3xx_gpio_probe(struct platform_device *pdev) { - struct resource *res; struct gpio_chip *gc; void __iomem *base; int err; @@ -30,8 +29,7 @@ static int iop3xx_gpio_probe(struct platform_device *pdev) if (!gc) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); From 38b1e6805e1d134b3966e283013695af586e09e9 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:54:54 +0100 Subject: [PATCH 37/85] drivers: gpio: janz-ttl: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-janz-ttl.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-janz-ttl.c b/drivers/gpio/gpio-janz-ttl.c index 6b9bf8b7bf16..b97a91166497 100644 --- a/drivers/gpio/gpio-janz-ttl.c +++ b/drivers/gpio/gpio-janz-ttl.c @@ -147,7 +147,6 @@ static int ttl_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct ttl_module *mod; struct gpio_chip *gpio; - struct resource *res; int ret; pdata = dev_get_platdata(&pdev->dev); @@ -164,8 +163,7 @@ static int ttl_probe(struct platform_device *pdev) spin_lock_init(&mod->lock); /* get access to the MODULbus registers for this module */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mod->regs = devm_ioremap_resource(dev, res); + mod->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mod->regs)) return PTR_ERR(mod->regs); From 62fe072a24e2a6520802cbc57bd2943e0ab8f640 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:54:56 +0100 Subject: [PATCH 38/85] drivers: gpio: loongon1: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-loongson1.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-loongson1.c b/drivers/gpio/gpio-loongson1.c index fca84ccac35c..1b1ee94eeab4 100644 --- a/drivers/gpio/gpio-loongson1.c +++ b/drivers/gpio/gpio-loongson1.c @@ -47,15 +47,13 @@ static int ls1x_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct gpio_chip *gc; - struct resource *res; int ret; gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); if (!gc) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - gpio_reg_base = devm_ioremap_resource(dev, res); + gpio_reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(gpio_reg_base)) return PTR_ERR(gpio_reg_base); From 47b4916cb4fb691d10bcb82185737c15291a27ac Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:54:57 +0100 Subject: [PATCH 39/85] drivers: gpio: lpc18xx: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Acked-by: Vladimir Zapolskiy Signed-off-by: Linus Walleij --- drivers/gpio/gpio-lpc18xx.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-lpc18xx.c b/drivers/gpio/gpio-lpc18xx.c index d441dbaed7a3..d711ae06747e 100644 --- a/drivers/gpio/gpio-lpc18xx.c +++ b/drivers/gpio/gpio-lpc18xx.c @@ -340,10 +340,7 @@ static int lpc18xx_gpio_probe(struct platform_device *pdev) index = of_property_match_string(dev->of_node, "reg-names", "gpio"); if (index < 0) { /* To support backward compatibility take the first resource */ - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - gc->base = devm_ioremap_resource(dev, res); + gc->base = devm_platform_ioremap_resource(pdev, 0); } else { struct resource res; From 329e23f9bc0a28fc58e3910b100358309a2d3156 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:54:58 +0100 Subject: [PATCH 40/85] drivers: gpio: mb86s7x: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mb86s7x.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c index 3134c0d2bfe4..9308081e0a4a 100644 --- a/drivers/gpio/gpio-mb86s7x.c +++ b/drivers/gpio/gpio-mb86s7x.c @@ -146,7 +146,6 @@ static void mb86s70_gpio_set(struct gpio_chip *gc, unsigned gpio, int value) static int mb86s70_gpio_probe(struct platform_device *pdev) { struct mb86s70_gpio_chip *gchip; - struct resource *res; int ret; gchip = devm_kzalloc(&pdev->dev, sizeof(*gchip), GFP_KERNEL); @@ -155,8 +154,7 @@ static int mb86s70_gpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, gchip); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - gchip->base = devm_ioremap_resource(&pdev->dev, res); + gchip->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(gchip->base)) return PTR_ERR(gchip->base); From 92d718fd47749ed79a3823947690dede1fd673cc Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:54:59 +0100 Subject: [PATCH 41/85] drivers: gpio: mt7621: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Reviewed-by: Matthias Brugger Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mt7621.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-mt7621.c b/drivers/gpio/gpio-mt7621.c index 74401e0adb29..79654fb2e50f 100644 --- a/drivers/gpio/gpio-mt7621.c +++ b/drivers/gpio/gpio-mt7621.c @@ -293,7 +293,6 @@ mediatek_gpio_bank_probe(struct device *dev, static int mediatek_gpio_probe(struct platform_device *pdev) { - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct mtk *mtk; @@ -304,7 +303,7 @@ mediatek_gpio_probe(struct platform_device *pdev) if (!mtk) return -ENOMEM; - mtk->base = devm_ioremap_resource(dev, res); + mtk->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mtk->base)) return PTR_ERR(mtk->base); From dc02a0cacb6cfe37ca7c8590e46c1a3c985c3092 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:55:00 +0100 Subject: [PATCH 42/85] drivers: gpio: mvebu: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mvebu.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index f97ed32b8beb..059094ac44cb 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -1038,11 +1038,9 @@ static const struct regmap_config mvebu_gpio_regmap_config = { static int mvebu_gpio_probe_raw(struct platform_device *pdev, struct mvebu_gpio_chip *mvchip) { - struct resource *res; void __iomem *base; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); @@ -1062,8 +1060,7 @@ static int mvebu_gpio_probe_raw(struct platform_device *pdev, * per-CPU registers */ if (mvchip->soc_variant == MVEBU_GPIO_SOC_VARIANT_ARMADAXP) { - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(base)) return PTR_ERR(base); From 123ac0e5356cebb7b1bc51d5fb141a74d0a9db43 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:55:01 +0100 Subject: [PATCH 43/85] drivers: gpio: mxc: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mxc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index e86e61dda4b7..b2813580c582 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -411,7 +411,6 @@ static int mxc_gpio_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct mxc_gpio_port *port; - struct resource *iores; int irq_base; int err; @@ -423,8 +422,7 @@ static int mxc_gpio_probe(struct platform_device *pdev) port->dev = &pdev->dev; - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - port->base = devm_ioremap_resource(&pdev->dev, iores); + port->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(port->base)) return PTR_ERR(port->base); From 037ae5bc377859916a298c8656d56bb034e8d219 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 20:48:21 +0100 Subject: [PATCH 44/85] drivers: gpio: octeon: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-octeon.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-octeon.c b/drivers/gpio/gpio-octeon.c index 1b19c88ea7bb..afb0e8a791e5 100644 --- a/drivers/gpio/gpio-octeon.c +++ b/drivers/gpio/gpio-octeon.c @@ -82,7 +82,6 @@ static int octeon_gpio_probe(struct platform_device *pdev) { struct octeon_gpio *gpio; struct gpio_chip *chip; - struct resource *res_mem; void __iomem *reg_base; int err = 0; @@ -91,8 +90,7 @@ static int octeon_gpio_probe(struct platform_device *pdev) return -ENOMEM; chip = &gpio->chip; - res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg_base = devm_ioremap_resource(&pdev->dev, res_mem); + reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg_base)) return PTR_ERR(reg_base); From 542c25b7a209697f383b781da2762154fb59eaa8 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:55:04 +0100 Subject: [PATCH 45/85] drivers: gpio: pxa: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pxa.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index bcc6be4a5cb2..dd479607b66a 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -622,7 +622,6 @@ static int pxa_gpio_probe(struct platform_device *pdev) { struct pxa_gpio_chip *pchip; struct pxa_gpio_bank *c; - struct resource *res; struct clk *clk; struct pxa_gpio_platform_data *info; void __iomem *gpio_reg_base; @@ -665,11 +664,8 @@ static int pxa_gpio_probe(struct platform_device *pdev) pchip->irq0 = irq0; pchip->irq1 = irq1; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -EINVAL; - gpio_reg_base = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); + + gpio_reg_base = devm_platform_ioremap_resource(pdev, 0); if (!gpio_reg_base) return -EINVAL; From ecbf7c2e8bb323cf96758b3911766058fabc360e Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:55:06 +0100 Subject: [PATCH 46/85] drivers: gpio: rcar: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Reviewed-by: Geert Uytterhoeven Signed-off-by: Linus Walleij --- drivers/gpio/gpio-rcar.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index 500a3596aaf4..70e95fc4779f 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -430,7 +430,7 @@ static int gpio_rcar_parse_dt(struct gpio_rcar_priv *p, unsigned int *npins) static int gpio_rcar_probe(struct platform_device *pdev) { struct gpio_rcar_priv *p; - struct resource *io, *irq; + struct resource *irq; struct gpio_chip *gpio_chip; struct irq_chip *irq_chip; struct device *dev = &pdev->dev; @@ -461,8 +461,7 @@ static int gpio_rcar_probe(struct platform_device *pdev) goto err0; } - io = platform_get_resource(pdev, IORESOURCE_MEM, 0); - p->base = devm_ioremap_resource(dev, io); + p->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(p->base)) { ret = PTR_ERR(p->base); goto err0; From 7290f152fecc2db1f6262e040f457b723bba8aa1 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:55:07 +0100 Subject: [PATCH 47/85] drivers: gpio: spear-spics: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-spear-spics.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-spear-spics.c b/drivers/gpio/gpio-spear-spics.c index ee3039f091f4..6eca531b7d96 100644 --- a/drivers/gpio/gpio-spear-spics.c +++ b/drivers/gpio/gpio-spear-spics.c @@ -122,15 +122,13 @@ static int spics_gpio_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct spear_spics *spics; - struct resource *res; int ret; spics = devm_kzalloc(&pdev->dev, sizeof(*spics), GFP_KERNEL); if (!spics) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - spics->base = devm_ioremap_resource(&pdev->dev, res); + spics->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(spics->base)) return PTR_ERR(spics->base); From c68a520f6a05eef09fb64784625f38b6caf1c93c Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:55:09 +0100 Subject: [PATCH 48/85] drivers: gpio: sta2x11: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-sta2x11.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c index 2283c869ad5d..a51c310708b8 100644 --- a/drivers/gpio/gpio-sta2x11.c +++ b/drivers/gpio/gpio-sta2x11.c @@ -360,7 +360,6 @@ static int gsta_probe(struct platform_device *dev) struct pci_dev *pdev; struct sta2x11_gpio_pdata *gpio_pdata; struct gsta_gpio *chip; - struct resource *res; pdev = *(struct pci_dev **)dev_get_platdata(&dev->dev); gpio_pdata = dev_get_platdata(&pdev->dev); @@ -369,13 +368,11 @@ static int gsta_probe(struct platform_device *dev) dev_err(&dev->dev, "no gpio config\n"); pr_debug("gpio config: %p\n", gpio_pdata); - res = platform_get_resource(dev, IORESOURCE_MEM, 0); - chip = devm_kzalloc(&dev->dev, sizeof(*chip), GFP_KERNEL); if (!chip) return -ENOMEM; chip->dev = &dev->dev; - chip->reg_base = devm_ioremap_resource(&dev->dev, res); + chip->reg_base = devm_platform_ioremap_resource(dev, 0); if (IS_ERR(chip->reg_base)) return PTR_ERR(chip->reg_base); From 6ba7c53b799d2cfbd18d5cc63bc12fb95550ca02 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:55:10 +0100 Subject: [PATCH 49/85] drivers: gpio: stp-xway: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-stp-xway.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c index 19972084c45b..8a319d56c5de 100644 --- a/drivers/gpio/gpio-stp-xway.c +++ b/drivers/gpio/gpio-stp-xway.c @@ -210,7 +210,6 @@ static int xway_stp_hw_init(struct xway_stp *chip) static int xway_stp_probe(struct platform_device *pdev) { - struct resource *res; u32 shadow, groups, dsl, phy; struct xway_stp *chip; struct clk *clk; @@ -220,8 +219,7 @@ static int xway_stp_probe(struct platform_device *pdev) if (!chip) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - chip->virt = devm_ioremap_resource(&pdev->dev, res); + chip->virt = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(chip->virt)) return PTR_ERR(chip->virt); From 5b827ff598b08085e7e8b64fa06420e9dc8ef620 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:55:11 +0100 Subject: [PATCH 50/85] drivers: gpio: tb10x: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tb10x.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c index d5e5d19f4c0a..6bbac6c83f29 100644 --- a/drivers/gpio/gpio-tb10x.c +++ b/drivers/gpio/gpio-tb10x.c @@ -120,7 +120,6 @@ static irqreturn_t tb10x_gpio_irq_cascade(int irq, void *data) static int tb10x_gpio_probe(struct platform_device *pdev) { struct tb10x_gpio *tb10x_gpio; - struct resource *mem; struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; int ret = -EBUSY; @@ -136,8 +135,7 @@ static int tb10x_gpio_probe(struct platform_device *pdev) if (tb10x_gpio == NULL) return -ENOMEM; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - tb10x_gpio->base = devm_ioremap_resource(dev, mem); + tb10x_gpio->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(tb10x_gpio->base)) return PTR_ERR(tb10x_gpio->base); From a0b81f1ca4323fcb78781a46af0f02b5a0efd47a Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:55:12 +0100 Subject: [PATCH 51/85] drivers: gpio: tegra: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Acked-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/gpio/gpio-tegra.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 1ececf2c3282..6d9b6906b9d0 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -569,7 +569,6 @@ static const struct dev_pm_ops tegra_gpio_pm_ops = { static int tegra_gpio_probe(struct platform_device *pdev) { struct tegra_gpio_info *tgi; - struct resource *res; struct tegra_gpio_bank *bank; unsigned int gpio, i, j; int ret; @@ -645,8 +644,7 @@ static int tegra_gpio_probe(struct platform_device *pdev) bank->tgi = tgi; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - tgi->regs = devm_ioremap_resource(&pdev->dev, res); + tgi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(tgi->regs)) return PTR_ERR(tgi->regs); From aa6c9b91089b40d7efa411cec3de537f324debd8 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:55:13 +0100 Subject: [PATCH 52/85] drivers: gpio: timberdale: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-timberdale.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index 314e300d6ba3..1c70e831069c 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -229,7 +229,6 @@ static int timbgpio_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct gpio_chip *gc; struct timbgpio *tgpio; - struct resource *iomem; struct timbgpio_platform_data *pdata = dev_get_platdata(&pdev->dev); int irq = platform_get_irq(pdev, 0); @@ -246,8 +245,7 @@ static int timbgpio_probe(struct platform_device *pdev) spin_lock_init(&tgpio->lock); - iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - tgpio->membase = devm_ioremap_resource(dev, iomem); + tgpio->membase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(tgpio->membase)) return PTR_ERR(tgpio->membase); From f7a6e467eaf1e188c58da741e046e28a178cf274 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:55:14 +0100 Subject: [PATCH 53/85] drivers: gpio: ts4800: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ts4800.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-ts4800.c b/drivers/gpio/gpio-ts4800.c index c2a80b4cbf32..8c0d82d926dd 100644 --- a/drivers/gpio/gpio-ts4800.c +++ b/drivers/gpio/gpio-ts4800.c @@ -23,7 +23,6 @@ static int ts4800_gpio_probe(struct platform_device *pdev) { struct device_node *node; struct gpio_chip *chip; - struct resource *res; void __iomem *base_addr; int retval; u32 ngpios; @@ -32,8 +31,7 @@ static int ts4800_gpio_probe(struct platform_device *pdev) if (!chip) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base_addr = devm_ioremap_resource(&pdev->dev, res); + base_addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base_addr)) return PTR_ERR(base_addr); From 83fa76b65cd2008ca0c657830cdc2a18699672b7 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:55:15 +0100 Subject: [PATCH 54/85] drivers: gpio: uniphier: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Acked-by: Masahiro Yamada Signed-off-by: Linus Walleij --- drivers/gpio/gpio-uniphier.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c index 0f662b297a95..93cdcc41e9fb 100644 --- a/drivers/gpio/gpio-uniphier.c +++ b/drivers/gpio/gpio-uniphier.c @@ -346,7 +346,6 @@ static int uniphier_gpio_probe(struct platform_device *pdev) struct uniphier_gpio_priv *priv; struct gpio_chip *chip; struct irq_chip *irq_chip; - struct resource *regs; unsigned int nregs; u32 ngpios; int ret; @@ -370,8 +369,7 @@ static int uniphier_gpio_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->regs = devm_ioremap_resource(dev, regs); + priv->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->regs)) return PTR_ERR(priv->regs); From df53665b4f18ed5ee68a4ec814ae3bc9951931ed Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:55:16 +0100 Subject: [PATCH 55/85] drivers: gpio: vf610: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-vf610.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 541fa6ac399d..4b86a2dee7f2 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -251,7 +251,6 @@ static int vf610_gpio_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct vf610_gpio_port *port; - struct resource *iores; struct gpio_chip *gc; int i; int ret; @@ -261,13 +260,11 @@ static int vf610_gpio_probe(struct platform_device *pdev) return -ENOMEM; port->sdata = of_device_get_match_data(dev); - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - port->base = devm_ioremap_resource(dev, iores); + port->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(port->base)) return PTR_ERR(port->base); - iores = platform_get_resource(pdev, IORESOURCE_MEM, 1); - port->gpio_base = devm_ioremap_resource(dev, iores); + port->gpio_base = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(port->gpio_base)) return PTR_ERR(port->gpio_base); From 6ff49fba4007f5705af017f56f941e9957baae76 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:55:18 +0100 Subject: [PATCH 56/85] drivers: gpio: xgene-sb: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-xgene-sb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-xgene-sb.c b/drivers/gpio/gpio-xgene-sb.c index 2eb76f35aa7e..641a05181017 100644 --- a/drivers/gpio/gpio-xgene-sb.c +++ b/drivers/gpio/gpio-xgene-sb.c @@ -229,7 +229,6 @@ static int xgene_gpio_sb_probe(struct platform_device *pdev) { struct xgene_gpio_sb *priv; int ret; - struct resource *res; void __iomem *regs; struct irq_domain *parent_domain = NULL; u32 val32; @@ -238,8 +237,7 @@ static int xgene_gpio_sb_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_ioremap_resource(&pdev->dev, res); + regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) return PTR_ERR(regs); From 8d86f985ac4118cf3ea6168cd593c8fd96a1d83d Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:55:19 +0100 Subject: [PATCH 57/85] drivers: gpio: zx: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-zx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-zx.c b/drivers/gpio/gpio-zx.c index 5eacad9b2692..fb927559aefa 100644 --- a/drivers/gpio/gpio-zx.c +++ b/drivers/gpio/gpio-zx.c @@ -218,15 +218,13 @@ static int zx_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct zx_gpio *chip; - struct resource *res; int irq, id, ret; chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); if (!chip) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - chip->base = devm_ioremap_resource(dev, res); + chip->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(chip->base)) return PTR_ERR(chip->base); From 3883de0287d0b9beacb8715854e7f41ed2cbefa5 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:55:20 +0100 Subject: [PATCH 58/85] drivers: gpio: xlp: devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-xlp.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-xlp.c b/drivers/gpio/gpio-xlp.c index 0a3607fd21af..54d3359444f3 100644 --- a/drivers/gpio/gpio-xlp.c +++ b/drivers/gpio/gpio-xlp.c @@ -290,22 +290,17 @@ MODULE_DEVICE_TABLE(of, xlp_gpio_of_ids); static int xlp_gpio_probe(struct platform_device *pdev) { struct gpio_chip *gc; - struct resource *iores; struct xlp_gpio_priv *priv; void __iomem *gpio_base; int irq_base, irq, err; int ngpio; u32 soc_type; - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!iores) - return -ENODEV; - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - gpio_base = devm_ioremap_resource(&pdev->dev, iores); + gpio_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(gpio_base)) return PTR_ERR(gpio_base); From 77bc0e69c3e264214e5234bcde5654f40fe1e7db Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 19:55:21 +0100 Subject: [PATCH 59/85] gpio: zynq: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Linus Walleij --- drivers/gpio/gpio-zynq.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 00ff7b1fa8a1..9392edaeec3f 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -834,7 +834,6 @@ static int zynq_gpio_probe(struct platform_device *pdev) int ret, bank_num; struct zynq_gpio *gpio; struct gpio_chip *chip; - struct resource *res; const struct of_device_id *match; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); @@ -849,8 +848,7 @@ static int zynq_gpio_probe(struct platform_device *pdev) gpio->p_data = match->data; platform_set_drvdata(pdev, gpio); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - gpio->base_addr = devm_ioremap_resource(&pdev->dev, res); + gpio->base_addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(gpio->base_addr)) return PTR_ERR(gpio->base_addr); From 430c1ce304e4e190a89b065aa75d7a0ea725560b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Thu, 7 Mar 2019 14:38:04 +0100 Subject: [PATCH 60/85] pinctrl: mcp23s08: debugfs: remove custom printer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The comment for this dbg_show says that it is supposed to return more than what the generic code is showing, including de-glitching. That's wrong because: - this chip does not support deglitching, - the code does not print anything extra compared to the generic handler, - its behavior is different because it skips unrequested GPIOs; the generic code prints their names if they're assigned There is an important difference, though. Previously, dbg_show would re-check some registers to see if they still match what the regmap thinks should be in there. This was semi-useful when develpoing the HW board because it immediately pointed to SPI wiring problem if a CS connection was missing (0xffs are easy to see). However, I do not think that this makes much sense -- and one could always do this in some other way if needed. Signed-off-by: Jan Kundrát Cc: Phil Reid Cc: Linus Walleij Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-mcp23s08.c | 110 ----------------------------- 1 file changed, 110 deletions(-) diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c index 5d7a8514def9..83dbab7c11bc 100644 --- a/drivers/pinctrl/pinctrl-mcp23s08.c +++ b/drivers/pinctrl/pinctrl-mcp23s08.c @@ -656,115 +656,6 @@ static int mcp23s08_irqchip_setup(struct mcp23s08 *mcp) /*----------------------------------------------------------------------*/ -#ifdef CONFIG_DEBUG_FS - -#include - -/* - * This compares the chip's registers with the register - * cache and corrects any incorrectly set register. This - * can be used to fix state for MCP23xxx, that temporary - * lost its power supply. - */ -#define MCP23S08_CONFIG_REGS 7 -static int __check_mcp23s08_reg_cache(struct mcp23s08 *mcp) -{ - int cached[MCP23S08_CONFIG_REGS]; - int err = 0, i; - - /* read cached config registers */ - for (i = 0; i < MCP23S08_CONFIG_REGS; i++) { - err = mcp_read(mcp, i, &cached[i]); - if (err) - goto out; - } - - regcache_cache_bypass(mcp->regmap, true); - - for (i = 0; i < MCP23S08_CONFIG_REGS; i++) { - int uncached; - err = mcp_read(mcp, i, &uncached); - if (err) - goto out; - - if (uncached != cached[i]) { - dev_err(mcp->dev, "restoring reg 0x%02x from 0x%04x to 0x%04x (power-loss?)\n", - i, uncached, cached[i]); - mcp_write(mcp, i, cached[i]); - } - } - -out: - if (err) - dev_err(mcp->dev, "read error: reg=%02x, err=%d", i, err); - regcache_cache_bypass(mcp->regmap, false); - return err; -} - -/* - * This shows more info than the generic gpio dump code: - * pullups, deglitching, open drain drive. - */ -static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip) -{ - struct mcp23s08 *mcp; - char bank; - int t; - unsigned mask; - int iodir, gpio, gppu; - - mcp = gpiochip_get_data(chip); - - /* NOTE: we only handle one bank for now ... */ - bank = '0' + ((mcp->addr >> 1) & 0x7); - - mutex_lock(&mcp->lock); - - t = __check_mcp23s08_reg_cache(mcp); - if (t) { - seq_printf(s, " I/O Error\n"); - goto done; - } - t = mcp_read(mcp, MCP_IODIR, &iodir); - if (t) { - seq_printf(s, " I/O Error\n"); - goto done; - } - t = mcp_read(mcp, MCP_GPIO, &gpio); - if (t) { - seq_printf(s, " I/O Error\n"); - goto done; - } - t = mcp_read(mcp, MCP_GPPU, &gppu); - if (t) { - seq_printf(s, " I/O Error\n"); - goto done; - } - - for (t = 0, mask = BIT(0); t < chip->ngpio; t++, mask <<= 1) { - const char *label; - - label = gpiochip_is_requested(chip, t); - if (!label) - continue; - - seq_printf(s, " gpio-%-3d P%c.%d (%-12s) %s %s %s\n", - chip->base + t, bank, t, label, - (iodir & mask) ? "in " : "out", - (gpio & mask) ? "hi" : "lo", - (gppu & mask) ? "up" : " "); - /* NOTE: ignoring the irq-related registers */ - } -done: - mutex_unlock(&mcp->lock); -} - -#else -#define mcp23s08_dbg_show NULL -#endif - -/*----------------------------------------------------------------------*/ - static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, void *data, unsigned addr, unsigned type, unsigned int base, int cs) @@ -785,7 +676,6 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, mcp->chip.get = mcp23s08_get; mcp->chip.direction_output = mcp23s08_direction_output; mcp->chip.set = mcp23s08_set; - mcp->chip.dbg_show = mcp23s08_dbg_show; #ifdef CONFIG_OF_GPIO mcp->chip.of_gpio_n_cells = 2; mcp->chip.of_node = dev->of_node; From 7c68571f77fbc1d2a6ed70dbc9b2c0782d282d43 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 7 Mar 2019 11:33:32 +0100 Subject: [PATCH 61/85] gpio: omap: avoid clang warning clang warns about a tentative array definition in the gpio-omap driver: drivers/gpio/gpio-omap.c:1282:34: error: tentative array definition assumed to have one element [-Werror] static const struct of_device_id omap_gpio_match[]; It's best to just reorder the entire file to avoid forward declarations, which lets us use the regular declaration. To do this, the unnecessary CONFIG_OF check must also be removed. Signed-off-by: Arnd Bergmann Reviewed-by: Grygorii Strashko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 569 +++++++++++++++++++-------------------- 1 file changed, 277 insertions(+), 292 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 7f33024b6d83..33a312688072 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1251,8 +1251,195 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) return ret; } -static void omap_gpio_idle(struct gpio_bank *bank, bool may_lose_context); -static void omap_gpio_unidle(struct gpio_bank *bank); +static void omap_gpio_init_context(struct gpio_bank *p) +{ + struct omap_gpio_reg_offs *regs = p->regs; + void __iomem *base = p->base; + + p->context.ctrl = readl_relaxed(base + regs->ctrl); + p->context.oe = readl_relaxed(base + regs->direction); + p->context.wake_en = readl_relaxed(base + regs->wkup_en); + p->context.leveldetect0 = readl_relaxed(base + regs->leveldetect0); + p->context.leveldetect1 = readl_relaxed(base + regs->leveldetect1); + p->context.risingdetect = readl_relaxed(base + regs->risingdetect); + p->context.fallingdetect = readl_relaxed(base + regs->fallingdetect); + p->context.irqenable1 = readl_relaxed(base + regs->irqenable); + p->context.irqenable2 = readl_relaxed(base + regs->irqenable2); + + if (regs->set_dataout && p->regs->clr_dataout) + p->context.dataout = readl_relaxed(base + regs->set_dataout); + else + p->context.dataout = readl_relaxed(base + regs->dataout); + + p->context_valid = true; +} + +static void omap_gpio_restore_context(struct gpio_bank *bank) +{ + writel_relaxed(bank->context.wake_en, + bank->base + bank->regs->wkup_en); + writel_relaxed(bank->context.ctrl, bank->base + bank->regs->ctrl); + writel_relaxed(bank->context.leveldetect0, + bank->base + bank->regs->leveldetect0); + writel_relaxed(bank->context.leveldetect1, + bank->base + bank->regs->leveldetect1); + writel_relaxed(bank->context.risingdetect, + bank->base + bank->regs->risingdetect); + writel_relaxed(bank->context.fallingdetect, + bank->base + bank->regs->fallingdetect); + if (bank->regs->set_dataout && bank->regs->clr_dataout) + writel_relaxed(bank->context.dataout, + bank->base + bank->regs->set_dataout); + else + writel_relaxed(bank->context.dataout, + bank->base + bank->regs->dataout); + writel_relaxed(bank->context.oe, bank->base + bank->regs->direction); + + if (bank->dbck_enable_mask) { + writel_relaxed(bank->context.debounce, bank->base + + bank->regs->debounce); + writel_relaxed(bank->context.debounce_en, + bank->base + bank->regs->debounce_en); + } + + writel_relaxed(bank->context.irqenable1, + bank->base + bank->regs->irqenable); + writel_relaxed(bank->context.irqenable2, + bank->base + bank->regs->irqenable2); +} + +static void omap_gpio_idle(struct gpio_bank *bank, bool may_lose_context) +{ + struct device *dev = bank->chip.parent; + u32 l1 = 0, l2 = 0; + + if (bank->funcs.idle_enable_level_quirk) + bank->funcs.idle_enable_level_quirk(bank); + + if (!bank->enabled_non_wakeup_gpios) + goto update_gpio_context_count; + + if (!may_lose_context) + goto update_gpio_context_count; + + /* + * If going to OFF, remove triggering for all + * non-wakeup GPIOs. Otherwise spurious IRQs will be + * generated. See OMAP2420 Errata item 1.101. + */ + bank->saved_datain = readl_relaxed(bank->base + + bank->regs->datain); + l1 = bank->context.fallingdetect; + l2 = bank->context.risingdetect; + + l1 &= ~bank->enabled_non_wakeup_gpios; + l2 &= ~bank->enabled_non_wakeup_gpios; + + writel_relaxed(l1, bank->base + bank->regs->fallingdetect); + writel_relaxed(l2, bank->base + bank->regs->risingdetect); + + bank->workaround_enabled = true; + +update_gpio_context_count: + if (bank->get_context_loss_count) + bank->context_loss_count = + bank->get_context_loss_count(dev); + + omap_gpio_dbck_disable(bank); +} + +static void omap_gpio_unidle(struct gpio_bank *bank) +{ + struct device *dev = bank->chip.parent; + u32 l = 0, gen, gen0, gen1; + int c; + + /* + * On the first resume during the probe, the context has not + * been initialised and so initialise it now. Also initialise + * the context loss count. + */ + if (bank->loses_context && !bank->context_valid) { + omap_gpio_init_context(bank); + + if (bank->get_context_loss_count) + bank->context_loss_count = + bank->get_context_loss_count(dev); + } + + omap_gpio_dbck_enable(bank); + + if (bank->funcs.idle_disable_level_quirk) + bank->funcs.idle_disable_level_quirk(bank); + + if (bank->loses_context) { + if (!bank->get_context_loss_count) { + omap_gpio_restore_context(bank); + } else { + c = bank->get_context_loss_count(dev); + if (c != bank->context_loss_count) { + omap_gpio_restore_context(bank); + } else { + return; + } + } + } + + if (!bank->workaround_enabled) + return; + + l = readl_relaxed(bank->base + bank->regs->datain); + + /* + * Check if any of the non-wakeup interrupt GPIOs have changed + * state. If so, generate an IRQ by software. This is + * horribly racy, but it's the best we can do to work around + * this silicon bug. + */ + l ^= bank->saved_datain; + l &= bank->enabled_non_wakeup_gpios; + + /* + * No need to generate IRQs for the rising edge for gpio IRQs + * configured with falling edge only; and vice versa. + */ + gen0 = l & bank->context.fallingdetect; + gen0 &= bank->saved_datain; + + gen1 = l & bank->context.risingdetect; + gen1 &= ~(bank->saved_datain); + + /* FIXME: Consider GPIO IRQs with level detections properly! */ + gen = l & (~(bank->context.fallingdetect) & + ~(bank->context.risingdetect)); + /* Consider all GPIO IRQs needed to be updated */ + gen |= gen0 | gen1; + + if (gen) { + u32 old0, old1; + + old0 = readl_relaxed(bank->base + bank->regs->leveldetect0); + old1 = readl_relaxed(bank->base + bank->regs->leveldetect1); + + if (!bank->regs->irqstatus_raw0) { + writel_relaxed(old0 | gen, bank->base + + bank->regs->leveldetect0); + writel_relaxed(old1 | gen, bank->base + + bank->regs->leveldetect1); + } + + if (bank->regs->irqstatus_raw0) { + writel_relaxed(old0 | l, bank->base + + bank->regs->leveldetect0); + writel_relaxed(old1 | l, bank->base + + bank->regs->leveldetect1); + } + writel_relaxed(old0, bank->base + bank->regs->leveldetect0); + writel_relaxed(old1, bank->base + bank->regs->leveldetect1); + } + + bank->workaround_enabled = false; +} static int gpio_omap_cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v) @@ -1281,7 +1468,93 @@ static int gpio_omap_cpu_notifier(struct notifier_block *nb, return NOTIFY_OK; } -static const struct of_device_id omap_gpio_match[]; +static struct omap_gpio_reg_offs omap2_gpio_regs = { + .revision = OMAP24XX_GPIO_REVISION, + .direction = OMAP24XX_GPIO_OE, + .datain = OMAP24XX_GPIO_DATAIN, + .dataout = OMAP24XX_GPIO_DATAOUT, + .set_dataout = OMAP24XX_GPIO_SETDATAOUT, + .clr_dataout = OMAP24XX_GPIO_CLEARDATAOUT, + .irqstatus = OMAP24XX_GPIO_IRQSTATUS1, + .irqstatus2 = OMAP24XX_GPIO_IRQSTATUS2, + .irqenable = OMAP24XX_GPIO_IRQENABLE1, + .irqenable2 = OMAP24XX_GPIO_IRQENABLE2, + .set_irqenable = OMAP24XX_GPIO_SETIRQENABLE1, + .clr_irqenable = OMAP24XX_GPIO_CLEARIRQENABLE1, + .debounce = OMAP24XX_GPIO_DEBOUNCE_VAL, + .debounce_en = OMAP24XX_GPIO_DEBOUNCE_EN, + .ctrl = OMAP24XX_GPIO_CTRL, + .wkup_en = OMAP24XX_GPIO_WAKE_EN, + .leveldetect0 = OMAP24XX_GPIO_LEVELDETECT0, + .leveldetect1 = OMAP24XX_GPIO_LEVELDETECT1, + .risingdetect = OMAP24XX_GPIO_RISINGDETECT, + .fallingdetect = OMAP24XX_GPIO_FALLINGDETECT, +}; + +static struct omap_gpio_reg_offs omap4_gpio_regs = { + .revision = OMAP4_GPIO_REVISION, + .direction = OMAP4_GPIO_OE, + .datain = OMAP4_GPIO_DATAIN, + .dataout = OMAP4_GPIO_DATAOUT, + .set_dataout = OMAP4_GPIO_SETDATAOUT, + .clr_dataout = OMAP4_GPIO_CLEARDATAOUT, + .irqstatus = OMAP4_GPIO_IRQSTATUS0, + .irqstatus2 = OMAP4_GPIO_IRQSTATUS1, + .irqenable = OMAP4_GPIO_IRQSTATUSSET0, + .irqenable2 = OMAP4_GPIO_IRQSTATUSSET1, + .set_irqenable = OMAP4_GPIO_IRQSTATUSSET0, + .clr_irqenable = OMAP4_GPIO_IRQSTATUSCLR0, + .debounce = OMAP4_GPIO_DEBOUNCINGTIME, + .debounce_en = OMAP4_GPIO_DEBOUNCENABLE, + .ctrl = OMAP4_GPIO_CTRL, + .wkup_en = OMAP4_GPIO_IRQWAKEN0, + .leveldetect0 = OMAP4_GPIO_LEVELDETECT0, + .leveldetect1 = OMAP4_GPIO_LEVELDETECT1, + .risingdetect = OMAP4_GPIO_RISINGDETECT, + .fallingdetect = OMAP4_GPIO_FALLINGDETECT, +}; + +/* + * Note that omap2 does not currently support idle modes with context loss so + * no need to add OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER quirk flag to save + * and restore context. + */ +static const struct omap_gpio_platform_data omap2_pdata = { + .regs = &omap2_gpio_regs, + .bank_width = 32, + .dbck_flag = false, +}; + +static const struct omap_gpio_platform_data omap3_pdata = { + .regs = &omap2_gpio_regs, + .bank_width = 32, + .dbck_flag = true, + .quirks = OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER, +}; + +static const struct omap_gpio_platform_data omap4_pdata = { + .regs = &omap4_gpio_regs, + .bank_width = 32, + .dbck_flag = true, + .quirks = OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER, +}; + +static const struct of_device_id omap_gpio_match[] = { + { + .compatible = "ti,omap4-gpio", + .data = &omap4_pdata, + }, + { + .compatible = "ti,omap3-gpio", + .data = &omap3_pdata, + }, + { + .compatible = "ti,omap2-gpio", + .data = &omap2_pdata, + }, + { }, +}; +MODULE_DEVICE_TABLE(of, omap_gpio_match); static int omap_gpio_probe(struct platform_device *pdev) { @@ -1439,200 +1712,6 @@ static int omap_gpio_remove(struct platform_device *pdev) return 0; } -static void omap_gpio_restore_context(struct gpio_bank *bank); - -static void omap_gpio_idle(struct gpio_bank *bank, bool may_lose_context) -{ - struct device *dev = bank->chip.parent; - u32 l1 = 0, l2 = 0; - - if (bank->funcs.idle_enable_level_quirk) - bank->funcs.idle_enable_level_quirk(bank); - - if (!bank->enabled_non_wakeup_gpios) - goto update_gpio_context_count; - - if (!may_lose_context) - goto update_gpio_context_count; - - /* - * If going to OFF, remove triggering for all - * non-wakeup GPIOs. Otherwise spurious IRQs will be - * generated. See OMAP2420 Errata item 1.101. - */ - bank->saved_datain = readl_relaxed(bank->base + - bank->regs->datain); - l1 = bank->context.fallingdetect; - l2 = bank->context.risingdetect; - - l1 &= ~bank->enabled_non_wakeup_gpios; - l2 &= ~bank->enabled_non_wakeup_gpios; - - writel_relaxed(l1, bank->base + bank->regs->fallingdetect); - writel_relaxed(l2, bank->base + bank->regs->risingdetect); - - bank->workaround_enabled = true; - -update_gpio_context_count: - if (bank->get_context_loss_count) - bank->context_loss_count = - bank->get_context_loss_count(dev); - - omap_gpio_dbck_disable(bank); -} - -static void omap_gpio_init_context(struct gpio_bank *p); - -static void omap_gpio_unidle(struct gpio_bank *bank) -{ - struct device *dev = bank->chip.parent; - u32 l = 0, gen, gen0, gen1; - int c; - - /* - * On the first resume during the probe, the context has not - * been initialised and so initialise it now. Also initialise - * the context loss count. - */ - if (bank->loses_context && !bank->context_valid) { - omap_gpio_init_context(bank); - - if (bank->get_context_loss_count) - bank->context_loss_count = - bank->get_context_loss_count(dev); - } - - omap_gpio_dbck_enable(bank); - - if (bank->funcs.idle_disable_level_quirk) - bank->funcs.idle_disable_level_quirk(bank); - - if (bank->loses_context) { - if (!bank->get_context_loss_count) { - omap_gpio_restore_context(bank); - } else { - c = bank->get_context_loss_count(dev); - if (c != bank->context_loss_count) { - omap_gpio_restore_context(bank); - } else { - return; - } - } - } - - if (!bank->workaround_enabled) - return; - - l = readl_relaxed(bank->base + bank->regs->datain); - - /* - * Check if any of the non-wakeup interrupt GPIOs have changed - * state. If so, generate an IRQ by software. This is - * horribly racy, but it's the best we can do to work around - * this silicon bug. - */ - l ^= bank->saved_datain; - l &= bank->enabled_non_wakeup_gpios; - - /* - * No need to generate IRQs for the rising edge for gpio IRQs - * configured with falling edge only; and vice versa. - */ - gen0 = l & bank->context.fallingdetect; - gen0 &= bank->saved_datain; - - gen1 = l & bank->context.risingdetect; - gen1 &= ~(bank->saved_datain); - - /* FIXME: Consider GPIO IRQs with level detections properly! */ - gen = l & (~(bank->context.fallingdetect) & - ~(bank->context.risingdetect)); - /* Consider all GPIO IRQs needed to be updated */ - gen |= gen0 | gen1; - - if (gen) { - u32 old0, old1; - - old0 = readl_relaxed(bank->base + bank->regs->leveldetect0); - old1 = readl_relaxed(bank->base + bank->regs->leveldetect1); - - if (!bank->regs->irqstatus_raw0) { - writel_relaxed(old0 | gen, bank->base + - bank->regs->leveldetect0); - writel_relaxed(old1 | gen, bank->base + - bank->regs->leveldetect1); - } - - if (bank->regs->irqstatus_raw0) { - writel_relaxed(old0 | l, bank->base + - bank->regs->leveldetect0); - writel_relaxed(old1 | l, bank->base + - bank->regs->leveldetect1); - } - writel_relaxed(old0, bank->base + bank->regs->leveldetect0); - writel_relaxed(old1, bank->base + bank->regs->leveldetect1); - } - - bank->workaround_enabled = false; -} - -static void omap_gpio_init_context(struct gpio_bank *p) -{ - struct omap_gpio_reg_offs *regs = p->regs; - void __iomem *base = p->base; - - p->context.ctrl = readl_relaxed(base + regs->ctrl); - p->context.oe = readl_relaxed(base + regs->direction); - p->context.wake_en = readl_relaxed(base + regs->wkup_en); - p->context.leveldetect0 = readl_relaxed(base + regs->leveldetect0); - p->context.leveldetect1 = readl_relaxed(base + regs->leveldetect1); - p->context.risingdetect = readl_relaxed(base + regs->risingdetect); - p->context.fallingdetect = readl_relaxed(base + regs->fallingdetect); - p->context.irqenable1 = readl_relaxed(base + regs->irqenable); - p->context.irqenable2 = readl_relaxed(base + regs->irqenable2); - - if (regs->set_dataout && p->regs->clr_dataout) - p->context.dataout = readl_relaxed(base + regs->set_dataout); - else - p->context.dataout = readl_relaxed(base + regs->dataout); - - p->context_valid = true; -} - -static void omap_gpio_restore_context(struct gpio_bank *bank) -{ - writel_relaxed(bank->context.wake_en, - bank->base + bank->regs->wkup_en); - writel_relaxed(bank->context.ctrl, bank->base + bank->regs->ctrl); - writel_relaxed(bank->context.leveldetect0, - bank->base + bank->regs->leveldetect0); - writel_relaxed(bank->context.leveldetect1, - bank->base + bank->regs->leveldetect1); - writel_relaxed(bank->context.risingdetect, - bank->base + bank->regs->risingdetect); - writel_relaxed(bank->context.fallingdetect, - bank->base + bank->regs->fallingdetect); - if (bank->regs->set_dataout && bank->regs->clr_dataout) - writel_relaxed(bank->context.dataout, - bank->base + bank->regs->set_dataout); - else - writel_relaxed(bank->context.dataout, - bank->base + bank->regs->dataout); - writel_relaxed(bank->context.oe, bank->base + bank->regs->direction); - - if (bank->dbck_enable_mask) { - writel_relaxed(bank->context.debounce, bank->base + - bank->regs->debounce); - writel_relaxed(bank->context.debounce_en, - bank->base + bank->regs->debounce_en); - } - - writel_relaxed(bank->context.irqenable1, - bank->base + bank->regs->irqenable); - writel_relaxed(bank->context.irqenable2, - bank->base + bank->regs->irqenable2); -} - static int __maybe_unused omap_gpio_runtime_suspend(struct device *dev) { struct gpio_bank *bank = dev_get_drvdata(dev); @@ -1673,104 +1752,10 @@ static int __maybe_unused omap_gpio_runtime_resume(struct device *dev) return error; } -#ifdef CONFIG_ARCH_OMAP2PLUS static const struct dev_pm_ops gpio_pm_ops = { SET_RUNTIME_PM_OPS(omap_gpio_runtime_suspend, omap_gpio_runtime_resume, NULL) }; -#else -static const struct dev_pm_ops gpio_pm_ops; -#endif /* CONFIG_ARCH_OMAP2PLUS */ - -#if defined(CONFIG_OF) -static struct omap_gpio_reg_offs omap2_gpio_regs = { - .revision = OMAP24XX_GPIO_REVISION, - .direction = OMAP24XX_GPIO_OE, - .datain = OMAP24XX_GPIO_DATAIN, - .dataout = OMAP24XX_GPIO_DATAOUT, - .set_dataout = OMAP24XX_GPIO_SETDATAOUT, - .clr_dataout = OMAP24XX_GPIO_CLEARDATAOUT, - .irqstatus = OMAP24XX_GPIO_IRQSTATUS1, - .irqstatus2 = OMAP24XX_GPIO_IRQSTATUS2, - .irqenable = OMAP24XX_GPIO_IRQENABLE1, - .irqenable2 = OMAP24XX_GPIO_IRQENABLE2, - .set_irqenable = OMAP24XX_GPIO_SETIRQENABLE1, - .clr_irqenable = OMAP24XX_GPIO_CLEARIRQENABLE1, - .debounce = OMAP24XX_GPIO_DEBOUNCE_VAL, - .debounce_en = OMAP24XX_GPIO_DEBOUNCE_EN, - .ctrl = OMAP24XX_GPIO_CTRL, - .wkup_en = OMAP24XX_GPIO_WAKE_EN, - .leveldetect0 = OMAP24XX_GPIO_LEVELDETECT0, - .leveldetect1 = OMAP24XX_GPIO_LEVELDETECT1, - .risingdetect = OMAP24XX_GPIO_RISINGDETECT, - .fallingdetect = OMAP24XX_GPIO_FALLINGDETECT, -}; - -static struct omap_gpio_reg_offs omap4_gpio_regs = { - .revision = OMAP4_GPIO_REVISION, - .direction = OMAP4_GPIO_OE, - .datain = OMAP4_GPIO_DATAIN, - .dataout = OMAP4_GPIO_DATAOUT, - .set_dataout = OMAP4_GPIO_SETDATAOUT, - .clr_dataout = OMAP4_GPIO_CLEARDATAOUT, - .irqstatus = OMAP4_GPIO_IRQSTATUS0, - .irqstatus2 = OMAP4_GPIO_IRQSTATUS1, - .irqenable = OMAP4_GPIO_IRQSTATUSSET0, - .irqenable2 = OMAP4_GPIO_IRQSTATUSSET1, - .set_irqenable = OMAP4_GPIO_IRQSTATUSSET0, - .clr_irqenable = OMAP4_GPIO_IRQSTATUSCLR0, - .debounce = OMAP4_GPIO_DEBOUNCINGTIME, - .debounce_en = OMAP4_GPIO_DEBOUNCENABLE, - .ctrl = OMAP4_GPIO_CTRL, - .wkup_en = OMAP4_GPIO_IRQWAKEN0, - .leveldetect0 = OMAP4_GPIO_LEVELDETECT0, - .leveldetect1 = OMAP4_GPIO_LEVELDETECT1, - .risingdetect = OMAP4_GPIO_RISINGDETECT, - .fallingdetect = OMAP4_GPIO_FALLINGDETECT, -}; - -/* - * Note that omap2 does not currently support idle modes with context loss so - * no need to add OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER quirk flag to save - * and restore context. - */ -static const struct omap_gpio_platform_data omap2_pdata = { - .regs = &omap2_gpio_regs, - .bank_width = 32, - .dbck_flag = false, -}; - -static const struct omap_gpio_platform_data omap3_pdata = { - .regs = &omap2_gpio_regs, - .bank_width = 32, - .dbck_flag = true, - .quirks = OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER, -}; - -static const struct omap_gpio_platform_data omap4_pdata = { - .regs = &omap4_gpio_regs, - .bank_width = 32, - .dbck_flag = true, - .quirks = OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER, -}; - -static const struct of_device_id omap_gpio_match[] = { - { - .compatible = "ti,omap4-gpio", - .data = &omap4_pdata, - }, - { - .compatible = "ti,omap3-gpio", - .data = &omap3_pdata, - }, - { - .compatible = "ti,omap2-gpio", - .data = &omap2_pdata, - }, - { }, -}; -MODULE_DEVICE_TABLE(of, omap_gpio_match); -#endif static struct platform_driver omap_gpio_driver = { .probe = omap_gpio_probe, @@ -1778,7 +1763,7 @@ static struct platform_driver omap_gpio_driver = { .driver = { .name = "omap_gpio", .pm = &gpio_pm_ops, - .of_match_table = of_match_ptr(omap_gpio_match), + .of_match_table = omap_gpio_match, }, }; From 58f57f864c034b8e49b7d9637601e813ffac69bd Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 11 Mar 2019 20:50:05 +0100 Subject: [PATCH 62/85] gpio: omap: use devm_platform_ioremap_resource() Use the new helper that wraps the calls to platform_get_resource() and devm_ioremap_resource() together. Signed-off-by: Enrico Weigelt, metux IT consult Acked-by: Grygorii Strashko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 33a312688072..cf4a8727786a 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1562,7 +1562,6 @@ static int omap_gpio_probe(struct platform_device *pdev) struct device_node *node = dev->of_node; const struct of_device_id *match; const struct omap_gpio_platform_data *pdata; - struct resource *res; struct gpio_bank *bank; struct irq_chip *irqc; int ret; @@ -1648,8 +1647,7 @@ static int omap_gpio_probe(struct platform_device *pdev) raw_spin_lock_init(&bank->wa_lock); /* Static mapping, never released */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - bank->base = devm_ioremap_resource(dev, res); + bank->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(bank->base)) { return PTR_ERR(bank->base); } From 542f36159f9466faf4bd8d776fdc79f07c048c42 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 14 Mar 2019 20:32:50 +0100 Subject: [PATCH 63/85] gpio: Set proper argument value to set_config The gpio_set_config function creates a pinconf configuration for a given pinc_config_param. However, it always uses an arg of 0, which might not be a valid argument for a given param. A good example of that would be the bias parameters, where 0 means that the pull up or down resistor is null, and the pin is directly connected to VCC/GND. The framework uses in some other places the value 1 as a default argument to enable the pull resistor, so let's use the same one here. Signed-off-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index f41ad889124f..e5c3c4bff6fe 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2565,8 +2565,20 @@ EXPORT_SYMBOL_GPL(gpiochip_free_own_desc); static int gpio_set_config(struct gpio_chip *gc, unsigned offset, enum pin_config_param mode) { - unsigned long config = { PIN_CONF_PACKED(mode, 0) }; + unsigned long config; + unsigned arg; + switch (mode) { + case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_PULL_UP: + arg = 1; + break; + + default: + arg = 0; + } + + config = PIN_CONF_PACKED(mode, arg); return gc->set_config ? gc->set_config(gc, offset, config) : -ENOTSUPP; } From 4f2f95e9a81299266a4a4f771ac6eb9395528d73 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Mon, 1 Apr 2019 10:09:42 +0100 Subject: [PATCH 64/85] gpio: mmio: Fix bgpio_get_set & bgpio_get_set_multiple During my regression testing I noticed the cadence GPIO driver fails on the latest gpio for-next tree. I think the reason is this patch: commit 96cd559817f2 ("Merge branch 'devel' into for-next") Here is a part of the test log: Loopback 8 -> 24 TESTING: gpio: 488: output direction PASSED TESTING: gpio: 504: input direction PASSED TESTING: gpio: 488: 0 PASSED TESTING: gpio: 488 -> 504: 0 PASSED TESTING: gpio: 488: 1 FAILED TESTING: gpio: 488 -> 504: 1 FAILED TESTING: gpio: 488: 0 PASSED TESTING: gpio: 488 -> 504: 0 PASSED It looks like the issue is that gc->bgpio_dir has changed its meaning. It used to be set to the register value (so it was being inverted). Now it's always set to 1 for output and 0 for input. However the bgpio_get_set functions were not updated. So they invert the bit again, which means a wrong register is being accessed. This patch fixes that by removing the unnecessary inversion. Signed-off-by: Jan Kotas Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mmio.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c index f172b4382d8d..04be18b95485 100644 --- a/drivers/gpio/gpio-mmio.c +++ b/drivers/gpio/gpio-mmio.c @@ -134,17 +134,6 @@ static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio) unsigned long pinmask = bgpio_line2mask(gc, gpio); bool dir = !!(gc->bgpio_dir & pinmask); - /* - * If the direction is OUT we read the value from the SET - * register, and if the direction is IN we read the value - * from the DAT register. - * - * If the direction bits are inverted, naturally this gets - * inverted too. - */ - if (gc->bgpio_dir_inverted) - dir = !dir; - if (dir) return !!(gc->read_reg(gc->reg_set) & pinmask); else @@ -164,14 +153,8 @@ static int bgpio_get_set_multiple(struct gpio_chip *gc, unsigned long *mask, /* Make sure we first clear any bits that are zero when we read the register */ *bits &= ~*mask; - /* Exploit the fact that we know which directions are set */ - if (gc->bgpio_dir_inverted) { - set_mask = *mask & ~gc->bgpio_dir; - get_mask = *mask & gc->bgpio_dir; - } else { - set_mask = *mask & gc->bgpio_dir; - get_mask = *mask & ~gc->bgpio_dir; - } + set_mask = *mask & gc->bgpio_dir; + get_mask = *mask & ~gc->bgpio_dir; if (set_mask) *bits |= gc->read_reg(gc->reg_set) & set_mask; From b0d2569d8276439eb3d6f7d221f47bfc503ae00e Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 28 Mar 2019 01:39:58 +0000 Subject: [PATCH 65/85] gpio: mlxbf: remove unused including Remove including that don't need it. Signed-off-by: YueHaibing Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-mlxbf.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpio/gpio-mlxbf.c b/drivers/gpio/gpio-mlxbf.c index d428f42be74f..894aaf55fc96 100644 --- a/drivers/gpio/gpio-mlxbf.c +++ b/drivers/gpio/gpio-mlxbf.c @@ -11,7 +11,6 @@ #include #include #include -#include /* Number of pins on BlueField */ #define MLXBF_GPIO_NR 54 From 27157af66324d529b43231c12b5d1e1a3e9fa620 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 4 Apr 2019 23:55:14 +0700 Subject: [PATCH 66/85] gpio: mmio: Drop bgpio_dir_inverted The direction inversion semantics are now handled by simply using the registers for in/out available, no need to keep track of inversion semantics exmplicitly anymore. Reviewed-by: Bartosz Golaszewski Reviewed-by: Jan Kotas Signed-off-by: Linus Walleij --- drivers/gpio/gpio-mmio.c | 7 ------- include/linux/gpio/driver.h | 4 ---- 2 files changed, 11 deletions(-) diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c index 04be18b95485..6f904c874678 100644 --- a/drivers/gpio/gpio-mmio.c +++ b/drivers/gpio/gpio-mmio.c @@ -533,13 +533,6 @@ static int bgpio_setup_direction(struct gpio_chip *gc, gc->direction_output = bgpio_dir_out; gc->direction_input = bgpio_dir_in; gc->get_direction = bgpio_get_dir; - /* - * If only dirin is available, this means we need - * inverted semantics when handling get/set registers - * so detect this here. - */ - if (dirin && !dirout) - gc->bgpio_dir_inverted = true; } else { if (flags & BGPIOF_NO_OUTPUT) gc->direction_output = bgpio_dir_out_err; diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 95a51794c24a..4d69d458cf9f 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -229,9 +229,6 @@ struct gpio_irq_chip { * @reg_clr: output clear register (out=low) for generic GPIO * @reg_dir_out: direction out setting register for generic GPIO * @reg_dir_in: direction in setting register for generic GPIO - * @bgpio_dir_inverted: indicates that the direction register is inverted - * (gpiolib private state variable) this means @reg_dir_in is - * available but not @reg_dir_out. * @bgpio_dir_unreadable: indicates that the direction register(s) cannot * be read and we need to rely on out internal state tracking. * @bgpio_bits: number of register bits used for a generic GPIO i.e. @@ -305,7 +302,6 @@ struct gpio_chip { void __iomem *reg_clr; void __iomem *reg_dir_out; void __iomem *reg_dir_in; - bool bgpio_dir_inverted; bool bgpio_dir_unreadable; int bgpio_bits; spinlock_t bgpio_lock; From a71a81e7975843504170e69fe52605478f3c8e04 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 29 Mar 2019 09:42:29 +0100 Subject: [PATCH 67/85] gpio: of: Optimize quirk checks Simple string comparisons are cheaper than DT lookups, as the latter involve taking a spinlock and traversing properties. Hence optimize quirk checks by postponing DT lookups after string comparisons. Signed-off-by: Geert Uytterhoeven Reviewed-by: Mukesh Ojha Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-of.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 6a3ec575a404..3a6bb53d89df 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -86,9 +86,9 @@ static void of_gpio_flags_quirks(struct device_node *np, if (IS_ENABLED(CONFIG_REGULATOR) && (of_device_is_compatible(np, "regulator-fixed") || of_device_is_compatible(np, "reg-fixed-voltage") || - (of_device_is_compatible(np, "regulator-gpio") && - !(strcmp(propname, "enable-gpio") && - strcmp(propname, "enable-gpios"))))) { + (!(strcmp(propname, "enable-gpio") && + strcmp(propname, "enable-gpios")) && + of_device_is_compatible(np, "regulator-gpio")))) { /* * The regulator GPIO handles are specified such that the * presence or absence of "enable-active-high" solely controls @@ -119,9 +119,8 @@ static void of_gpio_flags_quirks(struct device_node *np, * property named "cs-gpios" we need to inspect the child node * to determine if the flags should have inverted semantics. */ - if (IS_ENABLED(CONFIG_SPI_MASTER) && - of_property_read_bool(np, "cs-gpios") && - !strcmp(propname, "cs-gpios")) { + if (IS_ENABLED(CONFIG_SPI_MASTER) && !strcmp(propname, "cs-gpios") && + of_property_read_bool(np, "cs-gpios")) { struct device_node *child; u32 cs; int ret; From f70fbc15bae2c89ffd72f2693d462b12fe05d847 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 20 Mar 2019 11:39:27 +0100 Subject: [PATCH 68/85] gpio: pca953x: Configure wake-up path when wake-up is enabled If a device is part of the wake-up path, it should indicate this by setting its power.wakeup_path field. This allows the genpd core code to keep the device enabled during system suspend when needed. As regulators powering devices are not handled by genpd, the driver handles these itself, and thus must skip regulator control when the device is part of the wake-up path. Signed-off-by: Geert Uytterhoeven Reviewed-by: Ulf Hansson Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 7e76830b3368..34f4ad1cc360 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -153,6 +153,7 @@ struct pca953x_chip { u8 irq_trig_fall[MAX_BANK]; struct irq_chip irq_chip; #endif + atomic_t wakeup_path; struct i2c_client *client; struct gpio_chip gpio_chip; @@ -581,6 +582,11 @@ static int pca953x_irq_set_wake(struct irq_data *d, unsigned int on) struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct pca953x_chip *chip = gpiochip_get_data(gc); + if (on) + atomic_inc(&chip->wakeup_path); + else + atomic_dec(&chip->wakeup_path); + return irq_set_irq_wake(chip->client->irq, on); } @@ -1100,7 +1106,10 @@ static int pca953x_suspend(struct device *dev) regcache_cache_only(chip->regmap, true); - regulator_disable(chip->regulator); + if (atomic_read(&chip->wakeup_path)) + device_set_wakeup_path(dev); + else + regulator_disable(chip->regulator); return 0; } @@ -1110,10 +1119,12 @@ static int pca953x_resume(struct device *dev) struct pca953x_chip *chip = dev_get_drvdata(dev); int ret; - ret = regulator_enable(chip->regulator); - if (ret != 0) { - dev_err(dev, "Failed to enable regulator: %d\n", ret); - return 0; + if (!atomic_read(&chip->wakeup_path)) { + ret = regulator_enable(chip->regulator); + if (ret != 0) { + dev_err(dev, "Failed to enable regulator: %d\n", ret); + return 0; + } } regcache_cache_only(chip->regmap, false); From 12f2639038ef420fe796171ffb810b30d1ac0619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 5 Apr 2019 21:46:12 +0200 Subject: [PATCH 69/85] tracing: stop making gpio tracing configurable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gpio tracing was made configurable in 4.4-rc1 (commit ddd70280bf0e ("tracing: gpio: Add Kconfig option for enabling/disabling trace events")). Since then it is the only event type that can be compiled conditionally. Given that there is only little overhead I don't understand the reasoning and I was annoyed more than once that gpio events were not available without recompiling. So drop the Kconfig symbol and make gpio events available unconditionally. Signed-off-by: Uwe Kleine-König Signed-off-by: Linus Walleij --- arch/arm/configs/aspeed_g4_defconfig | 1 - arch/arm/configs/aspeed_g5_defconfig | 1 - include/trace/events/gpio.h | 4 ---- kernel/trace/Kconfig | 7 ------- 4 files changed, 13 deletions(-) diff --git a/arch/arm/configs/aspeed_g4_defconfig b/arch/arm/configs/aspeed_g4_defconfig index 1446262921b4..0f3638dd576b 100644 --- a/arch/arm/configs/aspeed_g4_defconfig +++ b/arch/arm/configs/aspeed_g4_defconfig @@ -248,7 +248,6 @@ CONFIG_PANIC_TIMEOUT=-1 # CONFIG_SCHED_DEBUG is not set CONFIG_SCHED_STACK_END_CHECK=y CONFIG_FUNCTION_TRACER=y -# CONFIG_TRACING_EVENTS_GPIO is not set # CONFIG_RUNTIME_TESTING_MENU is not set CONFIG_DEBUG_WX=y CONFIG_DEBUG_USER=y diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig index 02fa3a41add5..eaab776c4ac2 100644 --- a/arch/arm/configs/aspeed_g5_defconfig +++ b/arch/arm/configs/aspeed_g5_defconfig @@ -248,7 +248,6 @@ CONFIG_PANIC_TIMEOUT=-1 # CONFIG_SCHED_DEBUG is not set CONFIG_SCHED_STACK_END_CHECK=y CONFIG_FUNCTION_TRACER=y -# CONFIG_TRACING_EVENTS_GPIO is not set # CONFIG_RUNTIME_TESTING_MENU is not set CONFIG_DEBUG_WX=y CONFIG_DEBUG_USER=y diff --git a/include/trace/events/gpio.h b/include/trace/events/gpio.h index 5c189a22c489..3aa9fd86d748 100644 --- a/include/trace/events/gpio.h +++ b/include/trace/events/gpio.h @@ -2,10 +2,6 @@ #undef TRACE_SYSTEM #define TRACE_SYSTEM gpio -#ifndef CONFIG_TRACING_EVENTS_GPIO -#define NOTRACE -#endif - #if !defined(_TRACE_GPIO_H) || defined(TRACE_HEADER_MULTI_READ) #define _TRACE_GPIO_H diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 8bd1d6d001d7..5d965cef6c77 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -774,13 +774,6 @@ config TRACE_EVAL_MAP_FILE If unsure, say N -config TRACING_EVENTS_GPIO - bool "Trace gpio events" - depends on GPIOLIB - default y - help - Enable tracing events for gpio subsystem - config GCOV_PROFILE_FTRACE bool "Enable GCOV profiling on ftrace subsystem" depends on GCOV_KERNEL From e6818d29ea1591b3e37d9cf635dc9dbca1a398ae Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 8 Apr 2019 12:46:53 -0700 Subject: [PATCH 70/85] gpio: gpio-omap: configure edge detection for level IRQs for idle wakeup The GPIO block can enter idle independently of the CPU power management calls via smart-idle. When the GPIO block enters idle, level detection stops working due to clocks being shut off, and an alternative form of edge detection is used. However, this needs the edge detection registers set to mark the appropriate edges. Arrange to configure the edge detection enables along with the level detection to ensure that any transition to active interrupt state that occurs while the block is idle is detected as a wake-up event. Since we enable the edge detection when configuring the IRQ, both omap2_gpio_enable_level_quirk() nor omap2_gpio_disable_level_quirk() become redundant, which also means OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER can be removed. This can be now done without regressions as patch "gpio: gpio-omap: fix level interrupt idling" allows level interrupts to idle on omap4 without a workaround. Cc: Aaro Koskinen Cc: Grygorii Strashko Cc: Keerthy Cc: Peter Ujfalusi Cc: Tero Kristo Signed-off-by: Russell King [tony@atomide.com: update description for the fix dependency] Signed-off-by: Tony Lindgren Signed-off-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 90 +++---------------------- include/linux/platform_data/gpio-omap.h | 2 - 2 files changed, 11 insertions(+), 81 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 8cbb109928cb..e9dedee0af10 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -31,8 +31,6 @@ #define OMAP4_GPIO_DEBOUNCINGTIME_MASK 0xFF -#define OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER BIT(2) - struct gpio_regs { u32 irqenable1; u32 irqenable2; @@ -48,13 +46,6 @@ struct gpio_regs { u32 debounce_en; }; -struct gpio_bank; - -struct gpio_omap_funcs { - void (*idle_enable_level_quirk)(struct gpio_bank *bank); - void (*idle_disable_level_quirk)(struct gpio_bank *bank); -}; - struct gpio_bank { struct list_head node; void __iomem *base; @@ -62,7 +53,6 @@ struct gpio_bank { u32 non_wakeup_gpios; u32 enabled_non_wakeup_gpios; struct gpio_regs context; - struct gpio_omap_funcs funcs; u32 saved_datain; u32 level_mask; u32 toggle_mask; @@ -83,7 +73,6 @@ struct gpio_bank { int stride; u32 width; int context_loss_count; - u32 quirks; void (*set_dataout)(struct gpio_bank *bank, unsigned gpio, int enable); void (*set_dataout_multiple)(struct gpio_bank *bank, @@ -378,10 +367,16 @@ static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio, trigger & IRQ_TYPE_LEVEL_LOW); omap_gpio_rmw(base, bank->regs->leveldetect1, gpio_bit, trigger & IRQ_TYPE_LEVEL_HIGH); + + /* + * We need the edge detection enabled for to allow the GPIO block + * to be woken from idle state. Set the appropriate edge detection + * in addition to the level detection. + */ omap_gpio_rmw(base, bank->regs->risingdetect, gpio_bit, - trigger & IRQ_TYPE_EDGE_RISING); + trigger & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)); omap_gpio_rmw(base, bank->regs->fallingdetect, gpio_bit, - trigger & IRQ_TYPE_EDGE_FALLING); + trigger & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)); bank->context.leveldetect0 = readl_relaxed(bank->base + bank->regs->leveldetect0); @@ -904,44 +899,6 @@ static void omap_gpio_unmask_irq(struct irq_data *d) raw_spin_unlock_irqrestore(&bank->lock, flags); } -/* - * Only edges can generate a wakeup event to the PRCM. - * - * Therefore, ensure any wake-up capable GPIOs have - * edge-detection enabled before going idle to ensure a wakeup - * to the PRCM is generated on a GPIO transition. (c.f. 34xx - * NDA TRM 25.5.3.1) - * - * The normal values will be restored upon ->runtime_resume() - * by writing back the values saved in bank->context. - */ -static void __maybe_unused -omap2_gpio_enable_level_quirk(struct gpio_bank *bank) -{ - u32 wake_low, wake_hi; - - /* Enable additional edge detection for level gpios for idle */ - wake_low = bank->context.leveldetect0 & bank->context.wake_en; - if (wake_low) - writel_relaxed(wake_low | bank->context.fallingdetect, - bank->base + bank->regs->fallingdetect); - - wake_hi = bank->context.leveldetect1 & bank->context.wake_en; - if (wake_hi) - writel_relaxed(wake_hi | bank->context.risingdetect, - bank->base + bank->regs->risingdetect); -} - -static void __maybe_unused -omap2_gpio_disable_level_quirk(struct gpio_bank *bank) -{ - /* Disable edge detection for level gpios after idle */ - writel_relaxed(bank->context.fallingdetect, - bank->base + bank->regs->fallingdetect); - writel_relaxed(bank->context.risingdetect, - bank->base + bank->regs->risingdetect); -} - /*---------------------------------------------------------------------*/ static int omap_mpuio_suspend_noirq(struct device *dev) @@ -1324,9 +1281,6 @@ static void omap_gpio_idle(struct gpio_bank *bank, bool may_lose_context) bank->saved_datain = readl_relaxed(base + bank->regs->datain); - if (bank->funcs.idle_enable_level_quirk) - bank->funcs.idle_enable_level_quirk(bank); - if (!bank->enabled_non_wakeup_gpios) goto update_gpio_context_count; @@ -1373,9 +1327,6 @@ static void omap_gpio_unidle(struct gpio_bank *bank) omap_gpio_dbck_enable(bank); - if (bank->funcs.idle_disable_level_quirk) - bank->funcs.idle_disable_level_quirk(bank); - if (bank->loses_context) { if (!bank->get_context_loss_count) { omap_gpio_restore_context(bank); @@ -1519,11 +1470,6 @@ static struct omap_gpio_reg_offs omap4_gpio_regs = { .fallingdetect = OMAP4_GPIO_FALLINGDETECT, }; -/* - * Note that omap2 does not currently support idle modes with context loss so - * no need to add OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER quirk flag to save - * and restore context. - */ static const struct omap_gpio_platform_data omap2_pdata = { .regs = &omap2_gpio_regs, .bank_width = 32, @@ -1534,14 +1480,12 @@ static const struct omap_gpio_platform_data omap3_pdata = { .regs = &omap2_gpio_regs, .bank_width = 32, .dbck_flag = true, - .quirks = OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER, }; static const struct omap_gpio_platform_data omap4_pdata = { .regs = &omap4_gpio_regs, .bank_width = 32, .dbck_flag = true, - .quirks = OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER, }; static const struct of_device_id omap_gpio_match[] = { @@ -1611,7 +1555,6 @@ static int omap_gpio_probe(struct platform_device *pdev) bank->chip.parent = dev; bank->chip.owner = THIS_MODULE; bank->dbck_flag = pdata->dbck_flag; - bank->quirks = pdata->quirks; bank->stride = pdata->bank_stride; bank->width = pdata->bank_width; bank->is_mpuio = pdata->is_mpuio; @@ -1641,13 +1584,6 @@ static int omap_gpio_probe(struct platform_device *pdev) omap_set_gpio_dataout_mask_multiple; } - if (bank->quirks & OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER) { - bank->funcs.idle_enable_level_quirk = - omap2_gpio_enable_level_quirk; - bank->funcs.idle_disable_level_quirk = - omap2_gpio_disable_level_quirk; - } - raw_spin_lock_init(&bank->lock); raw_spin_lock_init(&bank->wa_lock); @@ -1689,11 +1625,8 @@ static int omap_gpio_probe(struct platform_device *pdev) omap_gpio_show_rev(bank); - if (bank->funcs.idle_enable_level_quirk && - bank->funcs.idle_disable_level_quirk) { - bank->nb.notifier_call = gpio_omap_cpu_notifier; - cpu_pm_register_notifier(&bank->nb); - } + bank->nb.notifier_call = gpio_omap_cpu_notifier; + cpu_pm_register_notifier(&bank->nb); pm_runtime_put(dev); @@ -1704,8 +1637,7 @@ static int omap_gpio_remove(struct platform_device *pdev) { struct gpio_bank *bank = platform_get_drvdata(pdev); - if (bank->nb.notifier_call) - cpu_pm_unregister_notifier(&bank->nb); + cpu_pm_unregister_notifier(&bank->nb); list_del(&bank->node); gpiochip_remove(&bank->chip); pm_runtime_disable(&pdev->dev); diff --git a/include/linux/platform_data/gpio-omap.h b/include/linux/platform_data/gpio-omap.h index 6d07eebb3f75..7c36370c062e 100644 --- a/include/linux/platform_data/gpio-omap.h +++ b/include/linux/platform_data/gpio-omap.h @@ -200,8 +200,6 @@ struct omap_gpio_platform_data { bool is_mpuio; /* whether the bank is of type MPUIO */ u32 non_wakeup_gpios; - u32 quirks; /* Version specific quirks mask */ - struct omap_gpio_reg_offs *regs; /* Return context loss count due to PM states changing */ From 044e499acd1587e01bdd3434b3e5a1869ea26fdd Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 10 Apr 2019 12:51:13 -0700 Subject: [PATCH 71/85] gpio: gpio-omap: Remove conditional pm_runtime handling for GPIO interrupts Commit b764a5863fd8 ("gpio: omap: Remove custom PM calls and use cpu_pm instead") moved interrupt using GPIO banks to idle with cpu_pm in order to drop the use of pm_runtime_irq_safe() in a later patch. The GPIO banks with no interrupts claimed are still being idled based on PM runtime calls. However this caused a regression for am437x suspend for rtc+ddr idle mode where the device cannot enter idle state as reported by Keerthy . To fix the issue, we must not fail the pm_runtime callbacks. For GPIO interrupts, we already have irq_chip_pm_get increment the PM runtime use count as pointed out by Grygorii Strashko . So all we need to do is remove the conditional handling in the runtime_suspend and resume functions and let the CPU PM notifier idle the GPIO banks. Cc: Aaro Koskinen Cc: Grygorii Strashko Cc: Keerthy Cc: Peter Ujfalusi Cc: Tero Kristo Fixes: b764a5863fd8 ("gpio: omap: Remove custom PM calls and use cpu_pm instead") Reported-by: Keerthy Signed-off-by: Russell King [tony@atomide.com: updated patch description, dropped runtime count changes] Signed-off-by: Tony Lindgren Tested-by: Keerthy Reviewed-by: Keerthy Signed-off-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index e9dedee0af10..16289bafa001 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1651,40 +1651,26 @@ static int __maybe_unused omap_gpio_runtime_suspend(struct device *dev) { struct gpio_bank *bank = dev_get_drvdata(dev); unsigned long flags; - int error = 0; raw_spin_lock_irqsave(&bank->lock, flags); - /* Must be idled only by CPU_CLUSTER_PM_ENTER? */ - if (bank->irq_usage) { - error = -EBUSY; - goto unlock; - } omap_gpio_idle(bank, true); bank->is_suspended = true; -unlock: raw_spin_unlock_irqrestore(&bank->lock, flags); - return error; + return 0; } static int __maybe_unused omap_gpio_runtime_resume(struct device *dev) { struct gpio_bank *bank = dev_get_drvdata(dev); unsigned long flags; - int error = 0; raw_spin_lock_irqsave(&bank->lock, flags); - /* Must be unidled only by CPU_CLUSTER_PM_ENTER? */ - if (bank->irq_usage) { - error = -EBUSY; - goto unlock; - } omap_gpio_unidle(bank); bank->is_suspended = false; -unlock: raw_spin_unlock_irqrestore(&bank->lock, flags); - return error; + return 0; } static const struct dev_pm_ops gpio_pm_ops = { From 01769c4700d8ca156b4a331b16be9eda575dfde9 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 9 Apr 2019 12:25:17 +0200 Subject: [PATCH 72/85] gpio: pca953x: add pcal6416 to the of_device_id table When adding support for the pcal6416, the of_device_id table was left out, add the proper entry. Fixes: aac1e3c9680b ("gpio: pca953x: add support for pcal6416 type") Signed-off-by: Alexandre Belloni Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 349d0ccb5285..75066e538b13 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -1163,6 +1163,7 @@ static const struct of_device_id pca953x_dt_ids[] = { { .compatible = "nxp,pca9575", .data = OF_957X(16, PCA_INT), }, { .compatible = "nxp,pca9698", .data = OF_953X(40, 0), }, + { .compatible = "nxp,pcal6416", .data = OF_953X(16, PCA_LATCH_INT), }, { .compatible = "nxp,pcal6524", .data = OF_953X(24, PCA_LATCH_INT), }, { .compatible = "nxp,pcal9555a", .data = OF_953X(16, PCA_LATCH_INT), }, From 15e384c446d93d00ab96d34bf2a5c308e3b3d16b Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 9 Apr 2019 14:35:45 +0200 Subject: [PATCH 73/85] dt-bindings: gpio: pca953x: document the nxp,pca6416 The NXP PCA6416 is a variant of the PCA GPIO expander, with 16 GPIOs. Signed-off-by: Alexandre Belloni Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/gpio/gpio-pca953x.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt b/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt index 8678df2a5713..dab537c20def 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt +++ b/Documentation/devicetree/bindings/gpio/gpio-pca953x.txt @@ -2,6 +2,7 @@ Required properties: - compatible: Has to contain one of the following: + nxp,pca6416 nxp,pca9505 nxp,pca9534 nxp,pca9535 From 12c7a4fc47e4720e96205030b1f0dd6bd2746a3f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 9 Apr 2019 14:35:46 +0200 Subject: [PATCH 74/85] gpio: pca953x: add support for pca6416 The NXP PCA6416, documented at [1], is a variant of the PCA GPIO expander with 16 GPIOs, and supporting an interrupt. [1] https://www.nxp.com/docs/en/data-sheet/PCA6416A.pdf Signed-off-by: Alexandre Belloni Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 75066e538b13..b7ef33f63392 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -73,6 +73,7 @@ #define PCA_CHIP_TYPE(x) ((x) & PCA_TYPE_MASK) static const struct i2c_device_id pca953x_id[] = { + { "pca6416", 16 | PCA953X_TYPE | PCA_INT, }, { "pca9505", 40 | PCA953X_TYPE | PCA_INT, }, { "pca9534", 8 | PCA953X_TYPE | PCA_INT, }, { "pca9535", 16 | PCA953X_TYPE | PCA_INT, }, @@ -1148,6 +1149,7 @@ static int pca953x_resume(struct device *dev) #define OF_957X(__nrgpio, __int) (void *)(__nrgpio | PCA957X_TYPE | __int) static const struct of_device_id pca953x_dt_ids[] = { + { .compatible = "nxp,pca6416", .data = OF_953X(16, PCA_INT), }, { .compatible = "nxp,pca9505", .data = OF_953X(40, PCA_INT), }, { .compatible = "nxp,pca9534", .data = OF_953X( 8, PCA_INT), }, { .compatible = "nxp,pca9535", .data = OF_953X(16, PCA_INT), }, From 4050586b2beec8603d25ad7fc7ba15670143e6ba Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 10 Apr 2019 18:39:15 +0300 Subject: [PATCH 75/85] gpiolib: Indent entry values of enum gpio_lookup_flags Indent entry values in the enum gpio_lookup_flags for better readability. No functional change. Signed-off-by: Andy Shevchenko Acked-by: Hans de Goede Reviewed-by: Mika Westerberg Signed-off-by: Linus Walleij --- include/linux/gpio/machine.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h index 69673be10213..a0a981676490 100644 --- a/include/linux/gpio/machine.h +++ b/include/linux/gpio/machine.h @@ -6,14 +6,14 @@ #include enum gpio_lookup_flags { - GPIO_ACTIVE_HIGH = (0 << 0), - GPIO_ACTIVE_LOW = (1 << 0), - GPIO_OPEN_DRAIN = (1 << 1), - GPIO_OPEN_SOURCE = (1 << 2), - GPIO_PERSISTENT = (0 << 3), - GPIO_TRANSITORY = (1 << 3), - GPIO_PULL_UP = (1 << 4), - GPIO_PULL_DOWN = (1 << 5), + GPIO_ACTIVE_HIGH = (0 << 0), + GPIO_ACTIVE_LOW = (1 << 0), + GPIO_OPEN_DRAIN = (1 << 1), + GPIO_OPEN_SOURCE = (1 << 2), + GPIO_PERSISTENT = (0 << 3), + GPIO_TRANSITORY = (1 << 3), + GPIO_PULL_UP = (1 << 4), + GPIO_PULL_DOWN = (1 << 5), }; /** From fed7026adc7c3a67f992d28d7a5309ff749d3776 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 10 Apr 2019 18:39:16 +0300 Subject: [PATCH 76/85] gpiolib: Make use of enum gpio_lookup_flags consistent The library uses enum gpio_lookup_flags to define the possible characteristics of GPIO pin. Since enumerator listed only individual bits the common use of it is in a form of a bitmask of gpio_lookup_flags GPIO_* values. The more correct type for this is unsigned long. Due to above convert all users to use unsigned long instead of enum gpio_lookup_flags except enumerator definition. While here, make field and parameter descriptions consistent as well. Suggested-by: Mika Westerberg Signed-off-by: Andy Shevchenko Reviewed-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 14 +++++++++----- drivers/gpio/gpiolib-of.c | 11 +++++------ drivers/gpio/gpiolib.c | 13 ++++++------- drivers/gpio/gpiolib.h | 9 ++++----- include/linux/gpio/machine.h | 8 ++++---- 5 files changed, 28 insertions(+), 27 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index e9ddf66f2d14..962bdd89cd8f 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -696,7 +696,7 @@ struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id, unsigned int idx, enum gpiod_flags *dflags, - enum gpio_lookup_flags *lookupflags) + unsigned long *lookupflags) { struct acpi_device *adev = ACPI_COMPANION(dev); struct acpi_gpio_info info; @@ -995,9 +995,12 @@ static void acpi_gpiochip_free_regions(struct acpi_gpio_chip *achip) } } -static struct gpio_desc *acpi_gpiochip_parse_own_gpio( - struct acpi_gpio_chip *achip, struct fwnode_handle *fwnode, - const char **name, unsigned int *lflags, unsigned int *dflags) +static struct gpio_desc * +acpi_gpiochip_parse_own_gpio(struct acpi_gpio_chip *achip, + struct fwnode_handle *fwnode, + const char **name, + unsigned long *lflags, + unsigned int *dflags) { struct gpio_chip *chip = achip->chip; struct gpio_desc *desc; @@ -1040,7 +1043,8 @@ static void acpi_gpiochip_scan_gpios(struct acpi_gpio_chip *achip) struct fwnode_handle *fwnode; device_for_each_child_node(chip->parent, fwnode) { - unsigned int lflags, dflags; + unsigned long lflags; + unsigned int dflags; struct gpio_desc *desc; const char *name; int ret; diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 3a6bb53d89df..c5547df4f6cd 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -287,8 +287,7 @@ static struct gpio_desc *of_find_regulator_gpio(struct device *dev, const char * } struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, - unsigned int idx, - enum gpio_lookup_flags *flags) + unsigned int idx, unsigned long *flags) { char prop_name[32]; /* 32 is max size of property name */ enum of_gpio_flags of_flags; @@ -361,8 +360,8 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, * @chip: GPIO chip whose hog is parsed * @idx: Index of the GPIO to parse * @name: GPIO line name - * @lflags: gpio_lookup_flags - returned from of_find_gpio() or - * of_parse_own_gpio() + * @lflags: bitmask of gpio_lookup_flags GPIO_* values - returned from + * of_find_gpio() or of_parse_own_gpio() * @dflags: gpiod_flags - optional GPIO initialization flags * * Returns GPIO descriptor to use with Linux GPIO API, or one of the errno @@ -371,7 +370,7 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, static struct gpio_desc *of_parse_own_gpio(struct device_node *np, struct gpio_chip *chip, unsigned int idx, const char **name, - enum gpio_lookup_flags *lflags, + unsigned long *lflags, enum gpiod_flags *dflags) { struct device_node *chip_np; @@ -444,7 +443,7 @@ static int of_gpiochip_scan_gpios(struct gpio_chip *chip) struct gpio_desc *desc = NULL; struct device_node *np; const char *name; - enum gpio_lookup_flags lflags; + unsigned long lflags; enum gpiod_flags dflags; unsigned int i; int ret; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 982845e8212c..e9909c07517b 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3923,8 +3923,7 @@ static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev) } static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, - unsigned int idx, - enum gpio_lookup_flags *flags) + unsigned int idx, unsigned long *flags) { struct gpio_desc *desc = ERR_PTR(-ENOENT); struct gpiod_lookup_table *table; @@ -4080,8 +4079,8 @@ EXPORT_SYMBOL_GPL(gpiod_get_optional); * gpiod_configure_flags - helper function to configure a given GPIO * @desc: gpio whose value will be assigned * @con_id: function within the GPIO consumer - * @lflags: gpio_lookup_flags - returned from of_find_gpio() or - * of_get_gpio_hog() + * @lflags: bitmask of gpio_lookup_flags GPIO_* values - returned from + * of_find_gpio() or of_get_gpio_hog() * @dflags: gpiod_flags - optional GPIO initialization flags * * Return 0 on success, -ENOENT if no GPIO has been assigned to the @@ -4163,9 +4162,9 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, unsigned int idx, enum gpiod_flags flags) { + unsigned long lookupflags = 0; struct gpio_desc *desc = NULL; int status; - enum gpio_lookup_flags lookupflags = 0; /* Maybe we have a device name, maybe not */ const char *devname = dev ? dev_name(dev) : "?"; @@ -4403,8 +4402,8 @@ EXPORT_SYMBOL_GPL(gpiod_get_index_optional); * gpiod_hog - Hog the specified GPIO desc given the provided flags * @desc: gpio whose value will be assigned * @name: gpio line name - * @lflags: gpio_lookup_flags - returned from of_find_gpio() or - * of_get_gpio_hog() + * @lflags: bitmask of gpio_lookup_flags GPIO_* values - returned from + * of_find_gpio() or of_get_gpio_hog() * @dflags: gpiod_flags - optional GPIO initialization flags */ int gpiod_hog(struct gpio_desc *desc, const char *name, diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 078ab17b96bf..5dbfce616ae1 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -17,7 +17,6 @@ #include enum of_gpio_flags; -enum gpio_lookup_flags; struct acpi_device; /** @@ -95,7 +94,7 @@ static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" }; struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, unsigned int idx, - enum gpio_lookup_flags *flags); + 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); @@ -104,7 +103,7 @@ void of_gpiochip_remove(struct gpio_chip *gc); static inline struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, unsigned int idx, - enum gpio_lookup_flags *flags) + unsigned long *lookupflags) { return ERR_PTR(-ENOENT); } @@ -131,7 +130,7 @@ struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id, unsigned int idx, enum gpiod_flags *dflags, - enum gpio_lookup_flags *lookupflags); + unsigned long *lookupflags); struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname, int index, struct acpi_gpio_info *info); @@ -158,7 +157,7 @@ acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *inf static inline struct gpio_desc * acpi_find_gpio(struct device *dev, const char *con_id, unsigned int idx, enum gpiod_flags *dflags, - enum gpio_lookup_flags *lookupflags) + unsigned long *lookupflags) { return ERR_PTR(-ENOENT); } diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h index a0a981676490..dad392158550 100644 --- a/include/linux/gpio/machine.h +++ b/include/linux/gpio/machine.h @@ -22,7 +22,7 @@ enum gpio_lookup_flags { * @chip_hwnum: hardware number (i.e. relative to the chip) of the GPIO * @con_id: name of the GPIO from the device's point of view * @idx: index of the GPIO in case several GPIOs share the same name - * @flags: mask of GPIO_* values + * @flags: bitmask of gpio_lookup_flags GPIO_* values * * gpiod_lookup is a lookup table for associating GPIOs to specific devices and * functions using platform data. @@ -32,7 +32,7 @@ struct gpiod_lookup { u16 chip_hwnum; const char *con_id; unsigned int idx; - enum gpio_lookup_flags flags; + unsigned long flags; }; struct gpiod_lookup_table { @@ -46,7 +46,7 @@ struct gpiod_lookup_table { * @chip_label: name of the chip the GPIO belongs to * @chip_hwnum: hardware number (i.e. relative to the chip) of the GPIO * @line_name: consumer name for the hogged line - * @lflags: mask of GPIO lookup flags + * @lflags: bitmask of gpio_lookup_flags GPIO_* values * @dflags: GPIO flags used to specify the direction and value */ struct gpiod_hog { @@ -54,7 +54,7 @@ struct gpiod_hog { const char *chip_label; u16 chip_hwnum; const char *line_name; - enum gpio_lookup_flags lflags; + unsigned long lflags; int dflags; }; From 2d6c06f5a4094ab4ea15b63af72d2dab74e9415a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 10 Apr 2019 18:39:17 +0300 Subject: [PATCH 77/85] gpiolib: Introduce GPIO_LOOKUP_FLAGS_DEFAULT Since GPIO library operates with enumerator when it's subject to handle the GPIO lookup flags, it will be better to clearly see what default means. Thus, introduce GPIO_LOOKUP_FLAGS_DEFAULT entry to describe the default assumptions. While here, replace 0 by newly introduced constant. Signed-off-by: Andy Shevchenko Reviewed-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 5 +++-- drivers/gpio/gpiolib-of.c | 2 +- drivers/gpio/gpiolib.c | 9 +++++---- include/linux/gpio/machine.h | 2 ++ 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 962bdd89cd8f..6ee929d90a6a 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -819,6 +819,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index) return PTR_ERR(desc); if (info.gpioint && idx++ == index) { + unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT; char label[32]; int irq; @@ -830,7 +831,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index) return irq; snprintf(label, sizeof(label), "GpioInt() %d", index); - ret = gpiod_configure_flags(desc, label, 0, info.flags); + ret = gpiod_configure_flags(desc, label, lflags, info.flags); if (ret < 0) return ret; @@ -1007,7 +1008,7 @@ acpi_gpiochip_parse_own_gpio(struct acpi_gpio_chip *achip, u32 gpios[2]; int ret; - *lflags = 0; + *lflags = GPIO_LOOKUP_FLAGS_DEFAULT; *dflags = 0; *name = NULL; diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index c5547df4f6cd..aec7bd86ae7e 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -386,7 +386,7 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np, return ERR_PTR(-EINVAL); xlate_flags = 0; - *lflags = 0; + *lflags = GPIO_LOOKUP_FLAGS_DEFAULT; *dflags = 0; ret = of_property_read_u32(chip_np, "#gpio-cells", &tmp); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index e9909c07517b..b8e4c9cd7b9e 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2515,6 +2515,7 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip, u16 hwnum, const char *label, enum gpiod_flags flags) { + unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT; struct gpio_desc *desc = gpiochip_get_desc(chip, hwnum); int err; @@ -2527,7 +2528,7 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip, u16 hwnum, if (err < 0) return ERR_PTR(err); - err = gpiod_configure_flags(desc, label, 0, flags); + err = gpiod_configure_flags(desc, label, lflags, flags); if (err) { chip_err(chip, "setup of own GPIO %s failed\n", label); gpiod_free_commit(desc); @@ -4162,7 +4163,7 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, unsigned int idx, enum gpiod_flags flags) { - unsigned long lookupflags = 0; + unsigned long lookupflags = GPIO_LOOKUP_FLAGS_DEFAULT; struct gpio_desc *desc = NULL; int status; /* Maybe we have a device name, maybe not */ @@ -4249,8 +4250,8 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, enum gpiod_flags dflags, const char *label) { + unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT; struct gpio_desc *desc; - unsigned long lflags = 0; enum of_gpio_flags flags; bool active_low = false; bool single_ended = false; @@ -4328,8 +4329,8 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, enum gpiod_flags dflags, const char *label) { + unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT; struct gpio_desc *desc = ERR_PTR(-ENODEV); - unsigned long lflags = 0; int ret; if (!fwnode) diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h index dad392158550..35f299d1f6a7 100644 --- a/include/linux/gpio/machine.h +++ b/include/linux/gpio/machine.h @@ -14,6 +14,8 @@ enum gpio_lookup_flags { GPIO_TRANSITORY = (1 << 3), GPIO_PULL_UP = (1 << 4), GPIO_PULL_DOWN = (1 << 5), + + GPIO_LOOKUP_FLAGS_DEFAULT = GPIO_ACTIVE_HIGH | GPIO_PERSISTENT, }; /** From 80c8d927dacc436963af7c0da711578e8c122db8 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 10 Apr 2019 18:39:18 +0300 Subject: [PATCH 78/85] gpiolib: acpi: Change type of dflags Most of the code inside GPIO library is using enum gpiod_flags. Some of the function still operate with unsigned int. In order to be more consistent and better type checking, convert acpi_gpiochip_parse_own_gpio() to use enum gpiod_flags instead of unsigned int. Signed-off-by: Andy Shevchenko Acked-by: Hans de Goede Reviewed-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 6ee929d90a6a..36cd9abe5e55 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -1001,7 +1001,7 @@ acpi_gpiochip_parse_own_gpio(struct acpi_gpio_chip *achip, struct fwnode_handle *fwnode, const char **name, unsigned long *lflags, - unsigned int *dflags) + enum gpiod_flags *dflags) { struct gpio_chip *chip = achip->chip; struct gpio_desc *desc; @@ -1045,7 +1045,7 @@ static void acpi_gpiochip_scan_gpios(struct acpi_gpio_chip *achip) device_for_each_child_node(chip->parent, fwnode) { unsigned long lflags; - unsigned int dflags; + enum gpiod_flags dflags; struct gpio_desc *desc; const char *name; int ret; From 24a49543336dbaecb83862a17f6a05d53ec2592f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 10 Apr 2019 18:39:19 +0300 Subject: [PATCH 79/85] gpiolib: acpi: Set pin value, based on bias, more accurately ACPI GpioIo() resource may have different bias settings. For now, we distinguish only PullUp() setting in order to configure the initial state of a pin. Take into consideration the rest of the possible choices as well, i.e. PullDown, PullNone and PullDefault, when configuring the initial state of the pin. Signed-off-by: Andy Shevchenko Acked-by: Hans de Goede Reviewed-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 36cd9abe5e55..878c7a7dea8b 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -444,8 +444,6 @@ static bool acpi_get_driver_gpio_data(struct acpi_device *adev, static enum gpiod_flags acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio) { - bool pull_up = agpio->pin_config == ACPI_PIN_CONFIG_PULLUP; - switch (agpio->io_restriction) { case ACPI_IO_RESTRICT_INPUT: return GPIOD_IN; @@ -454,16 +452,26 @@ acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio) * ACPI GPIO resources don't contain an initial value for the * GPIO. Therefore we deduce that value from the pull field * instead. If the pin is pulled up we assume default to be - * high, otherwise low. + * high, if it is pulled down we assume default to be low, + * otherwise we leave pin untouched. */ - return pull_up ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW; + switch (agpio->pin_config) { + case ACPI_PIN_CONFIG_PULLUP: + return GPIOD_OUT_HIGH; + case ACPI_PIN_CONFIG_PULLDOWN: + return GPIOD_OUT_LOW; + default: + break; + } default: - /* - * Assume that the BIOS has configured the direction and pull - * accordingly. - */ - return GPIOD_ASIS; + break; } + + /* + * Assume that the BIOS has configured the direction and pull + * accordingly. + */ + return GPIOD_ASIS; } static int From 606be34440ee3e6da3799691fcab7b69e1ad06cd Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 10 Apr 2019 18:39:20 +0300 Subject: [PATCH 80/85] gpiolib: acpi: Add acpi_gpio_update_gpiod_lookup_flags() helper This helper consolidates all settings of GPIO descriptor lookup flags and quirks in the future if any. No functional change intended. Signed-off-by: Andy Shevchenko Acked-by: Hans de Goede Reviewed-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 13 ++++++++++--- drivers/gpio/gpiolib.c | 4 +--- drivers/gpio/gpiolib.h | 8 ++++++++ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 878c7a7dea8b..9c6ebaaa02fe 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -525,6 +525,15 @@ acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *inf return ret; } +int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags, + struct acpi_gpio_info *info) +{ + if (info->polarity == GPIO_ACTIVE_LOW) + *lookupflags |= GPIO_ACTIVE_LOW; + + return 0; +} + struct acpi_gpio_lookup { struct acpi_gpio_info info; int index; @@ -745,10 +754,8 @@ struct gpio_desc *acpi_find_gpio(struct device *dev, return ERR_PTR(-ENOENT); } - if (info.polarity == GPIO_ACTIVE_LOW) - *lookupflags |= GPIO_ACTIVE_LOW; - acpi_gpio_update_gpiod_flags(dflags, &info); + acpi_gpio_update_gpiod_lookup_flags(lookupflags, &info); return desc; } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index b8e4c9cd7b9e..bfbe5d7af372 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -4350,9 +4350,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, return desc; acpi_gpio_update_gpiod_flags(&dflags, &info); - - if (info.polarity == GPIO_ACTIVE_LOW) - lflags |= GPIO_ACTIVE_LOW; + acpi_gpio_update_gpiod_lookup_flags(&lflags, &info); } /* Currently only ACPI takes this path */ diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 5dbfce616ae1..e1636e152a6c 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -125,6 +125,8 @@ 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, @@ -153,6 +155,12 @@ acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *inf { 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, From 2d3b6db122ce9aa0a0460e618516e6bfa8eef329 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 10 Apr 2019 18:39:21 +0300 Subject: [PATCH 81/85] gpiolib: acpi: Respect pin bias setting For now, we don't take into account the pin bias settings supplied by ACPI. This change is targeting the mentioned gap. Signed-off-by: Andy Shevchenko Acked-by: Hans de Goede Reviewed-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 12 ++++++++++++ drivers/gpio/gpiolib.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 9c6ebaaa02fe..c9fc9e232aaf 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -528,6 +528,17 @@ acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *inf int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags, struct acpi_gpio_info *info) { + switch (info->pin_config) { + case ACPI_PIN_CONFIG_PULLUP: + *lookupflags |= GPIO_PULL_UP; + break; + case ACPI_PIN_CONFIG_PULLDOWN: + *lookupflags |= GPIO_PULL_DOWN; + break; + default: + break; + } + if (info->polarity == GPIO_ACTIVE_LOW) *lookupflags |= GPIO_ACTIVE_LOW; @@ -567,6 +578,7 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data) lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr, agpio->pin_table[pin_index]); + lookup->info.pin_config = agpio->pin_config; lookup->info.gpioint = gpioint; /* diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index e1636e152a6c..cf79b1d78af0 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -74,6 +74,7 @@ struct gpio_device { * @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 @@ -82,6 +83,7 @@ struct acpi_gpio_info { struct acpi_device *adev; enum gpiod_flags flags; bool gpioint; + int pin_config; int polarity; int triggering; unsigned int quirks; From 1e9aa2a8164fa5b443b10962045eef01d7eeb9f7 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Tue, 16 Apr 2019 22:56:12 +0800 Subject: [PATCH 82/85] gpio: pxa: Make two symbols static Fix sparse warnings: drivers/gpio/gpio-pxa.c:580:29: warning: symbol 'pxa_irq_domain_ops' was not declared. Should it be static? drivers/gpio/gpio-pxa.c:819:20: warning: symbol 'pxa_gpio_syscore_ops' was not declared. Should it be static? Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pxa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index dd479607b66a..26f77fdb217e 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -577,7 +577,7 @@ static int pxa_irq_domain_map(struct irq_domain *d, unsigned int irq, return 0; } -const struct irq_domain_ops pxa_irq_domain_ops = { +static const struct irq_domain_ops pxa_irq_domain_ops = { .map = pxa_irq_domain_map, .xlate = irq_domain_xlate_twocell, }; @@ -812,7 +812,7 @@ static void pxa_gpio_resume(void) #define pxa_gpio_resume NULL #endif -struct syscore_ops pxa_gpio_syscore_ops = { +static struct syscore_ops pxa_gpio_syscore_ops = { .suspend = pxa_gpio_suspend, .resume = pxa_gpio_resume, }; From 4a4b119b176e992912941a1e9dfa9d138b1c2faa Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Thu, 18 Apr 2019 11:23:48 +0200 Subject: [PATCH 83/85] gpio: sch: Remove write-only core_base Signed-off-by: Jan Kiszka Signed-off-by: Linus Walleij --- drivers/gpio/gpio-sch.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c index c333046d02b8..fb143f28c386 100644 --- a/drivers/gpio/gpio-sch.c +++ b/drivers/gpio/gpio-sch.c @@ -23,7 +23,6 @@ struct sch_gpio { struct gpio_chip chip; spinlock_t lock; unsigned short iobase; - unsigned short core_base; unsigned short resume_base; }; @@ -166,7 +165,6 @@ static int sch_gpio_probe(struct platform_device *pdev) switch (pdev->id) { case PCI_DEVICE_ID_INTEL_SCH_LPC: - sch->core_base = 0; sch->resume_base = 10; sch->chip.ngpio = 14; @@ -185,19 +183,16 @@ static int sch_gpio_probe(struct platform_device *pdev) break; case PCI_DEVICE_ID_INTEL_ITC_LPC: - sch->core_base = 0; sch->resume_base = 5; sch->chip.ngpio = 14; break; case PCI_DEVICE_ID_INTEL_CENTERTON_ILB: - sch->core_base = 0; sch->resume_base = 21; sch->chip.ngpio = 30; break; case PCI_DEVICE_ID_INTEL_QUARK_X1000_ILB: - sch->core_base = 0; sch->resume_base = 2; sch->chip.ngpio = 8; break; From 7358a821f0b571e824fa531c4f764000eeee320a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Apr 2019 10:27:04 -0300 Subject: [PATCH 84/85] docs: gpio: convert docs to ReST and rename to *.rst The API described at sysfs.txt is deprecated. Still, as it is still part of the Kernel (and will likely be there for some time, as we don't simply remove APIs). So, it makes sense to keep it there. The conversion of this file is trivial: - add blank lines and identation in order to identify paragraphs; - mark a literal block as such. At its new index.rst, let's add a :orphan: while this is not linked to the main index.rst file, in order to avoid build warnings. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Linus Walleij --- Documentation/gpio/index.rst | 17 +++++++++ Documentation/gpio/{sysfs.txt => sysfs.rst} | 39 +++++++++++++-------- 2 files changed, 42 insertions(+), 14 deletions(-) create mode 100644 Documentation/gpio/index.rst rename Documentation/gpio/{sysfs.txt => sysfs.rst} (86%) diff --git a/Documentation/gpio/index.rst b/Documentation/gpio/index.rst new file mode 100644 index 000000000000..09a4a553f434 --- /dev/null +++ b/Documentation/gpio/index.rst @@ -0,0 +1,17 @@ +:orphan: + +==== +gpio +==== + +.. toctree:: + :maxdepth: 1 + + sysfs + +.. only:: subproject and html + + Indices + ======= + + * :ref:`genindex` diff --git a/Documentation/gpio/sysfs.txt b/Documentation/gpio/sysfs.rst similarity index 86% rename from Documentation/gpio/sysfs.txt rename to Documentation/gpio/sysfs.rst index 58eeab81f349..ec09ffd983e7 100644 --- a/Documentation/gpio/sysfs.txt +++ b/Documentation/gpio/sysfs.rst @@ -1,10 +1,12 @@ GPIO Sysfs Interface for Userspace ================================== -THIS ABI IS DEPRECATED, THE ABI DOCUMENTATION HAS BEEN MOVED TO -Documentation/ABI/obsolete/sysfs-gpio AND NEW USERSPACE CONSUMERS -ARE SUPPOSED TO USE THE CHARACTER DEVICE ABI. THIS OLD SYSFS ABI WILL -NOT BE DEVELOPED (NO NEW FEATURES), IT WILL JUST BE MAINTAINED. +.. warning:: + + THIS ABI IS DEPRECATED, THE ABI DOCUMENTATION HAS BEEN MOVED TO + Documentation/ABI/obsolete/sysfs-gpio AND NEW USERSPACE CONSUMERS + ARE SUPPOSED TO USE THE CHARACTER DEVICE ABI. THIS OLD SYSFS ABI WILL + NOT BE DEVELOPED (NO NEW FEATURES), IT WILL JUST BE MAINTAINED. Refer to the examples in tools/gpio/* for an introduction to the new character device ABI. Also see the userspace header in @@ -51,13 +53,15 @@ The control interfaces are write-only: /sys/class/gpio/ - "export" ... Userspace may ask the kernel to export control of + "export" ... + Userspace may ask the kernel to export control of a GPIO to userspace by writing its number to this file. Example: "echo 19 > export" will create a "gpio19" node for GPIO #19, if that's not requested by kernel code. - "unexport" ... Reverses the effect of exporting to userspace. + "unexport" ... + Reverses the effect of exporting to userspace. Example: "echo 19 > unexport" will remove a "gpio19" node exported using the "export" file. @@ -67,7 +71,8 @@ and have the following read/write attributes: /sys/class/gpio/gpioN/ - "direction" ... reads as either "in" or "out". This value may + "direction" ... + reads as either "in" or "out". This value may normally be written. Writing as "out" defaults to initializing the value as low. To ensure glitch free operation, values "low" and "high" may be written to @@ -78,7 +83,8 @@ and have the following read/write attributes: it was exported by kernel code that didn't explicitly allow userspace to reconfigure this GPIO's direction. - "value" ... reads as either 0 (low) or 1 (high). If the GPIO + "value" ... + reads as either 0 (low) or 1 (high). If the GPIO is configured as an output, this value may be written; any nonzero value is treated as high. @@ -92,14 +98,16 @@ and have the following read/write attributes: file and read the new value or close the file and re-open it to read the value. - "edge" ... reads as either "none", "rising", "falling", or + "edge" ... + reads as either "none", "rising", "falling", or "both". Write these strings to select the signal edge(s) that will make poll(2) on the "value" file return. This file exists only if the pin can be configured as an interrupt generating input pin. - "active_low" ... reads as either 0 (false) or 1 (true). Write + "active_low" ... + reads as either 0 (false) or 1 (true). Write any nonzero value to invert the value attribute both for reading and writing. Existing and subsequent poll(2) support configuration via the edge attribute @@ -112,11 +120,14 @@ read-only attributes: /sys/class/gpio/gpiochipN/ - "base" ... same as N, the first GPIO managed by this chip + "base" ... + same as N, the first GPIO managed by this chip - "label" ... provided for diagnostics (not always unique) + "label" ... + provided for diagnostics (not always unique) - "ngpio" ... how many GPIOs this manages (N to N + ngpio - 1) + "ngpio" ... + how many GPIOs this manages (N to N + ngpio - 1) Board documentation should in most cases cover what GPIOs are used for what purposes. However, those numbers are not always stable; GPIOs on @@ -129,7 +140,7 @@ the correct GPIO number to use for a given signal. Exporting from Kernel code -------------------------- Kernel code can explicitly manage exports of GPIOs which have already been -requested using gpio_request(): +requested using gpio_request():: /* export the GPIO to userspace */ int gpiod_export(struct gpio_desc *desc, bool direction_may_change); From 0fbee1df2078fa1f61e2da14f51ceb357c79ae69 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 20 Apr 2019 13:03:34 +0200 Subject: [PATCH 85/85] gpio: Update documentation Strictify the language a bit, move things around, make proper headings, mention pull-up and pull-down, expand unreadable acronyms etc. Signed-off-by: Linus Walleij --- Documentation/driver-api/gpio/driver.rst | 361 ++++++++++++++--------- 1 file changed, 229 insertions(+), 132 deletions(-) diff --git a/Documentation/driver-api/gpio/driver.rst b/Documentation/driver-api/gpio/driver.rst index 3043167fc557..1ce7fcd0f989 100644 --- a/Documentation/driver-api/gpio/driver.rst +++ b/Documentation/driver-api/gpio/driver.rst @@ -1,10 +1,8 @@ -================================ -GPIO Descriptor Driver Interface -================================ +===================== +GPIO Driver Interface +===================== -This document serves as a guide for GPIO chip drivers writers. Note that it -describes the new descriptor-based interface. For a description of the -deprecated integer-based GPIO interface please refer to gpio-legacy.txt. +This document serves as a guide for writers of GPIO chip drivers. Each GPIO controller driver needs to include the following header, which defines the structures used to define a GPIO driver: @@ -15,32 +13,49 @@ the structures used to define a GPIO driver: Internal Representation of GPIOs ================================ -Inside a GPIO driver, individual GPIOs are identified by their hardware number, -which is a unique number between 0 and n, n being the number of GPIOs managed by -the chip. This number is purely internal: the hardware number of a particular -GPIO descriptor is never made visible outside of the driver. +A GPIO chip handles one or more GPIO lines. To be considered a GPIO chip, the +lines must conform to the definition: General Purpose Input/Output. If the +line is not general purpose, it is not GPIO and should not be handled by a +GPIO chip. The use case is the indicative: certain lines in a system may be +called GPIO but serve a very particular purpose thus not meeting the criteria +of a general purpose I/O. On the other hand a LED driver line may be used as a +GPIO and should therefore still be handled by a GPIO chip driver. -On top of this internal number, each GPIO also need to have a global number in -the integer GPIO namespace so that it can be used with the legacy GPIO +Inside a GPIO driver, individual GPIO lines are identified by their hardware +number, sometime also referred to as ``offset``, which is a unique number +between 0 and n-1, n being the number of GPIOs managed by the chip. + +The hardware GPIO number should be something intuitive to the hardware, for +example if a system uses a memory-mapped set of I/O-registers where 32 GPIO +lines are handled by one bit per line in a 32-bit register, it makes sense to +use hardware offsets 0..31 for these, corresponding to bits 0..31 in the +register. + +This number is purely internal: the hardware number of a particular GPIO +line is never made visible outside of the driver. + +On top of this internal number, each GPIO line also needs to have a global +number in the integer GPIO namespace so that it can be used with the legacy GPIO interface. Each chip must thus have a "base" number (which can be automatically -assigned), and for each GPIO the global number will be (base + hardware number). -Although the integer representation is considered deprecated, it still has many -users and thus needs to be maintained. +assigned), and for each GPIO line the global number will be (base + hardware +number). Although the integer representation is considered deprecated, it still +has many users and thus needs to be maintained. -So for example one platform could use numbers 32-159 for GPIOs, with a +So for example one platform could use global numbers 32-159 for GPIOs, with a controller defining 128 GPIOs at a "base" of 32 ; while another platform uses -numbers 0..63 with one set of GPIO controllers, 64-79 with another type of GPIO -controller, and on one particular board 80-95 with an FPGA. The numbers need not -be contiguous; either of those platforms could also use numbers 2000-2063 to -identify GPIOs in a bank of I2C GPIO expanders. +global numbers 0..63 with one set of GPIO controllers, 64-79 with another type +of GPIO controller, and on one particular board 80-95 with an FPGA. The legacy +numbers need not be contiguous; either of those platforms could also use numbers +2000-2063 to identify GPIO lines in a bank of I2C GPIO expanders. Controller Drivers: gpio_chip ============================= In the gpiolib framework each GPIO controller is packaged as a "struct -gpio_chip" (see linux/gpio/driver.h for its complete definition) with members -common to each controller of that type: +gpio_chip" (see for its complete definition) with members +common to each controller of that type, these should be assigned by the +driver code: - methods to establish GPIO line direction - methods used to access GPIO line values @@ -48,12 +63,12 @@ common to each controller of that type: - method to return the IRQ number associated to a given GPIO line - flag saying whether calls to its methods may sleep - optional line names array to identify lines - - optional debugfs dump method (showing extra state like pullup config) + - optional debugfs dump method (showing extra state information) - optional base number (will be automatically assigned if omitted) - optional label for diagnostics and GPIO chip mapping using platform data The code implementing a gpio_chip should support multiple instances of the -controller, possibly using the driver model. That code will configure each +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. @@ -62,24 +77,28 @@ 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. Chips such as audio codecs will have complex non-GPIO states. -Any debugfs dump method should normally ignore signals which haven't been -requested as GPIOs. They can use gpiochip_is_requested(), which returns either -NULL or the label associated with that GPIO when it was requested. +Any debugfs dump method should normally ignore lines which haven't been +requested. They can use gpiochip_is_requested(), which returns either +NULL or the label associated with that GPIO line when it was requested. -RT_FULL: the GPIO driver should not use spinlock_t or any sleepable APIs -(like PM runtime) in its gpio_chip implementation (.get/.set and direction -control callbacks) if it is expected to call GPIO APIs from atomic context -on -RT (inside hard IRQ handlers and similar contexts). Normally this should -not be required. +Realtime considerations: the GPIO driver should not use spinlock_t or any +sleepable APIs (like PM runtime) in its gpio_chip implementation (.get/.set +and direction control callbacks) if it is expected to call GPIO APIs from +atomic context on realtime kernels (inside hard IRQ handlers and similar +contexts). Normally this should not be required. GPIO electrical configuration ----------------------------- -GPIOs can be configured for several electrical modes of operation by using the -.set_config() callback. Currently this API supports setting debouncing and -single-ended modes (open drain/open source). These settings are described -below. +GPIO lines can be configured for several electrical modes of operation by using +the .set_config() callback. Currently this API supports setting: + +- Debouncing +- Single-ended modes (open drain/open source) +- Pull up and pull down resistor enablement + +These settings are described below. The .set_config() callback uses the same enumerators and configuration semantics as the generic pin control drivers. This is not a coincidence: it is @@ -94,8 +113,8 @@ description needs to provide "GPIO ranges" mapping the GPIO line offsets to pin numbers on the pin controller so they can properly cross-reference each other. -GPIOs with debounce support ---------------------------- +GPIO lines with debounce support +-------------------------------- Debouncing is a configuration set to a pin indicating that it is connected to a mechanical switch or button, or similar that may bounce. Bouncing means the @@ -111,8 +130,8 @@ a certain number of milliseconds for debouncing, or just "on/off" if that time is not configurable. -GPIOs with open drain/source support ------------------------------------- +GPIO lines with open drain/source support +----------------------------------------- Open drain (CMOS) or open collector (TTL) means the line is not actively driven high: instead you provide the drain/collector as output, so when the transistor @@ -132,13 +151,13 @@ This configuration is normally used as a way to achieve one of two things: - Level-shifting: to reach a logical level higher than that of the silicon where the output resides. -- inverse wire-OR on an I/O line, for example a GPIO line, making it possible +- Inverse wire-OR on an I/O line, for example a GPIO line, making it possible for any driving stage on the line to drive it low even if any other output to the same line is simultaneously driving it high. A special case of this is driving the SCL and SDA lines of an I2C bus, which is by definition a wire-OR bus. -Both usecases require that the line be equipped with a pull-up resistor. This +Both use cases require that the line be equipped with a pull-up resistor. This resistor will make the line tend to high level unless one of the transistors on the rail actively pulls it down. @@ -208,27 +227,91 @@ For open source configuration the same principle is used, just that instead of actively driving the line low, it is set to input. +GPIO lines with pull up/down resistor support +--------------------------------------------- + +A GPIO line can support pull-up/down using the .set_config() callback. This +means that a pull up or pull-down resistor is available on the output of the +GPIO line, and this resistor is software controlled. + +In discrete designs, a pull-up or pull-down resistor is simply soldered on +the circuit board. This is not something we deal or model in software. The +most you will think about these lines is that they will very likely be +configured as open drain or open source (see the section above). + +The .set_config() callback can only turn pull up or down on and off, and will +no have any semantic knowledge about the resistance used. It will only say +switch a bit in a register enabling or disabling pull-up or pull-down. + +If the GPIO line supports shunting in different resistance values for the +pull-up or pull-down resistor, the GPIO chip callback .set_config() will not +suffice. For these complex use cases, a combined GPIO chip and pin controller +need to be implemented, as the pin config interface of a pin controller +supports more versatile control over electrical properties and can handle +different pull-up or pull-down resistance values. + + GPIO drivers providing IRQs ---------------------------- +=========================== + It is custom that GPIO drivers (GPIO chips) are also providing interrupts, 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 irqchip, using +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- systems simultaneously: gpio and irq. -RT_FULL: a realtime compliant GPIO driver should not use spinlock_t or any -sleepable APIs (like PM runtime) as part of its irq_chip implementation. +It is legal for any IRQ consumer to request an IRQ from any irqchip even if it +is a combined GPIO+IRQ driver. The basic premise is that gpio_chip and +irq_chip are orthogonal, and offering their services independent of each +other. -* spinlock_t should be replaced with raw_spinlock_t [1]. -* If sleepable APIs have to be used, these can be done from the .irq_bus_lock() +gpiod_to_irq() is just a convenience function to figure out the IRQ for a +certain GPIO line and should not be relied upon to have been called before +the IRQ is used. + +Always prepare the hardware and make it ready for action in respective +callbacks from the GPIO and irq_chip APIs. Do not rely on gpiod_to_irq() having +been called first. + +We can divide GPIO irqchips in two broad categories: + +- CASCADED INTERRUPT CHIPS: this means that the GPIO chip has one common + interrupt output line, which is triggered by any enabled GPIO line on that + chip. The interrupt output line will then be routed to an parent interrupt + controller one level up, in the most simple case the systems primary + interrupt controller. This is modeled by an irqchip that will inspect bits + inside the GPIO controller to figure out which line fired it. The irqchip + part of the driver needs to inspect registers to figure this out and it + will likely also need to acknowledge that it is handling the interrupt + by clearing some bit (sometime implicitly, by just reading a status + register) and it will often need to set up the configuration such as + edge sensitivity (rising or falling edge, or high/low level interrupt for + example). + +- HIERARCHICAL INTERRUPT CHIPS: this means that each GPIO line has a dedicated + irq line to a parent interrupt controller one level up. There is no need + to inquire the GPIO hardware to figure out which line has figured, but it + may still be necessary to acknowledge the interrupt and set up the + configuration such as edge sensitivity. + +Realtime considerations: a realtime compliant GPIO driver should not use +spinlock_t or any sleepable APIs (like PM runtime) as part of its irqchip +implementation. + +- spinlock_t should be replaced with raw_spinlock_t [1]. +- If sleepable APIs have to be used, these can be done from the .irq_bus_lock() and .irq_bus_unlock() callbacks, as these are the only slowpath callbacks on an irqchip. Create the callbacks if needed [2]. -GPIO irqchips usually fall in one of two categories: -* CHAINED GPIO irqchips: these are usually the type that is embedded on +Cascaded GPIO irqchips +---------------------- + +Cascaded GPIO irqchips usually fall in one of three categories: + +- CHAINED CASCADED GPIO IRQCHIPS: these are usually the type that is embedded on an SoC. This means that there is a fast IRQ flow handler for the GPIOs that gets called in a chain from the parent IRQ handler, most typically the system interrupt controller. This means that the GPIO irqchip handler will @@ -245,16 +328,19 @@ GPIO irqchips usually fall in one of two categories: struct gpio_chip, as everything happens directly in the callbacks: no slow bus traffic like I2C can be used. - RT_FULL: Note, chained IRQ handlers will not be forced threaded on -RT. - As result, spinlock_t or any sleepable APIs (like PM runtime) can't be used - in chained IRQ handler. - If required (and if it can't be converted to the nested threaded GPIO irqchip) - a chained IRQ handler can be converted to generic irq handler and this way - it will be a threaded IRQ handler on -RT and a hard IRQ handler on non-RT - (for example, see [3]). - Know W/A: The generic_handle_irq() is expected to be called with IRQ disabled, + Realtime considerations: Note that chained IRQ handlers will not be forced + threaded on -RT. As a result, spinlock_t or any sleepable APIs (like PM + runtime) can't be used in a chained IRQ handler. + + If required (and if it can't be converted to the nested threaded GPIO irqchip, + see below) a chained IRQ handler can be converted to generic irq handler and + this way it will become a threaded IRQ handler on -RT and a hard IRQ handler + on non-RT (for example, see [3]). + + The generic_handle_irq() is expected to be called with IRQ disabled, so the IRQ core will complain if it is called from an IRQ handler which is - forced to a thread. The "fake?" raw lock can be used to W/A this problem:: + forced to a thread. The "fake?" raw lock can be used to work around this + problem:: raw_spinlock_t wa_lock; static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank) @@ -263,7 +349,7 @@ GPIO irqchips usually fall in one of two categories: generic_handle_irq(irq_find_mapping(bank->chip.irq.domain, bit)); raw_spin_unlock_irqrestore(&bank->wa_lock, wa_lock_flags); -* GENERIC CHAINED GPIO irqchips: these are the same as "CHAINED GPIO irqchips", +- GENERIC CHAINED GPIO IRQCHIPS: these are the same as "CHAINED GPIO irqchips", but chained IRQ handlers are not used. Instead GPIO IRQs dispatching is performed by generic IRQ handler which is configured using request_irq(). The GPIO irqchip will then end up calling something like this sequence in @@ -273,16 +359,19 @@ GPIO irqchips usually fall in one of two categories: for each detected GPIO IRQ generic_handle_irq(...); - RT_FULL: Such kind of handlers will be forced threaded on -RT, as result IRQ - core will complain that generic_handle_irq() is called with IRQ enabled and - the same W/A as for "CHAINED GPIO irqchips" can be applied. + Realtime considerations: this kind of handlers will be forced threaded on -RT, + and as result the IRQ core will complain that generic_handle_irq() is called + with IRQ enabled and the same work around as for "CHAINED GPIO irqchips" can + be applied. -* NESTED THREADED GPIO irqchips: these are off-chip GPIO expanders and any - other GPIO irqchip residing on the other side of a sleeping bus. Of course - such drivers that need slow bus traffic to read out IRQ status and similar, - traffic which may in turn incur other IRQs to happen, cannot be handled - in a quick IRQ handler with IRQs disabled. Instead they need to spawn a - thread and then mask the parent IRQ line until the interrupt is handled +- NESTED THREADED GPIO IRQCHIPS: these are off-chip GPIO expanders and any + other GPIO irqchip residing on the other side of a sleeping bus such as I2C + or SPI. + + Of course such drivers that need slow bus traffic to read out IRQ status and + similar, traffic which may in turn incur other IRQs to happen, cannot be + handled in a quick IRQ handler with IRQs disabled. Instead they need to spawn + a thread and then mask the parent IRQ line until the interrupt is handled by the driver. The hallmark of this driver is to call something like this in its interrupt handler:: @@ -294,36 +383,46 @@ GPIO irqchips usually fall in one of two categories: flag on struct gpio_chip to true, indicating that this chip may sleep when accessing the GPIOs. + These kinds of irqchips are inherently realtime tolerant as they are + already set up to handle sleeping contexts. + + +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: -* gpiochip_irqchip_add(): adds a chained 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(). +- 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 irqchip to a gpiochip. +- 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 irq handler for a +- 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 handler data, since the irqchip data is likely used by the - parent irqchip!). + 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 irq handler for a +- 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 explicitly requested by the driver, this does very little more than mark all the child IRQs as having the other IRQ as parent. -If there is a need to exclude certain GPIOs from the IRQ domain, you can -set .irq.need_valid_mask of the gpiochip before gpiochip_add_data() is -called. This allocates an .irq.valid_mask with as many bits set as there -are GPIOs in the chip. Drivers can exclude GPIOs by clearing bits from this -mask. The mask must be filled in before gpiochip_irqchip_add() or -gpiochip_irqchip_add_nested() is called. +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. To use the helpers please keep the following in mind: @@ -333,33 +432,24 @@ To use the helpers please keep the following in mind: - Nominally set all handlers to handle_bad_irq() in the setup call and pass handle_bad_irq() as flow handler parameter in gpiochip_irqchip_add() if it is - expected for GPIO driver that irqchip .set_type() callback have to be called - before using/enabling GPIO IRQ. Then set the handler to handle_level_irq() - and/or handle_edge_irq() in the irqchip .set_type() callback depending on - what your controller supports. - -It is legal for any IRQ consumer to request an IRQ from any irqchip no matter -if that is a combined GPIO+IRQ driver. The basic premise is that gpio_chip and -irq_chip are orthogonal, and offering their services independent of each -other. - -gpiod_to_irq() is just a convenience function to figure out the IRQ for a -certain GPIO line and should not be relied upon to have been called before -the IRQ is used. - -So always prepare the hardware and make it ready for action in respective -callbacks from the GPIO and irqchip APIs. Do not rely on gpiod_to_irq() having -been called first. - -This orthogonality leads to ambiguities that we need to solve: if there is -competition inside the subsystem which side is using the resource (a certain -GPIO line and register for example) it needs to deny certain operations and -keep track of usage inside of the gpiolib subsystem. This is why the API -below exists. + expected for GPIO driver that irqchip .set_type() callback will be called + before using/enabling each GPIO IRQ. Then set the handler to + handle_level_irq() and/or handle_edge_irq() in the irqchip .set_type() + callback depending on what your controller supports and what is requested + by the consumer. Locking IRQ usage ----------------- + +Since GPIO and irq_chip are orthogonal, we can get conflicts between different +use cases. For example a GPIO line used for IRQs should be an input line, +it does not make sense to fire interrupts on an output GPIO. + +If there is competition inside the subsystem which side is using the +resource (a certain GPIO line and register for example) it needs to deny +certain operations and keep track of usage inside of the gpiolib subsystem. + Input GPIOs can be used as IRQ signals. When this happens, a driver is requested to mark the GPIO as being used as an IRQ:: @@ -380,9 +470,15 @@ assigned. Disabling and enabling IRQs --------------------------- + +In some (fringe) use cases, a driver may be using a GPIO line as input for IRQs, +but occasionally switch that line over to drive output and then back to being +an input with interrupts again. This happens on things like CEC (Consumer +Electronics Control). + When a GPIO is used as an IRQ signal, then gpiolib also needs to know if the IRQ is enabled or disabled. In order to inform gpiolib about this, -a driver should call:: +the irqchip driver should call:: void gpiochip_disable_irq(struct gpio_chip *chip, unsigned int offset) @@ -398,40 +494,45 @@ irqchip. When using the gpiolib irqchip helpers, these callbacks are automatically assigned. + Real-Time compliance for GPIO IRQ chips --------------------------------------- -Any provider of irqchips needs to be carefully tailored to support Real Time +Any provider of irqchips needs to be carefully tailored to support Real-Time preemption. It is desirable that all irqchips in the GPIO subsystem keep this in mind and do the proper testing to assure they are real time-enabled. -So, pay attention on above " RT_FULL:" notes, please. -The following is a checklist to follow when preparing a driver for real -time-compliance: -- ensure spinlock_t is not used as part irq_chip implementation; -- ensure that sleepable APIs are not used as part irq_chip implementation. +So, pay attention on above realtime considerations in the documentation. + +The following is a checklist to follow when preparing a driver for real-time +compliance: + +- ensure spinlock_t is not used as part irq_chip implementation +- ensure that sleepable APIs are not used as part irq_chip implementation If sleepable APIs have to be used, these can be done from the .irq_bus_lock() - and .irq_bus_unlock() callbacks; + and .irq_bus_unlock() callbacks - Chained GPIO irqchips: ensure spinlock_t or any sleepable APIs are not used - from chained IRQ handler; + from the chained IRQ handler - Generic chained GPIO irqchips: take care about generic_handle_irq() calls and - apply corresponding W/A; -- Chained GPIO irqchips: get rid of chained IRQ handler and use generic irq - handler if possible :) -- regmap_mmio: Sry, but you are in trouble :( if MMIO regmap is used as for - GPIO IRQ chip implementation; -- Test your driver with the appropriate in-kernel real time test cases for both - level and edge IRQs. + apply corresponding work-around +- Chained GPIO irqchips: get rid of the chained IRQ handler and use generic irq + handler if possible +- regmap_mmio: it is possible to disable internal locking in regmap by setting + .disable_locking and handling the locking in the GPIO driver +- Test your driver with the appropriate in-kernel real-time test cases for both + level and edge IRQs + +* [1] http://www.spinics.net/lists/linux-omap/msg120425.html +* [2] https://lkml.org/lkml/2015/9/25/494 +* [3] https://lkml.org/lkml/2015/9/25/495 Requesting self-owned GPIO pins -------------------------------- +=============================== Sometimes it is useful to allow a GPIO chip driver to request its own GPIO -descriptors through the gpiolib API. Using gpio_request() for this purpose -does not help since it pins the module to the kernel forever (it calls -try_module_get()). A GPIO driver can use the following functions instead -to request and free descriptors without being pinned to the kernel forever:: +descriptors through the gpiolib API. A GPIO driver can use the following +functions to request and free descriptors:: struct gpio_desc *gpiochip_request_own_desc(struct gpio_desc *desc, u16 hwnum, @@ -446,7 +547,3 @@ gpiochip_free_own_desc(). These functions must be used with care since they do not affect module use count. Do not use the functions to request gpio descriptors not owned by the calling driver. - -* [1] http://www.spinics.net/lists/linux-omap/msg120425.html -* [2] https://lkml.org/lkml/2015/9/25/494 -* [3] https://lkml.org/lkml/2015/9/25/495