diff options
Diffstat (limited to 'drivers/gpio')
31 files changed, 581 insertions, 788 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 8023d03ec362..189f3b794804 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only # # GPIO infrastructure and drivers # @@ -61,16 +62,12 @@ config GPIO_SYSFS bool "/sys/class/gpio/... (sysfs interface)" depends on SYSFS help - Say Y here to add a sysfs interface for GPIOs. + Say Y here to add the legacy sysfs interface for GPIOs. - This is mostly useful to work around omissions in a system's - kernel support. Those are common in custom and semicustom - hardware assembled using standard kernels with a minimum of - custom patches. In those cases, userspace code may import - a given GPIO from the kernel, if no kernel driver requested it. - - Kernel drivers may also request that a particular GPIO be - exported to userspace; this can be useful when debugging. + This ABI is deprecated. If you want to use GPIO from userspace, + use the character device /dev/gpiochipN with the appropriate + ioctl() operations instead. The character device is always + available. config GPIO_GENERIC depends on HAS_IOMEM # Only for IOMEM drivers @@ -177,7 +174,7 @@ config GPIO_CLPS711X config GPIO_DAVINCI bool "TI Davinci/Keystone GPIO support" default y if ARCH_DAVINCI - depends on ARM && (ARCH_DAVINCI || ARCH_KEYSTONE) + depends on (ARM || ARM64) && (ARCH_DAVINCI || ARCH_KEYSTONE || ARCH_K3) help Say yes here to enable GPIO support for TI Davinci/Keystone SoCs. @@ -601,7 +598,6 @@ config GPIO_XGENE_SB config GPIO_XILINX tristate "Xilinx GPIO support" - depends on OF_GPIO help Say yes here to support the Xilinx FPGA GPIO device diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 6700eee860b7..9e400e34e300 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -17,154 +17,154 @@ obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o # directly supported by gpio-generic gpio-generic-$(CONFIG_GPIO_GENERIC) += gpio-mmio.o -obj-$(CONFIG_GPIO_104_DIO_48E) += gpio-104-dio-48e.o -obj-$(CONFIG_GPIO_104_IDIO_16) += gpio-104-idio-16.o -obj-$(CONFIG_GPIO_104_IDI_48) += gpio-104-idi-48.o -obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o -obj-$(CONFIG_GPIO_74XX_MMIO) += gpio-74xx-mmio.o -obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o -obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o -obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o -obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o -obj-$(CONFIG_GPIO_ALTERA_A10SR) += gpio-altera-a10sr.o -obj-$(CONFIG_GPIO_AMD_FCH) += gpio-amd-fch.o -obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o -obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o -obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o -obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o -obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o -obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o -obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o -obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o -obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o -obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o -obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o -obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o -obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o -obj-$(CONFIG_GPIO_CRYSTAL_COVE) += gpio-crystalcove.o -obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o -obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o -obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o -obj-$(CONFIG_GPIO_DLN2) += gpio-dln2.o -obj-$(CONFIG_GPIO_DWAPB) += gpio-dwapb.o -obj-$(CONFIG_GPIO_EIC_SPRD) += gpio-eic-sprd.o -obj-$(CONFIG_GPIO_EM) += gpio-em.o -obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o -obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o -obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o -obj-$(CONFIG_GPIO_FTGPIO010) += gpio-ftgpio010.o -obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o -obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o -obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o -obj-$(CONFIG_GPIO_GW_PLD) += gpio-gw-pld.o -obj-$(CONFIG_GPIO_HLWD) += gpio-hlwd.o -obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o -obj-$(CONFIG_GPIO_ICH) += gpio-ich.o -obj-$(CONFIG_GPIO_IOP) += gpio-iop.o -obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o -obj-$(CONFIG_GPIO_IT87) += gpio-it87.o -obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o -obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o -obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o -obj-$(CONFIG_GPIO_INTEL_MID) += gpio-intel-mid.o -obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o -obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o -obj-$(CONFIG_GPIO_LPC18XX) += gpio-lpc18xx.o -obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o -obj-$(CONFIG_GPIO_LP873X) += gpio-lp873x.o -obj-$(CONFIG_GPIO_LP87565) += gpio-lp87565.o -obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o -obj-$(CONFIG_GPIO_MADERA) += gpio-madera.o -obj-$(CONFIG_GPIO_MAX3191X) += gpio-max3191x.o -obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o -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 -obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o -obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o -obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o +obj-$(CONFIG_GPIO_104_DIO_48E) += gpio-104-dio-48e.o +obj-$(CONFIG_GPIO_104_IDI_48) += gpio-104-idi-48.o +obj-$(CONFIG_GPIO_104_IDIO_16) += gpio-104-idio-16.o +obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o +obj-$(CONFIG_GPIO_74XX_MMIO) += gpio-74xx-mmio.o +obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o +obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o +obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o +obj-$(CONFIG_GPIO_ALTERA_A10SR) += gpio-altera-a10sr.o +obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o +obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o +obj-$(CONFIG_GPIO_AMD_FCH) += gpio-amd-fch.o +obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o +obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o +obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o +obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o +obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o +obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o +obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o +obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o +obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o +obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o +obj-$(CONFIG_GPIO_SNPS_CREG) += gpio-creg-snps.o +obj-$(CONFIG_GPIO_CRYSTAL_COVE) += gpio-crystalcove.o +obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o +obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o +obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o +obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o +obj-$(CONFIG_GPIO_DLN2) += gpio-dln2.o +obj-$(CONFIG_GPIO_DWAPB) += gpio-dwapb.o +obj-$(CONFIG_GPIO_EIC_SPRD) += gpio-eic-sprd.o +obj-$(CONFIG_GPIO_EM) += gpio-em.o +obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o +obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o +obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o +obj-$(CONFIG_GPIO_FTGPIO010) += gpio-ftgpio010.o +obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o +obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o +obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o +obj-$(CONFIG_GPIO_GW_PLD) += gpio-gw-pld.o +obj-$(CONFIG_GPIO_HLWD) += gpio-hlwd.o +obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o +obj-$(CONFIG_GPIO_ICH) += gpio-ich.o +obj-$(CONFIG_GPIO_INTEL_MID) += gpio-intel-mid.o +obj-$(CONFIG_GPIO_IOP) += gpio-iop.o +obj-$(CONFIG_GPIO_IT87) += gpio-it87.o +obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o +obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o +obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o +obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o +obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o +obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o +obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o +obj-$(CONFIG_GPIO_LP873X) += gpio-lp873x.o +obj-$(CONFIG_GPIO_LP87565) += gpio-lp87565.o +obj-$(CONFIG_GPIO_LPC18XX) += gpio-lpc18xx.o +obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o +obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o +obj-$(CONFIG_GPIO_MADERA) += gpio-madera.o +obj-$(CONFIG_GPIO_MAX3191X) += gpio-max3191x.o +obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o +obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o +obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.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_MC33880) += gpio-mc33880.o +obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o +obj-$(CONFIG_GPIO_MENZ127) += gpio-menz127.o +obj-$(CONFIG_GPIO_MERRIFIELD) += gpio-merrifield.o +obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o +obj-$(CONFIG_GPIO_MLXBF) += gpio-mlxbf.o +obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o +obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o +obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o +obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o +obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o obj-$(CONFIG_GPIO_MT7621) += gpio-mt7621.o -obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o -obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o -obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o -obj-$(CONFIG_GPIO_OCTEON) += gpio-octeon.o -obj-$(CONFIG_GPIO_OMAP) += gpio-omap.o -obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o -obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o -obj-$(CONFIG_GPIO_PCH) += gpio-pch.o -obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio-pci-idio-16.o -obj-$(CONFIG_GPIO_PCIE_IDIO_24) += gpio-pcie-idio-24.o -obj-$(CONFIG_GPIO_PISOSR) += gpio-pisosr.o -obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o +obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o +obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o +obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o +obj-$(CONFIG_GPIO_OCTEON) += gpio-octeon.o +obj-$(CONFIG_GPIO_OMAP) += gpio-omap.o +obj-$(CONFIG_GPIO_PALMAS) += gpio-palmas.o +obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o +obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o +obj-$(CONFIG_GPIO_PCH) += gpio-pch.o +obj-$(CONFIG_GPIO_PCIE_IDIO_24) += gpio-pcie-idio-24.o +obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio-pci-idio-16.o +obj-$(CONFIG_GPIO_PISOSR) += gpio-pisosr.o +obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio-pmic-eic-sprd.o -obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o -obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o -obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o -obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o -obj-$(CONFIG_GPIO_REG) += gpio-reg.o -obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o +obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o +obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o +obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o +obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o +obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o +obj-$(CONFIG_GPIO_REG) += gpio-reg.o +obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) += gpio-sama5d2-piobu.o -obj-$(CONFIG_GPIO_SCH) += gpio-sch.o -obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o -obj-$(CONFIG_GPIO_SNPS_CREG) += gpio-creg-snps.o -obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o -obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o -obj-$(CONFIG_GPIO_SPRD) += gpio-sprd.o -obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o -obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o -obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o -obj-$(CONFIG_GPIO_SYSCON) += gpio-syscon.o -obj-$(CONFIG_GPIO_TB10X) += gpio-tb10x.o -obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o -obj-$(CONFIG_GPIO_TEGRA) += gpio-tegra.o -obj-$(CONFIG_GPIO_TEGRA186) += gpio-tegra186.o -obj-$(CONFIG_GPIO_THUNDERX) += gpio-thunderx.o -obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o -obj-$(CONFIG_GPIO_PALMAS) += gpio-palmas.o -obj-$(CONFIG_GPIO_SIOX) += gpio-siox.o -obj-$(CONFIG_GPIO_TPIC2810) += gpio-tpic2810.o -obj-$(CONFIG_GPIO_TPS65086) += gpio-tps65086.o -obj-$(CONFIG_GPIO_TPS65218) += gpio-tps65218.o -obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o -obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o -obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o -obj-$(CONFIG_GPIO_TPS68470) += gpio-tps68470.o -obj-$(CONFIG_GPIO_TQMX86) += gpio-tqmx86.o -obj-$(CONFIG_GPIO_TS4800) += gpio-ts4800.o -obj-$(CONFIG_GPIO_TS4900) += gpio-ts4900.o -obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o -obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o -obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o -obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o -obj-$(CONFIG_GPIO_UNIPHIER) += gpio-uniphier.o -obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o -obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o -obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o -obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o -obj-$(CONFIG_GPIO_WHISKEY_COVE) += gpio-wcove.o -obj-$(CONFIG_GPIO_WINBOND) += gpio-winbond.o -obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o -obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o -obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o -obj-$(CONFIG_GPIO_WS16C48) += gpio-ws16c48.o -obj-$(CONFIG_GPIO_XGENE) += gpio-xgene.o -obj-$(CONFIG_GPIO_XGENE_SB) += gpio-xgene-sb.o -obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o -obj-$(CONFIG_GPIO_XLP) += gpio-xlp.o -obj-$(CONFIG_GPIO_XRA1403) += gpio-xra1403.o -obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o -obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o -obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o -obj-$(CONFIG_GPIO_ZX) += gpio-zx.o -obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o +obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o +obj-$(CONFIG_GPIO_SCH) += gpio-sch.o +obj-$(CONFIG_GPIO_SIOX) += gpio-siox.o +obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o +obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o +obj-$(CONFIG_GPIO_SPRD) += gpio-sprd.o +obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o +obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o +obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o +obj-$(CONFIG_GPIO_SYSCON) += gpio-syscon.o +obj-$(CONFIG_GPIO_TB10X) += gpio-tb10x.o +obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o +obj-$(CONFIG_GPIO_TEGRA186) += gpio-tegra186.o +obj-$(CONFIG_GPIO_TEGRA) += gpio-tegra.o +obj-$(CONFIG_GPIO_THUNDERX) += gpio-thunderx.o +obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o +obj-$(CONFIG_GPIO_TPIC2810) += gpio-tpic2810.o +obj-$(CONFIG_GPIO_TPS65086) += gpio-tps65086.o +obj-$(CONFIG_GPIO_TPS65218) += gpio-tps65218.o +obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o +obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o +obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o +obj-$(CONFIG_GPIO_TPS68470) += gpio-tps68470.o +obj-$(CONFIG_GPIO_TQMX86) += gpio-tqmx86.o +obj-$(CONFIG_GPIO_TS4800) += gpio-ts4800.o +obj-$(CONFIG_GPIO_TS4900) += gpio-ts4900.o +obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o +obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o +obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o +obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o +obj-$(CONFIG_GPIO_UNIPHIER) += gpio-uniphier.o +obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o +obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o +obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o +obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o +obj-$(CONFIG_GPIO_WHISKEY_COVE) += gpio-wcove.o +obj-$(CONFIG_GPIO_WINBOND) += gpio-winbond.o +obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o +obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o +obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o +obj-$(CONFIG_GPIO_WS16C48) += gpio-ws16c48.o +obj-$(CONFIG_GPIO_XGENE) += gpio-xgene.o +obj-$(CONFIG_GPIO_XGENE_SB) += gpio-xgene-sb.o +obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o +obj-$(CONFIG_GPIO_XLP) += gpio-xlp.o +obj-$(CONFIG_GPIO_XRA1403) += gpio-xra1403.o +obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o +obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o +obj-$(CONFIG_GPIO_ZX) += gpio-zx.o +obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o diff --git a/drivers/gpio/TODO b/drivers/gpio/TODO index 19d27c904916..9c048f10c9ad 100644 --- a/drivers/gpio/TODO +++ b/drivers/gpio/TODO @@ -90,6 +90,46 @@ GPIOLIB irqchip The GPIOLIB irqchip is a helper irqchip for "simple cases" that should try to cover any generic kind of irqchip cascaded from a GPIO. +- Convert all the GPIOLIB_IRQCHIP users to pass an irqchip template, + parent and flags before calling [devm_]gpiochip_add[_data](). + Currently we set up the irqchip after setting up the gpiochip + using gpiochip_irqchip_add() and gpiochip_set_[chained|nested]_irqchip(). + This is too complex, so convert all users over to just set up + the irqchip before registering the gpio_chip, typical example: + + /* Typical state container with dynamic irqchip */ + struct my_gpio { + struct gpio_chip gc; + struct irq_chip irq; + }; + + int irq; /* from platform etc */ + struct my_gpio *g; + struct gpio_irq_chip *girq + + /* Set up the irqchip dynamically */ + g->irq.name = "my_gpio_irq"; + g->irq.irq_ack = my_gpio_ack_irq; + g->irq.irq_mask = my_gpio_mask_irq; + g->irq.irq_unmask = my_gpio_unmask_irq; + g->irq.irq_set_type = my_gpio_set_irq_type; + + /* Get a pointer to the gpio_irq_chip */ + girq = &g->gc.irq; + girq->chip = &g->irq; + girq->parent_handler = ftgpio_gpio_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + girq->parents[0] = irq; + + When this is done, we will delete the old APIs for instatiating + GPIOLIB_IRQCHIP and simplify the code. + - Look over and identify any remaining easily converted drivers and dry-code conversions to gpiolib irqchip for maintainers to test diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c index 748fdd4e9a53..a266d8796ee5 100644 --- a/drivers/gpio/gpio-altera.c +++ b/drivers/gpio/gpio-altera.c @@ -1,19 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2013 Altera Corporation * Based on gpio-mpc8xxx.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <linux/io.h> @@ -42,6 +30,7 @@ struct altera_gpio_chip { raw_spinlock_t gpio_lock; int interrupt_trigger; int mapped_irq; + struct irq_chip irq_chip; }; static void altera_gpio_irq_unmask(struct irq_data *d) @@ -113,15 +102,6 @@ static unsigned int altera_gpio_irq_startup(struct irq_data *d) return 0; } -static struct irq_chip altera_irq_chip = { - .name = "altera-gpio", - .irq_mask = altera_gpio_irq_mask, - .irq_unmask = altera_gpio_irq_unmask, - .irq_set_type = altera_gpio_irq_set_type, - .irq_startup = altera_gpio_irq_startup, - .irq_shutdown = altera_gpio_irq_mask, -}; - static int altera_gpio_get(struct gpio_chip *gc, unsigned offset) { struct of_mm_gpio_chip *mm_gc; @@ -306,8 +286,15 @@ static int altera_gpio_probe(struct platform_device *pdev) } altera_gc->interrupt_trigger = reg; - ret = gpiochip_irqchip_add(&altera_gc->mmchip.gc, &altera_irq_chip, 0, - handle_bad_irq, IRQ_TYPE_NONE); + altera_gc->irq_chip.name = "altera-gpio"; + altera_gc->irq_chip.irq_mask = altera_gpio_irq_mask; + altera_gc->irq_chip.irq_unmask = altera_gpio_irq_unmask; + altera_gc->irq_chip.irq_set_type = altera_gpio_irq_set_type; + altera_gc->irq_chip.irq_startup = altera_gpio_irq_startup; + altera_gc->irq_chip.irq_shutdown = altera_gpio_irq_mask; + + ret = gpiochip_irqchip_add(&altera_gc->mmchip.gc, &altera_gc->irq_chip, + 0, handle_bad_irq, IRQ_TYPE_NONE); if (ret) { dev_err(&pdev->dev, "could not add irqchip\n"); @@ -315,7 +302,7 @@ static int altera_gpio_probe(struct platform_device *pdev) } gpiochip_set_chained_irqchip(&altera_gc->mmchip.gc, - &altera_irq_chip, + &altera_gc->irq_chip, altera_gc->mapped_irq, altera_gc->interrupt_trigger == IRQ_TYPE_LEVEL_HIGH ? altera_gpio_irq_leveL_high_handler : diff --git a/drivers/gpio/gpio-amd-fch.c b/drivers/gpio/gpio-amd-fch.c index 38c3f4a3d4aa..f80b690f374c 100644 --- a/drivers/gpio/gpio-amd-fch.c +++ b/drivers/gpio/gpio-amd-fch.c @@ -32,7 +32,6 @@ static struct resource amd_fch_gpio_iores = "amd-fch-gpio-iomem"); struct amd_fch_gpio_priv { - struct platform_device *pdev; struct gpio_chip gc; void __iomem *base; struct amd_fch_gpio_pdata *pdata; @@ -153,7 +152,6 @@ static int amd_fch_gpio_probe(struct platform_device *pdev) return -ENOMEM; priv->pdata = pdata; - priv->pdev = pdev; priv->gc.owner = THIS_MODULE; priv->gc.parent = &pdev->dev; diff --git a/drivers/gpio/gpio-amdpt.c b/drivers/gpio/gpio-amdpt.c index 1ffd7c2d1285..2ec9d1fb7626 100644 --- a/drivers/gpio/gpio-amdpt.c +++ b/drivers/gpio/gpio-amdpt.c @@ -91,7 +91,7 @@ static int pt_gpio_probe(struct platform_device *pdev) 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"); + dev_err(dev, "Failed to map MMIO resource for PT GPIO.\n"); return PTR_ERR(pt_gpio->reg_base); } @@ -101,7 +101,7 @@ static int pt_gpio_probe(struct platform_device *pdev) pt_gpio->reg_base + PT_DIRECTION_REG, NULL, BGPIOF_READ_OUTPUT_REG_SET); if (ret) { - dev_err(&pdev->dev, "bgpio_init failed\n"); + dev_err(dev, "bgpio_init failed\n"); return ret; } @@ -110,11 +110,11 @@ static int pt_gpio_probe(struct platform_device *pdev) pt_gpio->gc.free = pt_gpio_free; pt_gpio->gc.ngpio = PT_TOTAL_GPIO; #if defined(CONFIG_OF_GPIO) - pt_gpio->gc.of_node = pdev->dev.of_node; + pt_gpio->gc.of_node = dev->of_node; #endif ret = gpiochip_add_data(&pt_gpio->gc, pt_gpio); if (ret) { - dev_err(&pdev->dev, "Failed to register GPIO lib\n"); + dev_err(dev, "Failed to register GPIO lib\n"); return ret; } @@ -124,7 +124,7 @@ static int pt_gpio_probe(struct platform_device *pdev) writel(0, pt_gpio->reg_base + PT_SYNC_REG); writel(0, pt_gpio->reg_base + PT_CLOCKRATE_REG); - dev_dbg(&pdev->dev, "PT GPIO driver loaded\n"); + dev_dbg(dev, "PT GPIO driver loaded\n"); return ret; } diff --git a/drivers/gpio/gpio-bt8xx.c b/drivers/gpio/gpio-bt8xx.c index b8ec75cbd4b5..a6f30ad6750f 100644 --- a/drivers/gpio/gpio-bt8xx.c +++ b/drivers/gpio/gpio-bt8xx.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* bt8xx GPIO abuser @@ -28,19 +29,6 @@ Copyright (C) 2005, 2006 Michael H. Schimek Sponsored by OPQ Systems AB - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/module.h> diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 188b8e5c8e67..a1c4a0825a36 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -301,7 +301,7 @@ static int davinci_gpio_probe(struct platform_device *pdev) static void gpio_irq_disable(struct irq_data *d) { struct davinci_gpio_regs __iomem *g = irq2regs(d); - u32 mask = (u32) irq_data_get_irq_handler_data(d); + uintptr_t mask = (uintptr_t)irq_data_get_irq_handler_data(d); writel_relaxed(mask, &g->clr_falling); writel_relaxed(mask, &g->clr_rising); @@ -310,7 +310,7 @@ static void gpio_irq_disable(struct irq_data *d) static void gpio_irq_enable(struct irq_data *d) { struct davinci_gpio_regs __iomem *g = irq2regs(d); - u32 mask = (u32) irq_data_get_irq_handler_data(d); + uintptr_t mask = (uintptr_t)irq_data_get_irq_handler_data(d); unsigned status = irqd_get_trigger_type(d); status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING; @@ -451,7 +451,7 @@ davinci_gpio_irq_map(struct irq_domain *d, unsigned int irq, "davinci_gpio"); irq_set_irq_type(irq, IRQ_TYPE_NONE); irq_set_chip_data(irq, (__force void *)g); - irq_set_handler_data(irq, (void *)__gpio_mask(hw)); + irq_set_handler_data(irq, (void *)(uintptr_t)__gpio_mask(hw)); return 0; } @@ -636,6 +636,7 @@ done: static const struct of_device_id davinci_gpio_ids[] = { { .compatible = "ti,keystone-gpio", keystone_gpio_get_irq_chip}, + { .compatible = "ti,am654-gpio", keystone_gpio_get_irq_chip}, { .compatible = "ti,dm6441-gpio", davinci_gpio_get_irq_chip}, { /* sentinel */ }, }; diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c index 77092268ee95..7b9ac4a12c20 100644 --- a/drivers/gpio/gpio-eic-sprd.c +++ b/drivers/gpio/gpio-eic-sprd.c @@ -568,7 +568,6 @@ static int sprd_eic_probe(struct platform_device *pdev) const struct sprd_eic_variant_data *pdata; struct gpio_irq_chip *irq; struct sprd_eic *sprd_eic; - struct resource *res; int ret, i; pdata = of_device_get_match_data(&pdev->dev); @@ -597,13 +596,9 @@ static int sprd_eic_probe(struct platform_device *pdev) * have one bank EIC, thus base[1] and base[2] can be * optional. */ - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - if (!res) - continue; - - sprd_eic->base[i] = devm_ioremap_resource(&pdev->dev, res); + sprd_eic->base[i] = devm_platform_ioremap_resource(pdev, i); if (IS_ERR(sprd_eic->base[i])) - return PTR_ERR(sprd_eic->base[i]); + continue; } sprd_eic->chip.label = sprd_eic_label_name[sprd_eic->type]; diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c index 71728d6e0bca..a90870a60c15 100644 --- a/drivers/gpio/gpio-ep93xx.c +++ b/drivers/gpio/gpio-ep93xx.c @@ -393,16 +393,13 @@ static int ep93xx_gpio_add_bank(struct gpio_chip *gc, struct device *dev, static int ep93xx_gpio_probe(struct platform_device *pdev) { struct ep93xx_gpio *epg; - struct resource *res; int i; - struct device *dev = &pdev->dev; - epg = devm_kzalloc(dev, sizeof(*epg), GFP_KERNEL); + epg = devm_kzalloc(&pdev->dev, sizeof(*epg), GFP_KERNEL); if (!epg) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - epg->base = devm_ioremap_resource(dev, res); + epg->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(epg->base)) return PTR_ERR(epg->base); diff --git a/drivers/gpio/gpio-ftgpio010.c b/drivers/gpio/gpio-ftgpio010.c index 8ff8ce2970d9..250e71f3e688 100644 --- a/drivers/gpio/gpio-ftgpio010.c +++ b/drivers/gpio/gpio-ftgpio010.c @@ -226,6 +226,7 @@ static int ftgpio_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct ftgpio_gpio *g; + struct gpio_irq_chip *girq; int irq; int ret; @@ -277,6 +278,24 @@ static int ftgpio_gpio_probe(struct platform_device *pdev) if (!IS_ERR(g->clk)) g->gc.set_config = ftgpio_gpio_set_config; + g->irq.name = "FTGPIO010"; + g->irq.irq_ack = ftgpio_gpio_ack_irq; + g->irq.irq_mask = ftgpio_gpio_mask_irq; + g->irq.irq_unmask = ftgpio_gpio_unmask_irq; + g->irq.irq_set_type = ftgpio_gpio_set_irq_type; + + girq = &g->gc.irq; + girq->chip = &g->irq; + girq->parent_handler = ftgpio_gpio_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + girq->parents[0] = irq; + ret = devm_gpiochip_add_data(dev, &g->gc, g); if (ret) goto dis_clk; @@ -289,22 +308,6 @@ static int ftgpio_gpio_probe(struct platform_device *pdev) /* Clear any use of debounce */ writel(0x0, g->base + GPIO_DEBOUNCE_EN); - g->irq.name = "FTGPIO010"; - g->irq.irq_ack = ftgpio_gpio_ack_irq; - g->irq.irq_mask = ftgpio_gpio_mask_irq; - g->irq.irq_unmask = ftgpio_gpio_unmask_irq; - g->irq.irq_set_type = ftgpio_gpio_set_irq_type; - - ret = gpiochip_irqchip_add(&g->gc, &g->irq, - 0, handle_bad_irq, - IRQ_TYPE_NONE); - if (ret) { - dev_info(dev, "could not add irqchip\n"); - goto dis_clk; - } - gpiochip_set_chained_irqchip(&g->gc, &g->irq, - irq, ftgpio_gpio_irq_handler); - platform_set_drvdata(pdev, g); dev_info(dev, "FTGPIO010 @%p registered\n", g->base); diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c index 45b8d6a02b87..8f8069e4e2f9 100644 --- a/drivers/gpio/gpio-grgpio.c +++ b/drivers/gpio/gpio-grgpio.c @@ -333,7 +333,6 @@ static int grgpio_probe(struct platform_device *ofdev) void __iomem *regs; struct gpio_chip *gc; struct grgpio_priv *priv; - struct resource *res; int err; u32 prop; s32 *irqmap; @@ -344,8 +343,7 @@ static int grgpio_probe(struct platform_device *ofdev) if (!priv) return -ENOMEM; - res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); - regs = devm_ioremap_resource(&ofdev->dev, res); + regs = devm_platform_ioremap_resource(ofdev, 0); if (IS_ERR(regs)) return PTR_ERR(regs); diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c index 4b1cf7ea858d..670c2a85a35b 100644 --- a/drivers/gpio/gpio-ixp4xx.c +++ b/drivers/gpio/gpio-ixp4xx.c @@ -205,20 +205,20 @@ static int ixp4xx_gpio_irq_domain_translate(struct irq_domain *domain, unsigned long *hwirq, unsigned int *type) { + int ret; /* We support standard DT translation */ if (is_of_node(fwspec->fwnode) && fwspec->param_count == 2) { - *hwirq = fwspec->param[0]; - *type = fwspec->param[1]; - return 0; + return irq_domain_translate_twocell(domain, fwspec, + hwirq, type); } /* This goes away when we transition to DT */ if (is_fwnode_irqchip(fwspec->fwnode)) { - if (fwspec->param_count != 2) - return -EINVAL; - *hwirq = fwspec->param[0]; - *type = fwspec->param[1]; + ret = irq_domain_translate_twocell(domain, fwspec, + hwirq, type); + if (ret) + return ret; WARN_ON(*type == IRQ_TYPE_NONE); return 0; } diff --git a/drivers/gpio/gpio-janz-ttl.c b/drivers/gpio/gpio-janz-ttl.c index b97a91166497..91f91f66d512 100644 --- a/drivers/gpio/gpio-janz-ttl.c +++ b/drivers/gpio/gpio-janz-ttl.c @@ -144,18 +144,17 @@ static void ttl_setup_device(struct ttl_module *mod) static int ttl_probe(struct platform_device *pdev) { struct janz_platform_data *pdata; - struct device *dev = &pdev->dev; struct ttl_module *mod; struct gpio_chip *gpio; int ret; pdata = dev_get_platdata(&pdev->dev); if (!pdata) { - dev_err(dev, "no platform data\n"); + dev_err(&pdev->dev, "no platform data\n"); return -ENXIO; } - mod = devm_kzalloc(dev, sizeof(*mod), GFP_KERNEL); + mod = devm_kzalloc(&pdev->dev, sizeof(*mod), GFP_KERNEL); if (!mod) return -ENOMEM; @@ -181,9 +180,9 @@ static int ttl_probe(struct platform_device *pdev) gpio->base = -1; gpio->ngpio = 20; - ret = devm_gpiochip_add_data(dev, gpio, NULL); + ret = devm_gpiochip_add_data(&pdev->dev, gpio, NULL); if (ret) { - dev_err(dev, "unable to add GPIO chip\n"); + dev_err(&pdev->dev, "unable to add GPIO chip\n"); return ret; } diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 059094ac44cb..869d47f89599 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -38,6 +38,7 @@ #include <linux/err.h> #include <linux/gpio/driver.h> #include <linux/gpio/consumer.h> +#include <linux/gpio/machine.h> #include <linux/init.h> #include <linux/io.h> #include <linux/irq.h> @@ -618,18 +619,14 @@ static int mvebu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) ret = -EBUSY; } else { desc = gpiochip_request_own_desc(&mvchip->chip, - pwm->hwpwm, "mvebu-pwm", 0); + pwm->hwpwm, "mvebu-pwm", + GPIO_ACTIVE_HIGH, + GPIOD_OUT_LOW); if (IS_ERR(desc)) { ret = PTR_ERR(desc); goto out; } - ret = gpiod_direction_output(desc, 0); - if (ret) { - gpiochip_free_own_desc(desc); - goto out; - } - mvpwm->gpiod = desc; } out: diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 16289bafa001..d3ef37e61d38 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -47,8 +47,9 @@ struct gpio_regs { }; struct gpio_bank { - struct list_head node; void __iomem *base; + const struct omap_gpio_reg_offs *regs; + int irq; u32 non_wakeup_gpios; u32 enabled_non_wakeup_gpios; @@ -75,11 +76,7 @@ struct gpio_bank { int context_loss_count; void (*set_dataout)(struct gpio_bank *bank, unsigned gpio, int enable); - void (*set_dataout_multiple)(struct gpio_bank *bank, - unsigned long *mask, unsigned long *bits); int (*get_context_loss_count)(struct device *dev); - - struct omap_gpio_reg_offs *regs; }; #define GPIO_MOD_CTRL_BIT BIT(0) @@ -95,20 +92,25 @@ static inline struct gpio_bank *omap_irq_data_get_bank(struct irq_data *d) return gpiochip_get_data(chip); } -static void omap_set_gpio_direction(struct gpio_bank *bank, int gpio, - int is_input) +static inline u32 omap_gpio_rmw(void __iomem *reg, u32 mask, bool set) { - void __iomem *reg = bank->base; - u32 l; + u32 val = readl_relaxed(reg); - reg += bank->regs->direction; - l = readl_relaxed(reg); - if (is_input) - l |= BIT(gpio); + if (set) + val |= mask; else - l &= ~(BIT(gpio)); - writel_relaxed(l, reg); - bank->context.oe = l; + val &= ~mask; + + writel_relaxed(val, reg); + + return val; +} + +static void omap_set_gpio_direction(struct gpio_bank *bank, int gpio, + int is_input) +{ + bank->context.oe = omap_gpio_rmw(bank->base + bank->regs->direction, + BIT(gpio), is_input); } @@ -134,88 +136,8 @@ static void omap_set_gpio_dataout_reg(struct gpio_bank *bank, unsigned offset, static void omap_set_gpio_dataout_mask(struct gpio_bank *bank, unsigned offset, int enable) { - void __iomem *reg = bank->base + bank->regs->dataout; - u32 gpio_bit = BIT(offset); - u32 l; - - l = readl_relaxed(reg); - if (enable) - l |= gpio_bit; - else - l &= ~gpio_bit; - writel_relaxed(l, reg); - bank->context.dataout = l; -} - -static int omap_get_gpio_datain(struct gpio_bank *bank, int offset) -{ - void __iomem *reg = bank->base + bank->regs->datain; - - return (readl_relaxed(reg) & (BIT(offset))) != 0; -} - -static int omap_get_gpio_dataout(struct gpio_bank *bank, int offset) -{ - void __iomem *reg = bank->base + bank->regs->dataout; - - return (readl_relaxed(reg) & (BIT(offset))) != 0; -} - -/* set multiple data out values using dedicate set/clear register */ -static void omap_set_gpio_dataout_reg_multiple(struct gpio_bank *bank, - unsigned long *mask, - unsigned long *bits) -{ - void __iomem *reg = bank->base; - u32 l; - - l = *bits & *mask; - writel_relaxed(l, reg + bank->regs->set_dataout); - bank->context.dataout |= l; - - l = ~*bits & *mask; - writel_relaxed(l, reg + bank->regs->clr_dataout); - bank->context.dataout &= ~l; -} - -/* set multiple data out values using mask register */ -static void omap_set_gpio_dataout_mask_multiple(struct gpio_bank *bank, - unsigned long *mask, - unsigned long *bits) -{ - void __iomem *reg = bank->base + bank->regs->dataout; - u32 l = (readl_relaxed(reg) & ~*mask) | (*bits & *mask); - - writel_relaxed(l, reg); - bank->context.dataout = l; -} - -static unsigned long omap_get_gpio_datain_multiple(struct gpio_bank *bank, - unsigned long *mask) -{ - void __iomem *reg = bank->base + bank->regs->datain; - - return readl_relaxed(reg) & *mask; -} - -static unsigned long omap_get_gpio_dataout_multiple(struct gpio_bank *bank, - unsigned long *mask) -{ - void __iomem *reg = bank->base + bank->regs->dataout; - - return readl_relaxed(reg) & *mask; -} - -static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set) -{ - int l = readl_relaxed(base + reg); - - if (set) - l |= mask; - else - l &= ~mask; - - writel_relaxed(l, base + reg); + bank->context.dataout = omap_gpio_rmw(bank->base + bank->regs->dataout, + BIT(offset), enable); } static inline void omap_gpio_dbck_enable(struct gpio_bank *bank) @@ -259,7 +181,6 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank) static int omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset, unsigned debounce) { - void __iomem *reg; u32 val; u32 l; bool enable = !!debounce; @@ -276,19 +197,11 @@ static int omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset, l = BIT(offset); clk_enable(bank->dbck); - reg = bank->base + bank->regs->debounce; - writel_relaxed(debounce, reg); + writel_relaxed(debounce, bank->base + bank->regs->debounce); - reg = bank->base + bank->regs->debounce_en; - val = readl_relaxed(reg); - - if (enable) - val |= l; - else - val &= ~l; + val = omap_gpio_rmw(bank->base + bank->regs->debounce_en, l, enable); bank->dbck_enable_mask = val; - writel_relaxed(val, reg); clk_disable(bank->dbck); /* * Enable debounce clock per module. @@ -363,9 +276,9 @@ static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio, void __iomem *base = bank->base; u32 gpio_bit = BIT(gpio); - omap_gpio_rmw(base, bank->regs->leveldetect0, gpio_bit, + omap_gpio_rmw(base + bank->regs->leveldetect0, gpio_bit, trigger & IRQ_TYPE_LEVEL_LOW); - omap_gpio_rmw(base, bank->regs->leveldetect1, gpio_bit, + omap_gpio_rmw(base + bank->regs->leveldetect1, gpio_bit, trigger & IRQ_TYPE_LEVEL_HIGH); /* @@ -373,9 +286,9 @@ static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio, * 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, + omap_gpio_rmw(base + bank->regs->risingdetect, gpio_bit, trigger & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)); - omap_gpio_rmw(base, bank->regs->fallingdetect, gpio_bit, + omap_gpio_rmw(base + bank->regs->fallingdetect, gpio_bit, trigger & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)); bank->context.leveldetect0 = @@ -387,11 +300,8 @@ static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio, bank->context.fallingdetect = readl_relaxed(bank->base + bank->regs->fallingdetect); - if (likely(!(bank->non_wakeup_gpios & gpio_bit))) { - omap_gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0); - bank->context.wake_en = - readl_relaxed(bank->base + bank->regs->wkup_en); - } + bank->level_mask = bank->context.leveldetect0 | + bank->context.leveldetect1; /* This part needs to be executed always for OMAP{34xx, 44xx} */ if (!bank->regs->irqctrl && !omap_gpio_is_off_wakeup_capable(bank, gpio)) { @@ -406,44 +316,25 @@ static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio, else bank->enabled_non_wakeup_gpios &= ~gpio_bit; } - - bank->level_mask = - readl_relaxed(bank->base + bank->regs->leveldetect0) | - readl_relaxed(bank->base + bank->regs->leveldetect1); } -#ifdef CONFIG_ARCH_OMAP1 /* * This only applies to chips that can't do both rising and falling edge * detection at once. For all other chips, this function is a noop. */ static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) { - void __iomem *reg = bank->base; - u32 l = 0; - - if (!bank->regs->irqctrl) - return; + if (IS_ENABLED(CONFIG_ARCH_OMAP1) && bank->regs->irqctrl) { + void __iomem *reg = bank->base + bank->regs->irqctrl; - reg += bank->regs->irqctrl; - - l = readl_relaxed(reg); - if ((l >> gpio) & 1) - l &= ~(BIT(gpio)); - else - l |= BIT(gpio); - - writel_relaxed(l, reg); + writel_relaxed(readl_relaxed(reg) ^ BIT(gpio), reg); + } } -#else -static void omap_toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) {} -#endif static int omap_set_gpio_triggering(struct gpio_bank *bank, int gpio, unsigned trigger) { void __iomem *reg = bank->base; - void __iomem *base = bank->base; u32 l = 0; if (bank->regs->leveldetect0 && bank->regs->wkup_en) { @@ -475,11 +366,6 @@ static int omap_set_gpio_triggering(struct gpio_bank *bank, int gpio, l |= 2 << (gpio << 1); if (trigger & IRQ_TYPE_EDGE_FALLING) l |= BIT(gpio << 1); - - /* Enable wake-up during idle for dynamic tick */ - omap_gpio_rmw(base, bank->regs->wkup_en, BIT(gpio), trigger); - bank->context.wake_en = - readl_relaxed(bank->base + bank->regs->wkup_en); writel_relaxed(l, reg); } return 0; @@ -508,17 +394,6 @@ static void omap_enable_gpio_module(struct gpio_bank *bank, unsigned offset) static void omap_disable_gpio_module(struct gpio_bank *bank, unsigned offset) { - void __iomem *base = bank->base; - - if (bank->regs->wkup_en && - !LINE_USED(bank->mod_usage, offset) && - !LINE_USED(bank->irq_usage, offset)) { - /* Disable wake-up during idle for dynamic tick */ - omap_gpio_rmw(base, bank->regs->wkup_en, BIT(offset), 0); - bank->context.wake_en = - readl_relaxed(bank->base + bank->regs->wkup_en); - } - if (bank->regs->ctrl && !BANK_USED(bank)) { void __iomem *reg = bank->base + bank->regs->ctrl; u32 ctrl; @@ -629,57 +504,39 @@ static u32 omap_get_gpio_irqbank_mask(struct gpio_bank *bank) return l; } -static void omap_enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) +static inline void omap_set_gpio_irqenable(struct gpio_bank *bank, + unsigned offset, int enable) { void __iomem *reg = bank->base; - u32 l; + u32 gpio_mask = BIT(offset); - if (bank->regs->set_irqenable) { - reg += bank->regs->set_irqenable; - l = gpio_mask; - bank->context.irqenable1 |= gpio_mask; + if (bank->regs->set_irqenable && bank->regs->clr_irqenable) { + if (enable) { + reg += bank->regs->set_irqenable; + bank->context.irqenable1 |= gpio_mask; + } else { + reg += bank->regs->clr_irqenable; + bank->context.irqenable1 &= ~gpio_mask; + } + writel_relaxed(gpio_mask, reg); } else { - reg += bank->regs->irqenable; - l = readl_relaxed(reg); - if (bank->regs->irqenable_inv) - l &= ~gpio_mask; - else - l |= gpio_mask; - bank->context.irqenable1 = l; + bank->context.irqenable1 = + omap_gpio_rmw(reg + bank->regs->irqenable, gpio_mask, + enable ^ bank->regs->irqenable_inv); } - writel_relaxed(l, reg); -} - -static void omap_disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) -{ - void __iomem *reg = bank->base; - u32 l; - - if (bank->regs->clr_irqenable) { - reg += bank->regs->clr_irqenable; - l = gpio_mask; - bank->context.irqenable1 &= ~gpio_mask; - } else { - reg += bank->regs->irqenable; - l = readl_relaxed(reg); - if (bank->regs->irqenable_inv) - l |= gpio_mask; - else - l &= ~gpio_mask; - bank->context.irqenable1 = l; + /* + * Program GPIO wakeup along with IRQ enable to satisfy OMAP4430 TRM + * note requiring correlation between the IRQ enable registers and + * the wakeup registers. In any case, we want wakeup from idle + * enabled for the GPIOs which support this feature. + */ + if (bank->regs->wkup_en && + (bank->regs->edgectrl1 || !(bank->non_wakeup_gpios & gpio_mask))) { + bank->context.wake_en = + omap_gpio_rmw(bank->base + bank->regs->wkup_en, + gpio_mask, enable); } - - writel_relaxed(l, reg); -} - -static inline void omap_set_gpio_irqenable(struct gpio_bank *bank, - unsigned offset, int enable) -{ - if (enable) - omap_enable_gpio_irqbank(bank, BIT(offset)); - else - omap_disable_gpio_irqbank(bank, BIT(offset)); } /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */ @@ -690,38 +547,6 @@ static int omap_gpio_wake_enable(struct irq_data *d, unsigned int enable) return irq_set_irq_wake(bank->irq, enable); } -static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - struct gpio_bank *bank = gpiochip_get_data(chip); - unsigned long flags; - - pm_runtime_get_sync(chip->parent); - - raw_spin_lock_irqsave(&bank->lock, flags); - omap_enable_gpio_module(bank, offset); - bank->mod_usage |= BIT(offset); - raw_spin_unlock_irqrestore(&bank->lock, flags); - - return 0; -} - -static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - struct gpio_bank *bank = gpiochip_get_data(chip); - unsigned long flags; - - raw_spin_lock_irqsave(&bank->lock, flags); - bank->mod_usage &= ~(BIT(offset)); - if (!LINE_USED(bank->irq_usage, offset)) { - omap_set_gpio_direction(bank, offset, 1); - omap_clear_gpio_debounce(bank, offset); - } - omap_disable_gpio_module(bank, offset); - raw_spin_unlock_irqrestore(&bank->lock, flags); - - pm_runtime_put(chip->parent); -} - /* * We need to unmask the GPIO bank interrupt as soon as possible to * avoid missing GPIO interrupts for other lines in the bank. @@ -734,7 +559,7 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank) { void __iomem *isr_reg = NULL; - u32 enabled, isr, level_mask; + u32 enabled, isr, edge; unsigned int bit; struct gpio_bank *bank = gpiobank; unsigned long wa_lock_flags; @@ -754,16 +579,14 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank) enabled = omap_get_gpio_irqbank_mask(bank); isr = readl_relaxed(isr_reg) & enabled; - if (bank->level_mask) - level_mask = bank->level_mask & enabled; - else - level_mask = 0; - - /* clear edge sensitive interrupts before handler(s) are - called so that we don't miss any interrupt occurred while - executing them */ - if (isr & ~level_mask) - omap_clear_gpio_irqbank(bank, isr & ~level_mask); + /* + * Clear edge sensitive interrupts before calling handler(s) + * so subsequent edge transitions are not missed while the + * handlers are running. + */ + edge = isr & ~bank->level_mask; + if (edge) + omap_clear_gpio_irqbank(bank, edge); raw_spin_unlock_irqrestore(&bank->lock, lock_flags); @@ -810,8 +633,6 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d) if (!LINE_USED(bank->mod_usage, offset)) omap_set_gpio_direction(bank, offset, 1); - else if (!omap_gpio_is_input(bank, offset)) - goto err; omap_enable_gpio_module(bank, offset); bank->irq_usage |= BIT(offset); @@ -819,9 +640,6 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d) omap_gpio_unmask_irq(d); return 0; -err: - raw_spin_unlock_irqrestore(&bank->lock, flags); - return -EINVAL; } static void omap_gpio_irq_shutdown(struct irq_data *d) @@ -832,9 +650,9 @@ static void omap_gpio_irq_shutdown(struct irq_data *d) raw_spin_lock_irqsave(&bank->lock, flags); bank->irq_usage &= ~(BIT(offset)); - omap_set_gpio_irqenable(bank, offset, 0); - omap_clear_gpio_irqstatus(bank, offset); omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE); + omap_clear_gpio_irqstatus(bank, offset); + omap_set_gpio_irqenable(bank, offset, 0); if (!LINE_USED(bank->mod_usage, offset)) omap_clear_gpio_debounce(bank, offset); omap_disable_gpio_module(bank, offset); @@ -855,14 +673,6 @@ static void gpio_irq_bus_sync_unlock(struct irq_data *data) pm_runtime_put(bank->chip.parent); } -static void omap_gpio_ack_irq(struct irq_data *d) -{ - struct gpio_bank *bank = omap_irq_data_get_bank(d); - unsigned offset = d->hwirq; - - omap_clear_gpio_irqstatus(bank, offset); -} - static void omap_gpio_mask_irq(struct irq_data *d) { struct gpio_bank *bank = omap_irq_data_get_bank(d); @@ -870,8 +680,8 @@ static void omap_gpio_mask_irq(struct irq_data *d) unsigned long flags; raw_spin_lock_irqsave(&bank->lock, flags); - omap_set_gpio_irqenable(bank, offset, 0); omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE); + omap_set_gpio_irqenable(bank, offset, 0); raw_spin_unlock_irqrestore(&bank->lock, flags); } @@ -883,9 +693,6 @@ static void omap_gpio_unmask_irq(struct irq_data *d) unsigned long flags; raw_spin_lock_irqsave(&bank->lock, flags); - if (trigger) - omap_set_gpio_triggering(bank, offset, trigger); - omap_set_gpio_irqenable(bank, offset, 1); /* @@ -893,9 +700,13 @@ static void omap_gpio_unmask_irq(struct irq_data *d) * is cleared, thus after the handler has run. OMAP4 needs this done * after enabing the interrupt to clear the wakeup status. */ - if (bank->level_mask & BIT(offset)) + if (bank->regs->leveldetect0 && bank->regs->wkup_en && + trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) omap_clear_gpio_irqstatus(bank, offset); + if (trigger) + omap_set_gpio_triggering(bank, offset, trigger); + raw_spin_unlock_irqrestore(&bank->lock, flags); } @@ -961,19 +772,44 @@ static inline void omap_mpuio_init(struct gpio_bank *bank) /*---------------------------------------------------------------------*/ -static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) { - struct gpio_bank *bank; + struct gpio_bank *bank = gpiochip_get_data(chip); + unsigned long flags; + + pm_runtime_get_sync(chip->parent); + + raw_spin_lock_irqsave(&bank->lock, flags); + omap_enable_gpio_module(bank, offset); + bank->mod_usage |= BIT(offset); + raw_spin_unlock_irqrestore(&bank->lock, flags); + + return 0; +} + +static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + struct gpio_bank *bank = gpiochip_get_data(chip); unsigned long flags; - void __iomem *reg; - int dir; - bank = gpiochip_get_data(chip); - reg = bank->base + bank->regs->direction; raw_spin_lock_irqsave(&bank->lock, flags); - dir = !!(readl_relaxed(reg) & BIT(offset)); + bank->mod_usage &= ~(BIT(offset)); + if (!LINE_USED(bank->irq_usage, offset)) { + omap_set_gpio_direction(bank, offset, 1); + omap_clear_gpio_debounce(bank, offset); + } + omap_disable_gpio_module(bank, offset); raw_spin_unlock_irqrestore(&bank->lock, flags); - return dir; + + pm_runtime_put(chip->parent); +} + +static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +{ + struct gpio_bank *bank = gpiochip_get_data(chip); + + return !!(readl_relaxed(bank->base + bank->regs->direction) & + BIT(offset)); } static int omap_gpio_input(struct gpio_chip *chip, unsigned offset) @@ -990,14 +826,15 @@ static int omap_gpio_input(struct gpio_chip *chip, unsigned offset) static int omap_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct gpio_bank *bank; - - bank = gpiochip_get_data(chip); + struct gpio_bank *bank = gpiochip_get_data(chip); + void __iomem *reg; if (omap_gpio_is_input(bank, offset)) - return omap_get_gpio_datain(bank, offset); + reg = bank->base + bank->regs->datain; else - return omap_get_gpio_dataout(bank, offset); + reg = bank->base + bank->regs->dataout; + + return (readl_relaxed(reg) & BIT(offset)) != 0; } static int omap_gpio_output(struct gpio_chip *chip, unsigned offset, int value) @@ -1017,18 +854,20 @@ static int omap_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask, unsigned long *bits) { struct gpio_bank *bank = gpiochip_get_data(chip); - void __iomem *reg = bank->base + bank->regs->direction; - unsigned long in = readl_relaxed(reg), l; + void __iomem *base = bank->base; + u32 direction, m, val = 0; - *bits = 0; + direction = readl_relaxed(base + bank->regs->direction); - l = in & *mask; - if (l) - *bits |= omap_get_gpio_datain_multiple(bank, &l); + m = direction & *mask; + if (m) + val |= readl_relaxed(base + bank->regs->datain) & m; - l = ~in & *mask; - if (l) - *bits |= omap_get_gpio_dataout_multiple(bank, &l); + m = ~direction & *mask; + if (m) + val |= readl_relaxed(base + bank->regs->dataout) & m; + + *bits = val; return 0; } @@ -1081,10 +920,14 @@ static void omap_gpio_set_multiple(struct gpio_chip *chip, unsigned long *mask, unsigned long *bits) { struct gpio_bank *bank = gpiochip_get_data(chip); + void __iomem *reg = bank->base + bank->regs->dataout; unsigned long flags; + u32 l; raw_spin_lock_irqsave(&bank->lock, flags); - bank->set_dataout_multiple(bank, mask, bits); + l = (readl_relaxed(reg) & ~*mask) | (*bits & *mask); + writel_relaxed(l, reg); + bank->context.dataout = l; raw_spin_unlock_irqrestore(&bank->lock, flags); } @@ -1118,9 +961,9 @@ static void omap_gpio_mod_init(struct gpio_bank *bank) return; } - omap_gpio_rmw(base, bank->regs->irqenable, l, + omap_gpio_rmw(base + bank->regs->irqenable, l, bank->regs->irqenable_inv); - omap_gpio_rmw(base, bank->regs->irqstatus, l, + omap_gpio_rmw(base + bank->regs->irqstatus, l, !bank->regs->irqenable_inv); if (bank->regs->debounce_en) writel_relaxed(0, base + bank->regs->debounce_en); @@ -1183,11 +1026,8 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) #endif /* MPUIO is a bit different, reading IRQ status clears it */ - if (bank->is_mpuio) { - irqc->irq_ack = dummy_irq_chip.irq_ack; - if (!bank->regs->wkup_en) - irqc->irq_set_wake = NULL; - } + if (bank->is_mpuio && !bank->regs->wkup_en) + irqc->irq_set_wake = NULL; irq = &bank->chip.irq; irq->chip = irqc; @@ -1218,7 +1058,7 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) static void omap_gpio_init_context(struct gpio_bank *p) { - struct omap_gpio_reg_offs *regs = p->regs; + const struct omap_gpio_reg_offs *regs = p->regs; void __iomem *base = p->base; p->context.ctrl = readl_relaxed(base + regs->ctrl); @@ -1230,60 +1070,56 @@ static void omap_gpio_init_context(struct gpio_bank *p) 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.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); + const struct omap_gpio_reg_offs *regs = bank->regs; + void __iomem *base = bank->base; + + writel_relaxed(bank->context.wake_en, base + regs->wkup_en); + writel_relaxed(bank->context.ctrl, base + regs->ctrl); + writel_relaxed(bank->context.leveldetect0, base + regs->leveldetect0); + writel_relaxed(bank->context.leveldetect1, base + regs->leveldetect1); + writel_relaxed(bank->context.risingdetect, base + regs->risingdetect); + writel_relaxed(bank->context.fallingdetect, base + regs->fallingdetect); + writel_relaxed(bank->context.dataout, base + regs->dataout); + writel_relaxed(bank->context.oe, base + regs->direction); if (bank->dbck_enable_mask) { - writel_relaxed(bank->context.debounce, bank->base + - bank->regs->debounce); + writel_relaxed(bank->context.debounce, base + regs->debounce); writel_relaxed(bank->context.debounce_en, - bank->base + bank->regs->debounce_en); + base + regs->debounce_en); } - writel_relaxed(bank->context.irqenable1, - bank->base + bank->regs->irqenable); - writel_relaxed(bank->context.irqenable2, - bank->base + bank->regs->irqenable2); + writel_relaxed(bank->context.irqenable1, base + regs->irqenable); + writel_relaxed(bank->context.irqenable2, base + regs->irqenable2); } static void omap_gpio_idle(struct gpio_bank *bank, bool may_lose_context) { struct device *dev = bank->chip.parent; void __iomem *base = bank->base; - u32 nowake; + u32 mask, nowake; bank->saved_datain = readl_relaxed(base + bank->regs->datain); if (!bank->enabled_non_wakeup_gpios) goto update_gpio_context_count; + /* Check for pending EDGE_FALLING, ignore EDGE_BOTH */ + mask = bank->enabled_non_wakeup_gpios & bank->context.fallingdetect; + mask &= ~bank->context.risingdetect; + bank->saved_datain |= mask; + + /* Check for pending EDGE_RISING, ignore EDGE_BOTH */ + mask = bank->enabled_non_wakeup_gpios & bank->context.risingdetect; + mask &= ~bank->context.fallingdetect; + bank->saved_datain &= ~mask; + if (!may_lose_context) goto update_gpio_context_count; @@ -1294,8 +1130,8 @@ static void omap_gpio_idle(struct gpio_bank *bank, bool may_lose_context) */ 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); + omap_gpio_rmw(base + bank->regs->fallingdetect, nowake, ~nowake); + omap_gpio_rmw(base + bank->regs->risingdetect, nowake, ~nowake); } update_gpio_context_count: @@ -1424,7 +1260,7 @@ static int gpio_omap_cpu_notifier(struct notifier_block *nb, return NOTIFY_OK; } -static struct omap_gpio_reg_offs omap2_gpio_regs = { +static const struct omap_gpio_reg_offs omap2_gpio_regs = { .revision = OMAP24XX_GPIO_REVISION, .direction = OMAP24XX_GPIO_OE, .datain = OMAP24XX_GPIO_DATAIN, @@ -1447,7 +1283,7 @@ static struct omap_gpio_reg_offs omap2_gpio_regs = { .fallingdetect = OMAP24XX_GPIO_FALLINGDETECT, }; -static struct omap_gpio_reg_offs omap4_gpio_regs = { +static const struct omap_gpio_reg_offs omap4_gpio_regs = { .revision = OMAP4_GPIO_REVISION, .direction = OMAP4_GPIO_OE, .datain = OMAP4_GPIO_DATAIN, @@ -1456,6 +1292,8 @@ static struct omap_gpio_reg_offs omap4_gpio_regs = { .clr_dataout = OMAP4_GPIO_CLEARDATAOUT, .irqstatus = OMAP4_GPIO_IRQSTATUS0, .irqstatus2 = OMAP4_GPIO_IRQSTATUS1, + .irqstatus_raw0 = OMAP4_GPIO_IRQSTATUSRAW0, + .irqstatus_raw1 = OMAP4_GPIO_IRQSTATUSRAW1, .irqenable = OMAP4_GPIO_IRQSTATUSSET0, .irqenable2 = OMAP4_GPIO_IRQSTATUSSET1, .set_irqenable = OMAP4_GPIO_IRQSTATUSSET0, @@ -1531,7 +1369,7 @@ static int omap_gpio_probe(struct platform_device *pdev) irqc->irq_startup = omap_gpio_irq_startup, irqc->irq_shutdown = omap_gpio_irq_shutdown, - irqc->irq_ack = omap_gpio_ack_irq, + irqc->irq_ack = dummy_irq_chip.irq_ack, irqc->irq_mask = omap_gpio_mask_irq, irqc->irq_unmask = omap_gpio_unmask_irq, irqc->irq_set_type = omap_gpio_irq_type, @@ -1575,14 +1413,10 @@ static int omap_gpio_probe(struct platform_device *pdev) pdata->get_context_loss_count; } - if (bank->regs->set_dataout && bank->regs->clr_dataout) { + 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 { + 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); @@ -1638,7 +1472,6 @@ 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) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index b7ef33f63392..c31ad558d056 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -1180,6 +1180,7 @@ static const struct of_device_id pca953x_dt_ids[] = { { .compatible = "ti,tca6408", .data = OF_953X( 8, PCA_INT), }, { .compatible = "ti,tca6416", .data = OF_953X(16, PCA_INT), }, { .compatible = "ti,tca6424", .data = OF_953X(24, PCA_INT), }, + { .compatible = "ti,tca9539", .data = OF_953X(16, PCA_INT), }, { .compatible = "onnn,cat9554", .data = OF_953X( 8, PCA_INT), }, { .compatible = "onnn,pca9654", .data = OF_953X( 8, PCA_INT), }, diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index c9b650f617fa..14fb8f6a1ad2 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Driver for pcf857x, pca857x, and pca967x I2C GPIO expanders * * Copyright (C) 2007 David Brownell - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/gpio/driver.h> diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index dc42571e6fdc..84af248f5172 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -286,6 +286,7 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) { struct device *dev = &adev->dev; struct pl061 *pl061; + struct gpio_irq_chip *girq; int ret, irq; pl061 = devm_kzalloc(dev, sizeof(*pl061), GFP_KERNEL); @@ -313,10 +314,6 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) pl061->gc.parent = dev; pl061->gc.owner = THIS_MODULE; - ret = gpiochip_add_data(&pl061->gc, pl061); - if (ret) - return ret; - /* * irq_chip support */ @@ -335,19 +332,24 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id) } pl061->parent_irq = irq; - ret = gpiochip_irqchip_add(&pl061->gc, &pl061->irq_chip, - 0, handle_bad_irq, - IRQ_TYPE_NONE); - if (ret) { - dev_info(&adev->dev, "could not add irqchip\n"); + girq = &pl061->gc.irq; + girq->chip = &pl061->irq_chip; + girq->parent_handler = pl061_irq_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = irq; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + + ret = devm_gpiochip_add_data(dev, &pl061->gc, pl061); + if (ret) return ret; - } - gpiochip_set_chained_irqchip(&pl061->gc, &pl061->irq_chip, - irq, pl061_irq_handler); amba_set_drvdata(adev, pl061); - dev_info(&adev->dev, "PL061 GPIO chip @%pa registered\n", - &adev->res.start); + dev_info(dev, "PL061 GPIO chip %s registered\n", dev_name(dev)); return 0; } diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index 70e95fc4779f..187984d26f47 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -489,7 +489,7 @@ static int gpio_rcar_probe(struct platform_device *pdev) irq_chip->irq_unmask = gpio_rcar_irq_enable; irq_chip->irq_set_type = gpio_rcar_irq_set_type; irq_chip->irq_set_wake = gpio_rcar_irq_set_wake; - irq_chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND; + irq_chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND; ret = gpiochip_add_data(gpio_chip, p); if (ret) { diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c index 2938217566d3..01ed2517e9fd 100644 --- a/drivers/gpio/gpio-rdc321x.c +++ b/drivers/gpio/gpio-rdc321x.c @@ -1,23 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * RDC321x GPIO driver * * Copyright (C) 2008, Volker Weiss <dev@tintuc.de> * Copyright (C) 2007-2010 Florian Fainelli <florian@openwrt.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * */ #include <linux/module.h> #include <linux/kernel.h> diff --git a/drivers/gpio/gpio-siox.c b/drivers/gpio/gpio-siox.c index 571b2a81c6de..40067e1535d3 100644 --- a/drivers/gpio/gpio-siox.c +++ b/drivers/gpio/gpio-siox.c @@ -243,17 +243,14 @@ static int gpio_siox_probe(struct siox_device *sdevice) if (ret) { dev_err(&sdevice->dev, "Failed to register gpio chip (%d)\n", ret); - goto err_gpiochip; + return ret; } ret = gpiochip_irqchip_add(&ddata->gchip, &ddata->ichip, - 0, handle_level_irq, IRQ_TYPE_EDGE_RISING); - if (ret) { + 0, handle_level_irq, IRQ_TYPE_NONE); + if (ret) dev_err(&sdevice->dev, "Failed to register irq chip (%d)\n", ret); -err_gpiochip: - gpiochip_remove(&ddata->gchip); - } return ret; } @@ -275,18 +272,7 @@ static struct siox_driver gpio_siox_driver = { .name = "gpio-siox", }, }; - -static int __init gpio_siox_init(void) -{ - return siox_driver_register(&gpio_siox_driver); -} -module_init(gpio_siox_init); - -static void __exit gpio_siox_exit(void) -{ - siox_driver_unregister(&gpio_siox_driver); -} -module_exit(gpio_siox_exit); +module_siox_driver(gpio_siox_driver); MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>"); MODULE_DESCRIPTION("SIOX gpio driver"); diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 6d9b6906b9d0..a54bba1bda6c 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -550,8 +550,8 @@ DEFINE_SHOW_ATTRIBUTE(tegra_dbg_gpio); static void tegra_gpio_debuginit(struct tegra_gpio_info *tgi) { - (void) debugfs_create_file("tegra_gpio", 0444, - NULL, tgi, &tegra_dbg_gpio_fops); + debugfs_create_file("tegra_gpio", 0444, NULL, tgi, + &tegra_dbg_gpio_fops); } #else diff --git a/drivers/gpio/gpio-tps65218.c b/drivers/gpio/gpio-tps65218.c index a379bba57d31..43a1150055ce 100644 --- a/drivers/gpio/gpio-tps65218.c +++ b/drivers/gpio/gpio-tps65218.c @@ -1,13 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright 2015 Verifone Int. * * Author: Nicolas Saenz Julienne <nicolassaenzj@gmail.com> * - * This program is free software; you can redistribute it and/or modify i t - * under the terms of the GNU General Public License as published by th e - * Free Software Foundation; either version 2 of the License, or (at you r - * option) any later version. - * * This driver is based on the gpio-tps65912 implementation. */ diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 30aef41e3b7e..7ba668db171b 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -265,7 +265,8 @@ static int vf610_gpio_probe(struct platform_device *pdev) return port->irq; port->clk_port = devm_clk_get(dev, "port"); - if (!IS_ERR(port->clk_port)) { + ret = PTR_ERR_OR_ZERO(port->clk_port); + if (!ret) { ret = clk_prepare_enable(port->clk_port); if (ret) return ret; @@ -273,16 +274,17 @@ static int vf610_gpio_probe(struct platform_device *pdev) port->clk_port); if (ret) return ret; - } else if (port->clk_port == ERR_PTR(-EPROBE_DEFER)) { + } else if (ret == -EPROBE_DEFER) { /* * Percolate deferrals, for anything else, * just live without the clocking. */ - return PTR_ERR(port->clk_port); + return ret; } port->clk_gpio = devm_clk_get(dev, "gpio"); - if (!IS_ERR(port->clk_gpio)) { + ret = PTR_ERR_OR_ZERO(port->clk_gpio); + if (!ret) { ret = clk_prepare_enable(port->clk_gpio); if (ret) return ret; @@ -290,8 +292,8 @@ static int vf610_gpio_probe(struct platform_device *pdev) port->clk_gpio); if (ret) return ret; - } else if (port->clk_gpio == ERR_PTR(-EPROBE_DEFER)) { - return PTR_ERR(port->clk_gpio); + } else if (ret == -EPROBE_DEFER) { + return ret; } gc = &port->gc; diff --git a/drivers/gpio/gpio-vr41xx.c b/drivers/gpio/gpio-vr41xx.c index b13a49c89cc1..98cd715ccc33 100644 --- a/drivers/gpio/gpio-vr41xx.c +++ b/drivers/gpio/gpio-vr41xx.c @@ -467,10 +467,9 @@ static struct gpio_chip vr41xx_gpio_chip = { static int giu_probe(struct platform_device *pdev) { - struct resource *res; unsigned int trigger, i, pin; struct irq_chip *chip; - int irq, ret; + int irq; switch (pdev->id) { case GPIO_50PINS_PULLUPDOWN: @@ -489,21 +488,14 @@ static int giu_probe(struct platform_device *pdev) return -ENODEV; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -EBUSY; - - giu_base = ioremap(res->start, resource_size(res)); - if (!giu_base) - return -ENOMEM; + giu_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(giu_base)) + return PTR_ERR(giu_base); vr41xx_gpio_chip.parent = &pdev->dev; - ret = gpiochip_add_data(&vr41xx_gpio_chip, NULL); - if (!ret) { - iounmap(giu_base); + if (gpiochip_add_data(&vr41xx_gpio_chip, NULL)) return -ENODEV; - } giu_write(GIUINTENL, 0); giu_write(GIUINTENH, 0); @@ -534,7 +526,6 @@ static int giu_probe(struct platform_device *pdev) static int giu_remove(struct platform_device *pdev) { if (giu_base) { - iounmap(giu_base); giu_base = NULL; } diff --git a/drivers/gpio/gpio-xgene-sb.c b/drivers/gpio/gpio-xgene-sb.c index 641a05181017..38c01912c7b2 100644 --- a/drivers/gpio/gpio-xgene-sb.c +++ b/drivers/gpio/gpio-xgene-sb.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * AppliedMicro X-Gene SoC GPIO-Standby Driver * @@ -5,19 +6,6 @@ * Author: Tin Huynh <tnhuynh@apm.com>. * Y Vo <yvo@apm.com>. * Quan Nguyen <qnguyen@apm.com>. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <linux/module.h> diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index 8f24478cc18b..42e5c25bac87 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -18,7 +18,6 @@ #include <linux/module.h> #include <linux/of_device.h> #include <linux/of_platform.h> -#include <linux/of_gpio.h> #include <linux/io.h> #include <linux/gpio/driver.h> #include <linux/slab.h> @@ -40,14 +39,16 @@ /** * struct xgpio_instance - Stores information about GPIO device - * @mmchip: OF GPIO chip for memory mapped banks + * @gc: GPIO chip + * @regs: register block * @gpio_width: GPIO width for every channel * @gpio_state: GPIO state shadow register * @gpio_dir: GPIO direction shadow register * @gpio_lock: Lock used for synchronization */ struct xgpio_instance { - struct of_mm_gpio_chip mmchip; + struct gpio_chip gc; + void __iomem *regs; unsigned int gpio_width[2]; u32 gpio_state[2]; u32 gpio_dir[2]; @@ -91,11 +92,10 @@ static inline int xgpio_offset(struct xgpio_instance *chip, int gpio) */ static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) { - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct xgpio_instance *chip = gpiochip_get_data(gc); u32 val; - val = xgpio_readreg(mm_gc->regs + XGPIO_DATA_OFFSET + + val = xgpio_readreg(chip->regs + XGPIO_DATA_OFFSET + xgpio_regoffset(chip, gpio)); return !!(val & BIT(xgpio_offset(chip, gpio))); @@ -113,7 +113,6 @@ static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { unsigned long flags; - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct xgpio_instance *chip = gpiochip_get_data(gc); int index = xgpio_index(chip, gpio); int offset = xgpio_offset(chip, gpio); @@ -126,7 +125,7 @@ static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) else chip->gpio_state[index] &= ~BIT(offset); - xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET + + xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + xgpio_regoffset(chip, gpio), chip->gpio_state[index]); spin_unlock_irqrestore(&chip->gpio_lock[index], flags); @@ -145,7 +144,6 @@ static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, unsigned long *bits) { unsigned long flags; - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct xgpio_instance *chip = gpiochip_get_data(gc); int index = xgpio_index(chip, 0); int offset, i; @@ -157,7 +155,7 @@ static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, if (*mask == 0) break; if (index != xgpio_index(chip, i)) { - xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET + + xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + xgpio_regoffset(chip, i), chip->gpio_state[index]); spin_unlock_irqrestore(&chip->gpio_lock[index], flags); @@ -173,7 +171,7 @@ static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, } } - xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET + + xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + xgpio_regoffset(chip, i), chip->gpio_state[index]); spin_unlock_irqrestore(&chip->gpio_lock[index], flags); @@ -191,7 +189,6 @@ static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) { unsigned long flags; - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct xgpio_instance *chip = gpiochip_get_data(gc); int index = xgpio_index(chip, gpio); int offset = xgpio_offset(chip, gpio); @@ -200,7 +197,7 @@ static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) /* Set the GPIO bit in shadow register and set direction as input */ chip->gpio_dir[index] |= BIT(offset); - xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET + + xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET + xgpio_regoffset(chip, gpio), chip->gpio_dir[index]); spin_unlock_irqrestore(&chip->gpio_lock[index], flags); @@ -223,7 +220,6 @@ static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { unsigned long flags; - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct xgpio_instance *chip = gpiochip_get_data(gc); int index = xgpio_index(chip, gpio); int offset = xgpio_offset(chip, gpio); @@ -235,12 +231,12 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) chip->gpio_state[index] |= BIT(offset); else chip->gpio_state[index] &= ~BIT(offset); - xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET + + xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + xgpio_regoffset(chip, gpio), chip->gpio_state[index]); /* Clear the GPIO bit in shadow register and set direction as output */ chip->gpio_dir[index] &= ~BIT(offset); - xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET + + xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET + xgpio_regoffset(chip, gpio), chip->gpio_dir[index]); spin_unlock_irqrestore(&chip->gpio_lock[index], flags); @@ -250,43 +246,23 @@ static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) /** * xgpio_save_regs - Set initial values of GPIO pins - * @mm_gc: Pointer to memory mapped GPIO chip structure + * @chip: Pointer to GPIO instance */ -static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc) +static void xgpio_save_regs(struct xgpio_instance *chip) { - struct xgpio_instance *chip = - container_of(mm_gc, struct xgpio_instance, mmchip); - - xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state[0]); - xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir[0]); + xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET, chip->gpio_state[0]); + xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET, chip->gpio_dir[0]); if (!chip->gpio_width[1]) return; - xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET + XGPIO_CHANNEL_OFFSET, + xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + XGPIO_CHANNEL_OFFSET, chip->gpio_state[1]); - xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET + XGPIO_CHANNEL_OFFSET, + xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET + XGPIO_CHANNEL_OFFSET, chip->gpio_dir[1]); } /** - * xgpio_remove - Remove method for the GPIO device. - * @pdev: pointer to the platform device - * - * This function remove gpiochips and frees all the allocated resources. - * - * Return: 0 always - */ -static int xgpio_remove(struct platform_device *pdev) -{ - struct xgpio_instance *chip = platform_get_drvdata(pdev); - - of_mm_gpiochip_remove(&chip->mmchip); - - return 0; -} - -/** * xgpio_of_probe - Probe method for the GPIO device. * @pdev: pointer to the platform device * @@ -347,21 +323,28 @@ static int xgpio_probe(struct platform_device *pdev) spin_lock_init(&chip->gpio_lock[1]); } - chip->mmchip.gc.ngpio = chip->gpio_width[0] + chip->gpio_width[1]; - chip->mmchip.gc.parent = &pdev->dev; - chip->mmchip.gc.direction_input = xgpio_dir_in; - chip->mmchip.gc.direction_output = xgpio_dir_out; - chip->mmchip.gc.get = xgpio_get; - chip->mmchip.gc.set = xgpio_set; - chip->mmchip.gc.set_multiple = xgpio_set_multiple; + chip->gc.base = -1; + chip->gc.ngpio = chip->gpio_width[0] + chip->gpio_width[1]; + chip->gc.parent = &pdev->dev; + chip->gc.direction_input = xgpio_dir_in; + chip->gc.direction_output = xgpio_dir_out; + chip->gc.get = xgpio_get; + chip->gc.set = xgpio_set; + chip->gc.set_multiple = xgpio_set_multiple; + + chip->gc.label = dev_name(&pdev->dev); + + chip->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(chip->regs)) { + dev_err(&pdev->dev, "failed to ioremap memory resource\n"); + return PTR_ERR(chip->regs); + } - chip->mmchip.save_regs = xgpio_save_regs; + xgpio_save_regs(chip); - /* Call the OF gpio helper to setup and register the GPIO device */ - status = of_mm_gpiochip_add_data(np, &chip->mmchip, chip); + status = devm_gpiochip_add_data(&pdev->dev, &chip->gc, chip); if (status) { - pr_err("%pOF: error in probe function with status %d\n", - np, status); + dev_err(&pdev->dev, "failed to add GPIO chip\n"); return status; } @@ -377,7 +360,6 @@ MODULE_DEVICE_TABLE(of, xgpio_of_match); static struct platform_driver xgpio_plat_driver = { .probe = xgpio_probe, - .remove = xgpio_remove, .driver = { .name = "gpio-xilinx", .of_match_table = xgpio_of_match, diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index c9fc9e232aaf..39f2f9035c11 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -217,14 +217,13 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares, if (!handler) return AE_OK; - desc = gpiochip_request_own_desc(chip, pin, "ACPI:Event", 0); + desc = gpiochip_request_own_desc(chip, pin, "ACPI:Event", + GPIO_ACTIVE_HIGH, GPIOD_IN); if (IS_ERR(desc)) { dev_err(chip->parent, "Failed to request GPIO\n"); return AE_ERROR; } - gpiod_direction_input(desc); - ret = gpiochip_lock_as_irq(chip, pin); if (ret) { dev_err(chip->parent, "Failed to lock GPIO as interrupt\n"); @@ -951,6 +950,7 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, const char *label = "ACPI:OpRegion"; desc = gpiochip_request_own_desc(chip, pin, label, + GPIO_ACTIVE_HIGH, flags); if (IS_ERR(desc)) { status = AE_ERROR; diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index aec7bd86ae7e..a8f02f551d6b 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -158,6 +158,12 @@ static void of_gpio_flags_quirks(struct device_node *np, } } } + + /* Legacy handling of stmmac's active-low PHY reset line */ + if (IS_ENABLED(CONFIG_STMMAC_ETH) && + !strcmp(propname, "snps,reset-gpio") && + of_property_read_bool(np, "snps,reset-active-low")) + *flags |= OF_GPIO_ACTIVE_LOW; } /** @@ -255,6 +261,37 @@ static struct gpio_desc *of_find_spi_gpio(struct device *dev, const char *con_id } /* + * The old Freescale bindings use simply "gpios" as name for the chip select + * lines rather than "cs-gpios" like all other SPI hardware. Account for this + * with a special quirk. + */ +static struct gpio_desc *of_find_spi_cs_gpio(struct device *dev, + const char *con_id, + unsigned int idx, + unsigned long *flags) +{ + struct device_node *np = dev->of_node; + + if (!IS_ENABLED(CONFIG_SPI_MASTER)) + return ERR_PTR(-ENOENT); + + /* Allow this specifically for Freescale devices */ + if (!of_device_is_compatible(np, "fsl,spi") && + !of_device_is_compatible(np, "aeroflexgaisler,spictrl")) + return ERR_PTR(-ENOENT); + /* Allow only if asking for "cs-gpios" */ + if (!con_id || strcmp(con_id, "cs")) + return ERR_PTR(-ENOENT); + + /* + * While all other SPI controllers use "cs-gpios" the Freescale + * uses just "gpios" so translate to that when "cs-gpios" is + * requested. + */ + return of_find_gpio(dev, NULL, idx, flags); +} + +/* * Some regulator bindings happened before we managed to establish that GPIO * properties should be named "foo-gpios" so we have this special kludge for * them. @@ -325,6 +362,12 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, /* Special handling for SPI GPIOs if used */ if (IS_ERR(desc)) desc = of_find_spi_gpio(dev, con_id, &of_flags); + if (IS_ERR(desc)) { + /* This quirk looks up flags and all */ + desc = of_find_spi_cs_gpio(dev, con_id, idx, flags); + if (!IS_ERR(desc)) + return desc; + } /* Special handling for regulator GPIOs if used */ if (IS_ERR(desc) && PTR_ERR(desc) != -EPROBE_DEFER) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index e013d417a936..12bd0f094abc 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1644,39 +1644,47 @@ EXPORT_SYMBOL_GPL(gpiochip_irqchip_irq_valid); /** * gpiochip_set_cascaded_irqchip() - connects a cascaded irqchip to a gpiochip - * @gpiochip: the gpiochip to set the irqchip chain to + * @gc: the gpiochip to set the irqchip chain to * @parent_irq: the irq number corresponding to the parent IRQ for this * chained irqchip * @parent_handler: the parent interrupt handler for the accumulated IRQ * coming out of the gpiochip. If the interrupt is nested rather than * cascaded, pass NULL in this handler argument */ -static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gpiochip, +static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gc, unsigned int parent_irq, irq_flow_handler_t parent_handler) { - if (!gpiochip->irq.domain) { - chip_err(gpiochip, "called %s before setting up irqchip\n", + struct gpio_irq_chip *girq = &gc->irq; + struct device *dev = &gc->gpiodev->dev; + + if (!girq->domain) { + chip_err(gc, "called %s before setting up irqchip\n", __func__); return; } if (parent_handler) { - if (gpiochip->can_sleep) { - chip_err(gpiochip, + if (gc->can_sleep) { + chip_err(gc, "you cannot have chained interrupts on a chip that may sleep\n"); return; } + girq->parents = devm_kcalloc(dev, 1, + sizeof(*girq->parents), + GFP_KERNEL); + if (!girq->parents) { + chip_err(gc, "out of memory allocating parent IRQ\n"); + return; + } + girq->parents[0] = parent_irq; + girq->num_parents = 1; /* * The parent irqchip is already using the chip_data for this * irqchip, so our callbacks simply use the handler_data. */ irq_set_chained_handler_and_data(parent_irq, parent_handler, - gpiochip); - - gpiochip->irq.parent_irq = parent_irq; - gpiochip->irq.parents = &gpiochip->irq.parent_irq; - gpiochip->irq.num_parents = 1; + gc); } } @@ -2503,7 +2511,11 @@ EXPORT_SYMBOL_GPL(gpiochip_is_requested); * @chip: GPIO chip * @hwnum: hardware number of the GPIO for which to request the descriptor * @label: label for the GPIO - * @flags: flags for this GPIO or 0 if default + * @lflags: lookup flags for this GPIO or 0 if default, this can be used to + * specify things like line inversion semantics with the machine flags + * such as GPIO_OUT_LOW + * @dflags: descriptor request flags for this GPIO or 0 if default, this + * can be used to specify consumer semantics such as open drain * * Function allows GPIO chip drivers to request and use their own GPIO * descriptors via gpiolib API. Difference to gpiod_request() is that this @@ -2517,9 +2529,9 @@ EXPORT_SYMBOL_GPL(gpiochip_is_requested); */ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip, u16 hwnum, const char *label, - enum gpiod_flags flags) + enum gpio_lookup_flags lflags, + enum gpiod_flags dflags) { - unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT; struct gpio_desc *desc = gpiochip_get_desc(chip, hwnum); int err; @@ -2532,7 +2544,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, lflags, flags); + err = gpiod_configure_flags(desc, label, lflags, dflags); if (err) { chip_err(chip, "setup of own GPIO %s failed\n", label); gpiod_free_commit(desc); @@ -4420,15 +4432,8 @@ int gpiod_hog(struct gpio_desc *desc, const char *name, chip = gpiod_to_chip(desc); hwnum = gpio_chip_hwgpio(desc); - /* - * FIXME: not very elegant that we call gpiod_configure_flags() - * twice here (once inside gpiochip_request_own_desc() and - * again here), but the gpiochip_request_own_desc() is external - * and cannot really pass the lflags so this is the lesser evil - * at the moment. Pass zero as dflags on this first call so we - * don't screw anything up. - */ - local_desc = gpiochip_request_own_desc(chip, hwnum, name, 0); + local_desc = gpiochip_request_own_desc(chip, hwnum, name, + lflags, dflags); if (IS_ERR(local_desc)) { status = PTR_ERR(local_desc); pr_err("requesting hog GPIO %s (chip %s, offset %d) failed, %d\n", @@ -4436,14 +4441,6 @@ int gpiod_hog(struct gpio_desc *desc, const char *name, return status; } - status = gpiod_configure_flags(desc, name, lflags, dflags); - if (status < 0) { - pr_err("setup of hog GPIO %s (chip %s, offset %d) failed, %d\n", - name, chip->label, hwnum, status); - gpiochip_free_own_desc(desc); - return status; - } - /* Mark GPIO as hogged so it can be identified and removed later */ set_bit(FLAG_IS_HOGGED, &desc->flags); @@ -4805,8 +4802,8 @@ static const struct file_operations gpiolib_operations = { static int __init gpiolib_debugfs_init(void) { /* /sys/kernel/debug/gpio */ - (void) debugfs_create_file("gpio", S_IFREG | S_IRUGO, - NULL, NULL, &gpiolib_operations); + debugfs_create_file("gpio", S_IFREG | S_IRUGO, NULL, NULL, + &gpiolib_operations); return 0; } subsys_initcall(gpiolib_debugfs_init); |