diff options
Diffstat (limited to 'drivers/gpio')
50 files changed, 979 insertions, 735 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index a77b3b25a779..8023d03ec362 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -12,7 +12,6 @@ config ARCH_HAVE_CUSTOM_GPIO_H menuconfig GPIOLIB bool "GPIO Support" - select ANON_INODES help This enables GPIO support through the generic GPIO library. You only need to enable this, if you also want to enable @@ -27,12 +26,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 @@ -333,7 +332,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" @@ -343,20 +342,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 && SYSFS - select GPIO_SYSFS - select GPIOLIB_IRQCHIP - 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 @@ -875,11 +860,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. @@ -906,17 +891,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" @@ -938,7 +923,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 @@ -1060,9 +1045,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" @@ -1098,7 +1083,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" @@ -1125,6 +1110,13 @@ config GPIO_MAX77620 driver also provides interrupt support for each of the gpios. Say yes here to enable the max77620 to be used as gpio controller. +config GPIO_MAX77650 + tristate "Maxim MAX77650/77651 GPIO support" + depends on MFD_MAX77650 + help + GPIO driver for MAX77650/77651 PMIC from Maxim Semiconductor. + These chips have a single pin that can be configured as GPIO. + config GPIO_MSIC bool "Intel MSIC mixed signal gpio support" depends on (X86 || COMPILE_TEST) && MFD_INTEL_MSIC @@ -1329,6 +1321,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) || (64BIT && 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 @@ -1449,10 +1448,22 @@ 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 +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 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 1ee5dab9c3cf..6700eee860b7 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -81,11 +81,13 @@ obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o obj-$(CONFIG_GPIO_MAX77620) += gpio-max77620.o +obj-$(CONFIG_GPIO_MAX77650) += gpio-max77650.o obj-$(CONFIG_GPIO_MB86S7X) += gpio-mb86s7x.o 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-74x164.c b/drivers/gpio/gpio-74x164.c index fb7b620763a2..e81307f9754e 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -1,21 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * 74Hx164 - Generic serial-in/parallel-out 8-bits shift register GPIO driver * * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> * Copyright (C) 2010 Miguel Gaio <miguel.gaio@efixo.com> - * - * 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 <linux/init.h> -#include <linux/mutex.h> -#include <linux/spi/spi.h> -#include <linux/gpio/driver.h> #include <linux/gpio/consumer.h> -#include <linux/slab.h> +#include <linux/gpio/driver.h> #include <linux/module.h> +#include <linux/mutex.h> +#include <linux/property.h> +#include <linux/slab.h> +#include <linux/spi/spi.h> #define GEN_74X164_NUMBER_GPIOS 8 @@ -116,10 +113,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; } 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); 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); diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index 217507002dbc..0f1b55c7c361 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); 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; 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); 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); 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); diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c index f0223cee9774..77092268ee95 100644 --- a/drivers/gpio/gpio-eic-sprd.c +++ b/drivers/gpio/gpio-eic-sprd.c @@ -414,6 +414,7 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type) irq_set_handler_locked(data, handle_edge_irq); break; case IRQ_TYPE_EDGE_BOTH: + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 0); sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 1); irq_set_handler_locked(data, handle_edge_irq); break; 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); 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); 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); 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); 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); 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; diff --git a/drivers/gpio/gpio-max77650.c b/drivers/gpio/gpio-max77650.c new file mode 100644 index 000000000000..3f03f4e8956c --- /dev/null +++ b/drivers/gpio/gpio-max77650.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2018 BayLibre SAS +// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com> +// +// GPIO driver for MAXIM 77650/77651 charger/power-supply. + +#include <linux/gpio/driver.h> +#include <linux/i2c.h> +#include <linux/mfd/max77650.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#define MAX77650_GPIO_DIR_MASK BIT(0) +#define MAX77650_GPIO_INVAL_MASK BIT(1) +#define MAX77650_GPIO_DRV_MASK BIT(2) +#define MAX77650_GPIO_OUTVAL_MASK BIT(3) +#define MAX77650_GPIO_DEBOUNCE_MASK BIT(4) + +#define MAX77650_GPIO_DIR_OUT 0x00 +#define MAX77650_GPIO_DIR_IN BIT(0) +#define MAX77650_GPIO_OUT_LOW 0x00 +#define MAX77650_GPIO_OUT_HIGH BIT(3) +#define MAX77650_GPIO_DRV_OPEN_DRAIN 0x00 +#define MAX77650_GPIO_DRV_PUSH_PULL BIT(2) +#define MAX77650_GPIO_DEBOUNCE BIT(4) + +#define MAX77650_GPIO_DIR_BITS(_reg) \ + ((_reg) & MAX77650_GPIO_DIR_MASK) +#define MAX77650_GPIO_INVAL_BITS(_reg) \ + (((_reg) & MAX77650_GPIO_INVAL_MASK) >> 1) + +struct max77650_gpio_chip { + struct regmap *map; + struct gpio_chip gc; + int irq; +}; + +static int max77650_gpio_direction_input(struct gpio_chip *gc, + unsigned int offset) +{ + struct max77650_gpio_chip *chip = gpiochip_get_data(gc); + + return regmap_update_bits(chip->map, + MAX77650_REG_CNFG_GPIO, + MAX77650_GPIO_DIR_MASK, + MAX77650_GPIO_DIR_IN); +} + +static int max77650_gpio_direction_output(struct gpio_chip *gc, + unsigned int offset, int value) +{ + struct max77650_gpio_chip *chip = gpiochip_get_data(gc); + int mask, regval; + + mask = MAX77650_GPIO_DIR_MASK | MAX77650_GPIO_OUTVAL_MASK; + regval = value ? MAX77650_GPIO_OUT_HIGH : MAX77650_GPIO_OUT_LOW; + regval |= MAX77650_GPIO_DIR_OUT; + + return regmap_update_bits(chip->map, + MAX77650_REG_CNFG_GPIO, mask, regval); +} + +static void max77650_gpio_set_value(struct gpio_chip *gc, + unsigned int offset, int value) +{ + struct max77650_gpio_chip *chip = gpiochip_get_data(gc); + int rv, regval; + + regval = value ? MAX77650_GPIO_OUT_HIGH : MAX77650_GPIO_OUT_LOW; + + rv = regmap_update_bits(chip->map, MAX77650_REG_CNFG_GPIO, + MAX77650_GPIO_OUTVAL_MASK, regval); + if (rv) + dev_err(gc->parent, "cannot set GPIO value: %d\n", rv); +} + +static int max77650_gpio_get_value(struct gpio_chip *gc, + unsigned int offset) +{ + struct max77650_gpio_chip *chip = gpiochip_get_data(gc); + unsigned int val; + int rv; + + rv = regmap_read(chip->map, MAX77650_REG_CNFG_GPIO, &val); + if (rv) + return rv; + + return MAX77650_GPIO_INVAL_BITS(val); +} + +static int max77650_gpio_get_direction(struct gpio_chip *gc, + unsigned int offset) +{ + struct max77650_gpio_chip *chip = gpiochip_get_data(gc); + unsigned int val; + int rv; + + rv = regmap_read(chip->map, MAX77650_REG_CNFG_GPIO, &val); + if (rv) + return rv; + + return MAX77650_GPIO_DIR_BITS(val); +} + +static int max77650_gpio_set_config(struct gpio_chip *gc, + unsigned int offset, unsigned long cfg) +{ + struct max77650_gpio_chip *chip = gpiochip_get_data(gc); + + switch (pinconf_to_config_param(cfg)) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + return regmap_update_bits(chip->map, + MAX77650_REG_CNFG_GPIO, + MAX77650_GPIO_DRV_MASK, + MAX77650_GPIO_DRV_OPEN_DRAIN); + case PIN_CONFIG_DRIVE_PUSH_PULL: + return regmap_update_bits(chip->map, + MAX77650_REG_CNFG_GPIO, + MAX77650_GPIO_DRV_MASK, + MAX77650_GPIO_DRV_PUSH_PULL); + case PIN_CONFIG_INPUT_DEBOUNCE: + return regmap_update_bits(chip->map, + MAX77650_REG_CNFG_GPIO, + MAX77650_GPIO_DEBOUNCE_MASK, + MAX77650_GPIO_DEBOUNCE); + default: + return -ENOTSUPP; + } +} + +static int max77650_gpio_to_irq(struct gpio_chip *gc, unsigned int offset) +{ + struct max77650_gpio_chip *chip = gpiochip_get_data(gc); + + return chip->irq; +} + +static int max77650_gpio_probe(struct platform_device *pdev) +{ + struct max77650_gpio_chip *chip; + struct device *dev, *parent; + struct i2c_client *i2c; + + dev = &pdev->dev; + parent = dev->parent; + i2c = to_i2c_client(parent); + + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->map = dev_get_regmap(parent, NULL); + if (!chip->map) + return -ENODEV; + + chip->irq = platform_get_irq_byname(pdev, "GPI"); + if (chip->irq < 0) + return chip->irq; + + chip->gc.base = -1; + chip->gc.ngpio = 1; + chip->gc.label = i2c->name; + chip->gc.parent = dev; + chip->gc.owner = THIS_MODULE; + chip->gc.can_sleep = true; + + chip->gc.direction_input = max77650_gpio_direction_input; + chip->gc.direction_output = max77650_gpio_direction_output; + chip->gc.set = max77650_gpio_set_value; + chip->gc.get = max77650_gpio_get_value; + chip->gc.get_direction = max77650_gpio_get_direction; + chip->gc.set_config = max77650_gpio_set_config; + chip->gc.to_irq = max77650_gpio_to_irq; + + return devm_gpiochip_add_data(dev, &chip->gc, chip); +} + +static struct platform_driver max77650_gpio_driver = { + .driver = { + .name = "max77650-gpio", + }, + .probe = max77650_gpio_probe, +}; +module_platform_driver(max77650_gpio_driver); + +MODULE_DESCRIPTION("MAXIM 77650/77651 GPIO driver"); +MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>"); +MODULE_LICENSE("GPL v2"); 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); diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c index 7c659fdaa6d5..3302125e5265 100644 --- a/drivers/gpio/gpio-merrifield.c +++ b/drivers/gpio/gpio-merrifield.c @@ -377,10 +377,20 @@ static void mrfld_irq_init_hw(struct mrfld_gpio *priv) } } -static const char *mrfld_gpio_get_pinctrl_dev_name(void) +static const char *mrfld_gpio_get_pinctrl_dev_name(struct mrfld_gpio *priv) { - const char *dev_name = acpi_dev_get_first_match_name("INTC1002", NULL, -1); - return dev_name ? dev_name : "pinctrl-merrifield"; + struct acpi_device *adev; + const char *name; + + adev = acpi_dev_get_first_match_dev("INTC1002", NULL, -1); + if (adev) { + name = devm_kstrdup(priv->dev, acpi_dev_name(adev), GFP_KERNEL); + acpi_dev_put(adev); + } else { + name = "pinctrl-merrifield"; + } + + return name; } static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id) @@ -441,7 +451,7 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id return retval; } - pinctrl_dev_name = mrfld_gpio_get_pinctrl_dev_name(); + pinctrl_dev_name = mrfld_gpio_get_pinctrl_dev_name(priv); for (i = 0; i < ARRAY_SIZE(mrfld_gpio_ranges); i++) { range = &mrfld_gpio_ranges[i]; retval = gpiochip_add_pin_range(&priv->chip, diff --git a/drivers/gpio/gpio-mlxbf.c b/drivers/gpio/gpio-mlxbf.c new file mode 100644 index 000000000000..894aaf55fc96 --- /dev/null +++ b/drivers/gpio/gpio-mlxbf.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/acpi.h> +#include <linux/bitops.h> +#include <linux/device.h> +#include <linux/gpio/driver.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/pm.h> +#include <linux/resource.h> +#include <linux/types.h> + +/* 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"); diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c index 50bdc29591c0..6f904c874678 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; @@ -372,11 +355,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 +369,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 +389,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 +527,12 @@ 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; - 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; + 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; - gc->bgpio_dir_inverted = true; } else { if (flags & BGPIOF_NO_OUTPUT) gc->direction_output = bgpio_dir_out_err; @@ -588,11 +571,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 +617,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/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); 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); 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); 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); diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 7f33024b6d83..16289bafa001 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,8 +73,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); void (*set_dataout_multiple)(struct gpio_bank *bank, @@ -353,6 +341,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) { @@ -363,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); @@ -384,13 +394,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 @@ -403,7 +407,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); @@ -896,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) @@ -1251,203 +1216,70 @@ 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 int gpio_omap_cpu_notifier(struct notifier_block *nb, - unsigned long cmd, void *v) +static void omap_gpio_init_context(struct gpio_bank *p) { - struct gpio_bank *bank; - unsigned long flags; + struct omap_gpio_reg_offs *regs = p->regs; + void __iomem *base = p->base; - bank = container_of(nb, struct gpio_bank, nb); + 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); - raw_spin_lock_irqsave(&bank->lock, flags); - switch (cmd) { - case CPU_CLUSTER_PM_ENTER: - if (bank->is_suspended) - break; - omap_gpio_idle(bank, true); - break; - case CPU_CLUSTER_PM_ENTER_FAILED: - case CPU_CLUSTER_PM_EXIT: - if (bank->is_suspended) - break; - omap_gpio_unidle(bank); - break; - } - raw_spin_unlock_irqrestore(&bank->lock, flags); + 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); - return NOTIFY_OK; + p->context_valid = true; } -static const struct of_device_id omap_gpio_match[]; - -static int omap_gpio_probe(struct platform_device *pdev) +static void omap_gpio_restore_context(struct gpio_bank *bank) { - struct device *dev = &pdev->dev; - 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; - - match = of_match_device(of_match_ptr(omap_gpio_match), dev); - - pdata = match ? match->data : dev_get_platdata(dev); - if (!pdata) - return -EINVAL; - - bank = devm_kzalloc(dev, sizeof(*bank), GFP_KERNEL); - if (!bank) - return -ENOMEM; - - irqc = devm_kzalloc(dev, sizeof(*irqc), GFP_KERNEL); - if (!irqc) - return -ENOMEM; - - irqc->irq_startup = omap_gpio_irq_startup, - irqc->irq_shutdown = omap_gpio_irq_shutdown, - irqc->irq_ack = omap_gpio_ack_irq, - irqc->irq_mask = omap_gpio_mask_irq, - irqc->irq_unmask = omap_gpio_unmask_irq, - irqc->irq_set_type = omap_gpio_irq_type, - irqc->irq_set_wake = omap_gpio_wake_enable, - irqc->irq_bus_lock = omap_gpio_irq_bus_lock, - irqc->irq_bus_sync_unlock = gpio_irq_bus_sync_unlock, - irqc->name = dev_name(&pdev->dev); - irqc->flags = IRQCHIP_MASK_ON_SUSPEND; - irqc->parent_device = dev; - - bank->irq = platform_get_irq(pdev, 0); - if (bank->irq <= 0) { - if (!bank->irq) - bank->irq = -ENXIO; - if (bank->irq != -EPROBE_DEFER) - dev_err(dev, - "can't get irq resource ret=%d\n", bank->irq); - return bank->irq; - } - - 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; - bank->non_wakeup_gpios = pdata->non_wakeup_gpios; - bank->regs = pdata->regs; -#ifdef CONFIG_OF_GPIO - bank->chip.of_node = of_node_get(node); -#endif - - if (node) { - if (!of_property_read_bool(node, "ti,gpio-always-on")) - bank->loses_context = true; - } else { - bank->loses_context = pdata->loses_context; - - if (bank->loses_context) - bank->get_context_loss_count = - pdata->get_context_loss_count; - } - - if (bank->regs->set_dataout && bank->regs->clr_dataout) { - bank->set_dataout = omap_set_gpio_dataout_reg; - bank->set_dataout_multiple = omap_set_gpio_dataout_reg_multiple; - } else { - bank->set_dataout = omap_set_gpio_dataout_mask; - bank->set_dataout_multiple = - 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); - - /* Static mapping, never released */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - bank->base = devm_ioremap_resource(dev, res); - if (IS_ERR(bank->base)) { - return PTR_ERR(bank->base); - } - - if (bank->dbck_flag) { - bank->dbck = devm_clk_get(dev, "dbclk"); - if (IS_ERR(bank->dbck)) { - dev_err(dev, - "Could not get gpio dbck. Disable debounce\n"); - bank->dbck_flag = false; - } else { - clk_prepare(bank->dbck); - } - } - - platform_set_drvdata(pdev, bank); - - pm_runtime_enable(dev); - pm_runtime_get_sync(dev); - - if (bank->is_mpuio) - omap_mpuio_init(bank); - - omap_gpio_mod_init(bank); - - ret = omap_gpio_chip_init(bank, irqc); - if (ret) { - pm_runtime_put_sync(dev); - pm_runtime_disable(dev); - if (bank->dbck_flag) - clk_unprepare(bank->dbck); - return ret; - } - - omap_gpio_show_rev(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->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); + 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); } - pm_runtime_put(dev); - - return 0; -} - -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); - list_del(&bank->node); - gpiochip_remove(&bank->chip); - pm_runtime_disable(&pdev->dev); - if (bank->dbck_flag) - clk_unprepare(bank->dbck); - - return 0; + writel_relaxed(bank->context.irqenable1, + bank->base + bank->regs->irqenable); + writel_relaxed(bank->context.irqenable2, + bank->base + bank->regs->irqenable2); } -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; - if (bank->funcs.idle_enable_level_quirk) - bank->funcs.idle_enable_level_quirk(bank); + bank->saved_datain = readl_relaxed(base + bank->regs->datain); if (!bank->enabled_non_wakeup_gpios) goto update_gpio_context_count; @@ -1456,22 +1288,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); - - bank->workaround_enabled = true; + 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); + } update_gpio_context_count: if (bank->get_context_loss_count) @@ -1481,8 +1306,6 @@ update_gpio_context_count: 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; @@ -1504,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); @@ -1518,11 +1338,14 @@ 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) - return; - l = readl_relaxed(bank->base + bank->regs->datain); /* @@ -1572,117 +1395,35 @@ 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) -{ - 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) +static int gpio_omap_cpu_notifier(struct notifier_block *nb, + unsigned long cmd, void *v) { - struct gpio_bank *bank = dev_get_drvdata(dev); + struct gpio_bank *bank; 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; -} -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; + bank = container_of(nb, struct gpio_bank, nb); raw_spin_lock_irqsave(&bank->lock, flags); - /* Must be unidled only by CPU_CLUSTER_PM_ENTER? */ - if (bank->irq_usage) { - error = -EBUSY; - goto unlock; + switch (cmd) { + case CPU_CLUSTER_PM_ENTER: + if (bank->is_suspended) + break; + omap_gpio_idle(bank, true); + break; + case CPU_CLUSTER_PM_ENTER_FAILED: + case CPU_CLUSTER_PM_EXIT: + if (bank->is_suspended) + break; + omap_gpio_unidle(bank); + break; } - omap_gpio_unidle(bank); - bank->is_suspended = false; -unlock: raw_spin_unlock_irqrestore(&bank->lock, flags); - return error; + return NOTIFY_OK; } -#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, @@ -1729,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, @@ -1744,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[] = { @@ -1770,15 +1504,187 @@ static const struct of_device_id omap_gpio_match[] = { { }, }; MODULE_DEVICE_TABLE(of, omap_gpio_match); + +static int omap_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; + const struct of_device_id *match; + const struct omap_gpio_platform_data *pdata; + struct gpio_bank *bank; + struct irq_chip *irqc; + int ret; + + match = of_match_device(of_match_ptr(omap_gpio_match), dev); + + pdata = match ? match->data : dev_get_platdata(dev); + if (!pdata) + return -EINVAL; + + bank = devm_kzalloc(dev, sizeof(*bank), GFP_KERNEL); + if (!bank) + return -ENOMEM; + + irqc = devm_kzalloc(dev, sizeof(*irqc), GFP_KERNEL); + if (!irqc) + return -ENOMEM; + + irqc->irq_startup = omap_gpio_irq_startup, + irqc->irq_shutdown = omap_gpio_irq_shutdown, + irqc->irq_ack = omap_gpio_ack_irq, + irqc->irq_mask = omap_gpio_mask_irq, + irqc->irq_unmask = omap_gpio_unmask_irq, + irqc->irq_set_type = omap_gpio_irq_type, + irqc->irq_set_wake = omap_gpio_wake_enable, + irqc->irq_bus_lock = omap_gpio_irq_bus_lock, + irqc->irq_bus_sync_unlock = gpio_irq_bus_sync_unlock, + irqc->name = dev_name(&pdev->dev); + irqc->flags = IRQCHIP_MASK_ON_SUSPEND; + irqc->parent_device = dev; + + bank->irq = platform_get_irq(pdev, 0); + if (bank->irq <= 0) { + if (!bank->irq) + bank->irq = -ENXIO; + if (bank->irq != -EPROBE_DEFER) + dev_err(dev, + "can't get irq resource ret=%d\n", bank->irq); + return bank->irq; + } + + bank->chip.parent = dev; + bank->chip.owner = THIS_MODULE; + bank->dbck_flag = pdata->dbck_flag; + bank->stride = pdata->bank_stride; + bank->width = pdata->bank_width; + bank->is_mpuio = pdata->is_mpuio; + bank->non_wakeup_gpios = pdata->non_wakeup_gpios; + bank->regs = pdata->regs; +#ifdef CONFIG_OF_GPIO + bank->chip.of_node = of_node_get(node); #endif + if (node) { + if (!of_property_read_bool(node, "ti,gpio-always-on")) + bank->loses_context = true; + } else { + bank->loses_context = pdata->loses_context; + + if (bank->loses_context) + bank->get_context_loss_count = + pdata->get_context_loss_count; + } + + if (bank->regs->set_dataout && bank->regs->clr_dataout) { + bank->set_dataout = omap_set_gpio_dataout_reg; + bank->set_dataout_multiple = omap_set_gpio_dataout_reg_multiple; + } else { + bank->set_dataout = omap_set_gpio_dataout_mask; + bank->set_dataout_multiple = + omap_set_gpio_dataout_mask_multiple; + } + + raw_spin_lock_init(&bank->lock); + raw_spin_lock_init(&bank->wa_lock); + + /* Static mapping, never released */ + bank->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(bank->base)) { + return PTR_ERR(bank->base); + } + + if (bank->dbck_flag) { + bank->dbck = devm_clk_get(dev, "dbclk"); + if (IS_ERR(bank->dbck)) { + dev_err(dev, + "Could not get gpio dbck. Disable debounce\n"); + bank->dbck_flag = false; + } else { + clk_prepare(bank->dbck); + } + } + + platform_set_drvdata(pdev, bank); + + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); + + if (bank->is_mpuio) + omap_mpuio_init(bank); + + omap_gpio_mod_init(bank); + + ret = omap_gpio_chip_init(bank, irqc); + if (ret) { + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + if (bank->dbck_flag) + clk_unprepare(bank->dbck); + return ret; + } + + omap_gpio_show_rev(bank); + + bank->nb.notifier_call = gpio_omap_cpu_notifier; + cpu_pm_register_notifier(&bank->nb); + + pm_runtime_put(dev); + + return 0; +} + +static int omap_gpio_remove(struct platform_device *pdev) +{ + struct gpio_bank *bank = platform_get_drvdata(pdev); + + cpu_pm_unregister_notifier(&bank->nb); + list_del(&bank->node); + gpiochip_remove(&bank->chip); + pm_runtime_disable(&pdev->dev); + if (bank->dbck_flag) + clk_unprepare(bank->dbck); + + return 0; +} + +static int __maybe_unused omap_gpio_runtime_suspend(struct device *dev) +{ + struct gpio_bank *bank = dev_get_drvdata(dev); + unsigned long flags; + + raw_spin_lock_irqsave(&bank->lock, flags); + omap_gpio_idle(bank, true); + bank->is_suspended = true; + raw_spin_unlock_irqrestore(&bank->lock, flags); + + return 0; +} + +static int __maybe_unused omap_gpio_runtime_resume(struct device *dev) +{ + struct gpio_bank *bank = dev_get_drvdata(dev); + unsigned long flags; + + raw_spin_lock_irqsave(&bank->lock, flags); + omap_gpio_unidle(bank); + bank->is_suspended = false; + raw_spin_unlock_irqrestore(&bank->lock, flags); + + return 0; +} + +static const struct dev_pm_ops gpio_pm_ops = { + SET_RUNTIME_PM_OPS(omap_gpio_runtime_suspend, omap_gpio_runtime_resume, + NULL) +}; + static struct platform_driver omap_gpio_driver = { .probe = omap_gpio_probe, .remove = omap_gpio_remove, .driver = { .name = "omap_gpio", .pm = &gpio_pm_ops, - .of_match_table = of_match_ptr(omap_gpio_match), + .of_match_table = omap_gpio_match, }, }; diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 7e76830b3368..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, }, @@ -153,6 +154,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 +583,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 +1107,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 +1120,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); @@ -1137,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), }, @@ -1152,6 +1165,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), }, @@ -1167,6 +1181,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), }, diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index bcc6be4a5cb2..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, }; @@ -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; @@ -816,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, }; 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; 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; 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); 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); 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); 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); 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); 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); 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); 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); 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); diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 541fa6ac399d..30aef41e3b7e 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, }; @@ -86,28 +85,24 @@ 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) { 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) @@ -237,37 +232,31 @@ 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 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; struct device_node *np = dev->of_node; struct vf610_gpio_port *port; - struct resource *iores; struct gpio_chip *gc; + struct irq_chip *ic; 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; 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); @@ -275,11 +264,15 @@ 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) 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, @@ -288,20 +281,19 @@ 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) { - clk_disable_unprepare(port->clk_port); + 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)) { - clk_disable_unprepare(port->clk_port); return PTR_ERR(port->clk_gpio); } - platform_set_drvdata(pdev, port); - gc = &port->gc; gc->of_node = np; gc->parent = dev; @@ -316,7 +308,15 @@ static int vf610_gpio_probe(struct platform_device *pdev) gc->direction_output = vf610_gpio_direction_output; gc->set = vf610_gpio_set; - ret = gpiochip_add_data(gc, port); + 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 = devm_gpiochip_add_data(dev, gc, port); if (ret < 0) return ret; @@ -327,39 +327,23 @@ 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; } -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); - - 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); 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); 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); 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); 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); diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 30d0baf7ddae..c9fc9e232aaf 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 @@ fail_free_desc: * * 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) { @@ -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 @@ -517,6 +525,26 @@ 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) +{ + 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; + + return 0; +} + struct acpi_gpio_lookup { struct acpi_gpio_info info; int index; @@ -550,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; /* @@ -653,7 +682,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 @@ -696,7 +725,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; @@ -737,10 +766,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; } @@ -751,10 +778,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, @@ -816,6 +846,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; @@ -827,7 +858,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; @@ -992,16 +1023,19 @@ 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, + enum gpiod_flags *dflags) { struct gpio_chip *chip = achip->chip; struct gpio_desc *desc; u32 gpios[2]; int ret; - *lflags = 0; + *lflags = GPIO_LOOKUP_FLAGS_DEFAULT; *dflags = 0; *name = NULL; @@ -1037,7 +1071,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; + enum gpiod_flags dflags; struct gpio_desc *desc; const char *name; int ret; @@ -1158,11 +1193,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) { diff --git a/drivers/gpio/gpiolib-devprop.c b/drivers/gpio/gpiolib-devprop.c index dd517098ab95..53781b253986 100644 --- a/drivers/gpio/gpiolib-devprop.c +++ b/drivers/gpio/gpiolib-devprop.c @@ -10,6 +10,7 @@ #include <linux/slab.h> #include <linux/gpio/consumer.h> #include <linux/gpio/driver.h> +#include <linux/export.h> #include "gpiolib.h" @@ -56,3 +57,4 @@ void devprop_gpiochip_set_names(struct gpio_chip *chip, kfree(names); } +EXPORT_SYMBOL_GPL(devprop_gpiochip_set_names); diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 6a3ec575a404..aec7bd86ae7e 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; @@ -288,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; @@ -362,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 @@ -372,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; @@ -388,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); @@ -445,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 0495bf1d480a..e013d417a936 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1379,7 +1379,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, status = gpiochip_add_irqchip(chip, lock_key, request_key); if (status) - goto err_remove_chip; + goto err_free_gpiochip_mask; status = of_gpiochip_add(chip); if (status) @@ -1387,7 +1387,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, status = gpiochip_init_valid_mask(chip); if (status) - goto err_remove_chip; + goto err_remove_of_chip; for (i = 0; i < chip->ngpio; i++) { struct gpio_desc *desc = &gdev->descs[i]; @@ -1415,14 +1415,18 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, if (gpiolib_initialized) { status = gpiochip_setup_dev(gdev); if (status) - goto err_remove_chip; + goto err_remove_acpi_chip; } return 0; -err_remove_chip: +err_remove_acpi_chip: acpi_gpiochip_remove(chip); +err_remove_of_chip: gpiochip_free_hogs(chip); of_gpiochip_remove(chip); +err_remove_chip: + gpiochip_irqchip_remove(chip); +err_free_gpiochip_mask: gpiochip_free_valid_mask(chip); err_remove_irqchip_mask: gpiochip_irqchip_free_valid_mask(chip); @@ -2515,6 +2519,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 +2532,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); @@ -2565,8 +2570,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; } @@ -3911,8 +3928,7 @@ found: } 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; @@ -4068,8 +4084,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 @@ -4151,9 +4167,9 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, unsigned int idx, enum gpiod_flags flags) { + unsigned long lookupflags = GPIO_LOOKUP_FLAGS_DEFAULT; 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) : "?"; @@ -4238,8 +4254,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; @@ -4317,8 +4333,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) @@ -4338,9 +4354,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 */ @@ -4391,8 +4405,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, @@ -4445,8 +4459,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) { @@ -4616,7 +4628,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); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 078ab17b96bf..7a65dad43932 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -17,7 +17,6 @@ #include <linux/cdev.h> enum of_gpio_flags; -enum gpio_lookup_flags; struct acpi_device; /** @@ -75,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 @@ -83,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; @@ -95,7 +96,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 +105,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); } @@ -126,12 +127,14 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip); int acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *info); +int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags, + struct acpi_gpio_info *info); struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id, unsigned int idx, enum gpiod_flags *dflags, - 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); @@ -154,11 +157,17 @@ 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, unsigned int idx, enum gpiod_flags *dflags, - enum gpio_lookup_flags *lookupflags) + unsigned long *lookupflags) { return ERR_PTR(-ENOENT); } @@ -243,9 +252,6 @@ static inline int gpio_chip_hwgpio(const struct gpio_desc *desc) return desc - &desc->gdev->descs[0]; } -void devprop_gpiochip_set_names(struct gpio_chip *chip, - const struct fwnode_handle *fwnode); - /* With descriptor prefix */ #define gpiod_emerg(desc, fmt, ...) \ |