diff options
Diffstat (limited to 'drivers/gpio')
55 files changed, 1042 insertions, 1038 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index acd40eb51c46..bb13c266c329 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -62,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 @@ -178,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. @@ -493,7 +489,8 @@ config GPIO_STA2X11 config GPIO_STP_XWAY bool "XWAY STP GPIOs" - depends on SOC_XWAY + depends on SOC_XWAY || COMPILE_TEST + depends on OF_GPIO help This enables support for the Serial To Parallel (STP) unit found on XWAY SoC. The STP allows the SoC to drive a shift registers cascade, @@ -602,7 +599,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 @@ -979,6 +975,17 @@ config GPIO_ARIZONA help Support for GPIOs on Wolfson Arizona class devices. +config GPIO_BD70528 + tristate "ROHM BD70528 GPIO support" + depends on MFD_ROHM_BD70528 + help + Support for GPIOs on ROHM BD70528 PMIC. There are four GPIOs + available on the ROHM PMIC in total. The GPIOs can also + generate interrupts. + + This driver can also be built as a module. If so, the module + will be called gpio-bd70528. + config GPIO_BD9571MWV tristate "ROHM BD9571 GPIO support" depends on MFD_BD9571MWV @@ -1305,7 +1312,7 @@ config GPIO_BT8XX The card needs to be physically altered for using it as a GPIO card. For more information on how to build a GPIO card from a BT8xx TV card, see the documentation file at - Documentation/bt8xxgpio.txt + Documentation/driver-api/bt8xxgpio.rst If unsure, say N. diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 6700eee860b7..a4e91175c708 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -17,154 +17,155 @@ 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_BD70528) += gpio-bd70528.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-adnp.c b/drivers/gpio/gpio-adnp.c index 12acdac85820..b9fcaab2a931 100644 --- a/drivers/gpio/gpio-adnp.c +++ b/drivers/gpio/gpio-adnp.c @@ -1,9 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2011-2012 Avionic Design GmbH - * - * 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/gpio/driver.h> diff --git a/drivers/gpio/gpio-altera.c b/drivers/gpio/gpio-altera.c index e088b908c2c1..9f2e6b04c361 100644 --- a/drivers/gpio/gpio-altera.c +++ b/drivers/gpio/gpio-altera.c @@ -30,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) @@ -101,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; @@ -246,6 +238,7 @@ static int altera_gpio_probe(struct platform_device *pdev) struct device_node *node = pdev->dev.of_node; int reg, ret; struct altera_gpio_chip *altera_gc; + struct gpio_irq_chip *girq; altera_gc = devm_kzalloc(&pdev->dev, sizeof(*altera_gc), GFP_KERNEL); if (!altera_gc) @@ -273,50 +266,50 @@ static int altera_gpio_probe(struct platform_device *pdev) altera_gc->mmchip.gc.owner = THIS_MODULE; altera_gc->mmchip.gc.parent = &pdev->dev; - ret = of_mm_gpiochip_add_data(node, &altera_gc->mmchip, altera_gc); - if (ret) { - dev_err(&pdev->dev, "Failed adding memory mapped gpiochip\n"); - return ret; - } - - platform_set_drvdata(pdev, altera_gc); - altera_gc->mapped_irq = platform_get_irq(pdev, 0); if (altera_gc->mapped_irq < 0) goto skip_irq; if (of_property_read_u32(node, "altr,interrupt-type", ®)) { - ret = -EINVAL; dev_err(&pdev->dev, "altr,interrupt-type value not set in device tree\n"); - goto teardown; + return -EINVAL; } 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; + + girq = &altera_gc->mmchip.gc.irq; + girq->chip = &altera_gc->irq_chip; + if (altera_gc->interrupt_trigger == IRQ_TYPE_LEVEL_HIGH) + girq->parent_handler = altera_gpio_irq_leveL_high_handler; + else + girq->parent_handler = altera_gpio_irq_edge_handler; + girq->num_parents = 1; + girq->parents = devm_kcalloc(&pdev->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] = altera_gc->mapped_irq; +skip_irq: + ret = of_mm_gpiochip_add_data(node, &altera_gc->mmchip, altera_gc); if (ret) { - dev_err(&pdev->dev, "could not add irqchip\n"); - goto teardown; + dev_err(&pdev->dev, "Failed adding memory mapped gpiochip\n"); + return ret; } - gpiochip_set_chained_irqchip(&altera_gc->mmchip.gc, - &altera_irq_chip, - altera_gc->mapped_irq, - altera_gc->interrupt_trigger == IRQ_TYPE_LEVEL_HIGH ? - altera_gpio_irq_leveL_high_handler : - altera_gpio_irq_edge_handler); + platform_set_drvdata(pdev, altera_gc); -skip_irq: return 0; -teardown: - of_mm_gpiochip_remove(&altera_gc->mmchip); - pr_err("%pOF: registration failed with status %d\n", - node, ret); - - return ret; } static int altera_gpio_remove(struct platform_device *pdev) diff --git a/drivers/gpio/gpio-amd-fch.c b/drivers/gpio/gpio-amd-fch.c index 38c3f4a3d4aa..181df1581df5 100644 --- a/drivers/gpio/gpio-amd-fch.c +++ b/drivers/gpio/gpio-amd-fch.c @@ -25,14 +25,13 @@ #define AMD_FCH_GPIO_FLAG_WRITE BIT(22) #define AMD_FCH_GPIO_FLAG_READ BIT(16) -static struct resource amd_fch_gpio_iores = +static const struct resource amd_fch_gpio_iores = DEFINE_RES_MEM_NAMED( AMD_FCH_MMIO_BASE + AMD_FCH_GPIO_BANK0_BASE, AMD_FCH_GPIO_SIZE, "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..44398992ae15 100644 --- a/drivers/gpio/gpio-amdpt.c +++ b/drivers/gpio/gpio-amdpt.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * AMD Promontory GPIO driver * * Copyright (C) 2015 ASMedia Technology Inc. * Author: YD Tseng <yd_tseng@asmedia.com.tw> - * - * 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/kernel.h> @@ -91,7 +88,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 +98,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 +107,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 +121,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-ath79.c b/drivers/gpio/gpio-ath79.c index 0a553d676042..f1a5ea9b3de2 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Atheros AR71XX/AR724X/AR913X GPIO API support * @@ -5,10 +6,6 @@ * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> - * - * 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/gpio/driver.h> @@ -225,14 +222,16 @@ MODULE_DEVICE_TABLE(of, ath79_gpio_of_match); static int ath79_gpio_probe(struct platform_device *pdev) { struct ath79_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; struct ath79_gpio_ctrl *ctrl; + struct gpio_irq_chip *girq; struct resource *res; u32 ath79_gpio_count; bool oe_inverted; int err; - ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL); + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); if (!ctrl) return -ENOMEM; platform_set_drvdata(pdev, ctrl); @@ -240,7 +239,7 @@ static int ath79_gpio_probe(struct platform_device *pdev) if (np) { err = of_property_read_u32(np, "ngpios", &ath79_gpio_count); if (err) { - dev_err(&pdev->dev, "ngpios property is not valid\n"); + dev_err(dev, "ngpios property is not valid\n"); return err; } oe_inverted = of_device_is_compatible(np, "qca,ar9340-gpio"); @@ -248,25 +247,24 @@ static int ath79_gpio_probe(struct platform_device *pdev) ath79_gpio_count = pdata->ngpios; oe_inverted = pdata->oe_inverted; } else { - dev_err(&pdev->dev, "No DT node or platform data found\n"); + dev_err(dev, "No DT node or platform data found\n"); return -EINVAL; } if (ath79_gpio_count >= 32) { - dev_err(&pdev->dev, "ngpios must be less than 32\n"); + dev_err(dev, "ngpios must be less than 32\n"); return -EINVAL; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -EINVAL; - ctrl->base = devm_ioremap_nocache( - &pdev->dev, res->start, resource_size(res)); + ctrl->base = devm_ioremap_nocache(dev, res->start, resource_size(res)); if (!ctrl->base) return -ENOMEM; raw_spin_lock_init(&ctrl->lock); - err = bgpio_init(&ctrl->gc, &pdev->dev, 4, + err = bgpio_init(&ctrl->gc, dev, 4, ctrl->base + AR71XX_GPIO_REG_IN, ctrl->base + AR71XX_GPIO_REG_SET, ctrl->base + AR71XX_GPIO_REG_CLEAR, @@ -274,45 +272,33 @@ static int ath79_gpio_probe(struct platform_device *pdev) oe_inverted ? ctrl->base + AR71XX_GPIO_REG_OE : NULL, 0); if (err) { - dev_err(&pdev->dev, "bgpio_init failed\n"); + dev_err(dev, "bgpio_init failed\n"); return err; } /* Use base 0 to stay compatible with legacy platforms */ ctrl->gc.base = 0; - err = gpiochip_add_data(&ctrl->gc, ctrl); - if (err) { - dev_err(&pdev->dev, - "cannot add AR71xx GPIO chip, error=%d", err); - return err; + /* Optional interrupt setup */ + if (!np || of_property_read_bool(np, "interrupt-controller")) { + girq = &ctrl->gc.irq; + girq->chip = &ath79_gpio_irqchip; + girq->parent_handler = ath79_gpio_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] = platform_get_irq(pdev, 0); + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; } - if (np && !of_property_read_bool(np, "interrupt-controller")) - return 0; - - err = gpiochip_irqchip_add(&ctrl->gc, &ath79_gpio_irqchip, 0, - handle_simple_irq, IRQ_TYPE_NONE); + err = devm_gpiochip_add_data(dev, &ctrl->gc, ctrl); if (err) { - dev_err(&pdev->dev, "failed to add gpiochip_irqchip\n"); - goto gpiochip_remove; + dev_err(dev, + "cannot add AR71xx GPIO chip, error=%d", err); + return err; } - - gpiochip_set_chained_irqchip(&ctrl->gc, &ath79_gpio_irqchip, - platform_get_irq(pdev, 0), - ath79_gpio_irq_handler); - - return 0; - -gpiochip_remove: - gpiochip_remove(&ctrl->gc); - return err; -} - -static int ath79_gpio_remove(struct platform_device *pdev) -{ - struct ath79_gpio_ctrl *ctrl = platform_get_drvdata(pdev); - - gpiochip_remove(&ctrl->gc); return 0; } @@ -322,7 +308,6 @@ static struct platform_driver ath79_gpio_driver = { .of_match_table = ath79_gpio_of_match, }, .probe = ath79_gpio_probe, - .remove = ath79_gpio_remove, }; module_platform_driver(ath79_gpio_driver); diff --git a/drivers/gpio/gpio-bd70528.c b/drivers/gpio/gpio-bd70528.c new file mode 100644 index 000000000000..fd85605d2dab --- /dev/null +++ b/drivers/gpio/gpio-bd70528.c @@ -0,0 +1,232 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 ROHM Semiconductors +// gpio-bd70528.c ROHM BD70528MWV gpio driver + +#include <linux/gpio/driver.h> +#include <linux/mfd/rohm-bd70528.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#define GPIO_IN_REG(offset) (BD70528_REG_GPIO1_IN + (offset) * 2) +#define GPIO_OUT_REG(offset) (BD70528_REG_GPIO1_OUT + (offset) * 2) + +struct bd70528_gpio { + struct rohm_regmap_dev chip; + struct gpio_chip gpio; +}; + +static int bd70528_set_debounce(struct bd70528_gpio *bdgpio, + unsigned int offset, unsigned int debounce) +{ + u8 val; + + switch (debounce) { + case 0: + val = BD70528_DEBOUNCE_DISABLE; + break; + case 1 ... 15: + val = BD70528_DEBOUNCE_15MS; + break; + case 16 ... 30: + val = BD70528_DEBOUNCE_30MS; + break; + case 31 ... 50: + val = BD70528_DEBOUNCE_50MS; + break; + default: + dev_err(bdgpio->chip.dev, + "Invalid debouce value %u\n", debounce); + return -EINVAL; + } + return regmap_update_bits(bdgpio->chip.regmap, GPIO_IN_REG(offset), + BD70528_DEBOUNCE_MASK, val); +} + +static int bd70528_get_direction(struct gpio_chip *chip, unsigned int offset) +{ + struct bd70528_gpio *bdgpio = gpiochip_get_data(chip); + int val, ret; + + /* Do we need to do something to IRQs here? */ + ret = regmap_read(bdgpio->chip.regmap, GPIO_OUT_REG(offset), &val); + if (ret) { + dev_err(bdgpio->chip.dev, "Could not read gpio direction\n"); + return ret; + } + + return !(val & BD70528_GPIO_OUT_EN_MASK); +} + +static int bd70528_gpio_set_config(struct gpio_chip *chip, unsigned int offset, + unsigned long config) +{ + struct bd70528_gpio *bdgpio = gpiochip_get_data(chip); + + switch (pinconf_to_config_param(config)) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + return regmap_update_bits(bdgpio->chip.regmap, + GPIO_OUT_REG(offset), + BD70528_GPIO_DRIVE_MASK, + BD70528_GPIO_OPEN_DRAIN); + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + return regmap_update_bits(bdgpio->chip.regmap, + GPIO_OUT_REG(offset), + BD70528_GPIO_DRIVE_MASK, + BD70528_GPIO_PUSH_PULL); + break; + case PIN_CONFIG_INPUT_DEBOUNCE: + return bd70528_set_debounce(bdgpio, offset, + pinconf_to_config_argument(config)); + break; + default: + break; + } + return -ENOTSUPP; +} + +static int bd70528_direction_input(struct gpio_chip *chip, unsigned int offset) +{ + struct bd70528_gpio *bdgpio = gpiochip_get_data(chip); + + /* Do we need to do something to IRQs here? */ + return regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset), + BD70528_GPIO_OUT_EN_MASK, + BD70528_GPIO_OUT_DISABLE); +} + +static void bd70528_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + int ret; + struct bd70528_gpio *bdgpio = gpiochip_get_data(chip); + u8 val = (value) ? BD70528_GPIO_OUT_HI : BD70528_GPIO_OUT_LO; + + ret = regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset), + BD70528_GPIO_OUT_MASK, val); + if (ret) + dev_err(bdgpio->chip.dev, "Could not set gpio to %d\n", value); +} + +static int bd70528_direction_output(struct gpio_chip *chip, unsigned int offset, + int value) +{ + struct bd70528_gpio *bdgpio = gpiochip_get_data(chip); + + bd70528_gpio_set(chip, offset, value); + return regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset), + BD70528_GPIO_OUT_EN_MASK, + BD70528_GPIO_OUT_ENABLE); +} + +#define GPIO_IN_STATE_MASK(offset) (BD70528_GPIO_IN_STATE_BASE << (offset)) + +static int bd70528_gpio_get_o(struct bd70528_gpio *bdgpio, unsigned int offset) +{ + int ret; + unsigned int val; + + ret = regmap_read(bdgpio->chip.regmap, GPIO_OUT_REG(offset), &val); + if (!ret) + ret = !!(val & BD70528_GPIO_OUT_MASK); + else + dev_err(bdgpio->chip.dev, "GPIO (out) state read failed\n"); + + return ret; +} + +static int bd70528_gpio_get_i(struct bd70528_gpio *bdgpio, unsigned int offset) +{ + unsigned int val; + int ret; + + ret = regmap_read(bdgpio->chip.regmap, BD70528_REG_GPIO_STATE, &val); + + if (!ret) + ret = !(val & GPIO_IN_STATE_MASK(offset)); + else + dev_err(bdgpio->chip.dev, "GPIO (in) state read failed\n"); + + return ret; +} + +static int bd70528_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + int ret = -EINVAL; + struct bd70528_gpio *bdgpio = gpiochip_get_data(chip); + + /* + * There is a race condition where someone might be changing the + * GPIO direction after we get it but before we read the value. But + * application design where GPIO direction may be changed just when + * we read GPIO value would be pointless as reader could not know + * whether the returned high/low state is caused by input or output. + * Or then there must be other ways to mitigate the issue. Thus + * locking would make no sense. + */ + ret = bd70528_get_direction(chip, offset); + if (ret == 0) + ret = bd70528_gpio_get_o(bdgpio, offset); + else if (ret == 1) + ret = bd70528_gpio_get_i(bdgpio, offset); + else + dev_err(bdgpio->chip.dev, "failed to read GPIO direction\n"); + + return ret; +} + +static int bd70528_probe(struct platform_device *pdev) +{ + struct bd70528_gpio *bdgpio; + struct rohm_regmap_dev *bd70528; + int ret; + + bd70528 = dev_get_drvdata(pdev->dev.parent); + if (!bd70528) { + dev_err(&pdev->dev, "No MFD driver data\n"); + return -EINVAL; + } + + bdgpio = devm_kzalloc(&pdev->dev, sizeof(*bdgpio), + GFP_KERNEL); + if (!bdgpio) + return -ENOMEM; + bdgpio->chip.dev = &pdev->dev; + bdgpio->gpio.parent = pdev->dev.parent; + bdgpio->gpio.label = "bd70528-gpio"; + bdgpio->gpio.owner = THIS_MODULE; + bdgpio->gpio.get_direction = bd70528_get_direction; + bdgpio->gpio.direction_input = bd70528_direction_input; + bdgpio->gpio.direction_output = bd70528_direction_output; + bdgpio->gpio.set_config = bd70528_gpio_set_config; + bdgpio->gpio.can_sleep = true; + bdgpio->gpio.get = bd70528_gpio_get; + bdgpio->gpio.set = bd70528_gpio_set; + bdgpio->gpio.ngpio = 4; + bdgpio->gpio.base = -1; +#ifdef CONFIG_OF_GPIO + bdgpio->gpio.of_node = pdev->dev.parent->of_node; +#endif + bdgpio->chip.regmap = bd70528->regmap; + + ret = devm_gpiochip_add_data(&pdev->dev, &bdgpio->gpio, + bdgpio); + if (ret) + dev_err(&pdev->dev, "gpio_init: Failed to add bd70528-gpio\n"); + + return ret; +} + +static struct platform_driver bd70528_gpio = { + .driver = { + .name = "bd70528-gpio" + }, + .probe = bd70528_probe, +}; + +module_platform_driver(bd70528_gpio); + +MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); +MODULE_DESCRIPTION("BD70528 voltage regulator driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-cs5535.c b/drivers/gpio/gpio-cs5535.c index 6314225dbed0..53b24e3ae7de 100644 --- a/drivers/gpio/gpio-cs5535.c +++ b/drivers/gpio/gpio-cs5535.c @@ -41,7 +41,7 @@ MODULE_PARM_DESC(mask, "GPIO channel mask."); /* * FIXME: convert this singleton driver to use the state container - * design pattern, see Documentation/driver-model/design-patterns.txt + * design pattern, see Documentation/driver-api/driver-model/design-patterns.rst */ static struct cs5535_gpio_chip { struct gpio_chip chip; diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 3bbf5804bd11..e0b025689625 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -238,8 +238,9 @@ static int davinci_gpio_probe(struct platform_device *pdev) for (i = 0; i < nirq; i++) { chips->irqs[i] = platform_get_irq(pdev, i); if (chips->irqs[i] < 0) { - dev_info(dev, "IRQ not populated, err = %d\n", - chips->irqs[i]); + if (chips->irqs[i] != -EPROBE_DEFER) + dev_info(dev, "IRQ not populated, err = %d\n", + chips->irqs[i]); return chips->irqs[i]; } } @@ -297,7 +298,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); @@ -306,7 +307,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; @@ -447,7 +448,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; } @@ -632,6 +633,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-dwapb.c b/drivers/gpio/gpio-dwapb.c index d3eda65fd6d3..3108be5e208c 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -1,10 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2011 Jamie Iles * - * 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. - * * All enquiries to support@picochip.com */ #include <linux/acpi.h> 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-em.c b/drivers/gpio/gpio-em.c index 84a7375cee0a..a87951293aaa 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -259,6 +259,13 @@ static const struct irq_domain_ops em_gio_irq_domain_ops = { .xlate = irq_domain_xlate_twocell, }; +static void em_gio_irq_domain_remove(void *data) +{ + struct irq_domain *domain = data; + + irq_domain_remove(domain); +} + static int em_gio_probe(struct platform_device *pdev) { struct em_gio_priv *p; @@ -270,10 +277,8 @@ static int em_gio_probe(struct platform_device *pdev) int ret; p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); - if (!p) { - ret = -ENOMEM; - goto err0; - } + if (!p) + return -ENOMEM; p->pdev = pdev; platform_set_drvdata(pdev, p); @@ -286,30 +291,22 @@ static int em_gio_probe(struct platform_device *pdev) if (!io[0] || !io[1] || !irq[0] || !irq[1]) { dev_err(&pdev->dev, "missing IRQ or IOMEM\n"); - ret = -EINVAL; - goto err0; + return -EINVAL; } p->base0 = devm_ioremap_nocache(&pdev->dev, io[0]->start, resource_size(io[0])); - if (!p->base0) { - dev_err(&pdev->dev, "failed to remap low I/O memory\n"); - ret = -ENXIO; - goto err0; - } + if (!p->base0) + return -ENOMEM; p->base1 = devm_ioremap_nocache(&pdev->dev, io[1]->start, resource_size(io[1])); - if (!p->base1) { - dev_err(&pdev->dev, "failed to remap high I/O memory\n"); - ret = -ENXIO; - goto err0; - } + if (!p->base1) + return -ENOMEM; if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) { dev_err(&pdev->dev, "Missing ngpios OF property\n"); - ret = -EINVAL; - goto err0; + return -EINVAL; } gpio_chip = &p->gpio_chip; @@ -339,47 +336,34 @@ static int em_gio_probe(struct platform_device *pdev) p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, ngpios, 0, &em_gio_irq_domain_ops, p); if (!p->irq_domain) { - ret = -ENXIO; dev_err(&pdev->dev, "cannot initialize irq domain\n"); - goto err0; + return -ENXIO; } + ret = devm_add_action_or_reset(&pdev->dev, em_gio_irq_domain_remove, + p->irq_domain); + if (ret) + return ret; + if (devm_request_irq(&pdev->dev, irq[0]->start, em_gio_irq_handler, 0, name, p)) { dev_err(&pdev->dev, "failed to request low IRQ\n"); - ret = -ENOENT; - goto err1; + return -ENOENT; } if (devm_request_irq(&pdev->dev, irq[1]->start, em_gio_irq_handler, 0, name, p)) { dev_err(&pdev->dev, "failed to request high IRQ\n"); - ret = -ENOENT; - goto err1; + return -ENOENT; } - ret = gpiochip_add_data(gpio_chip, p); + ret = devm_gpiochip_add_data(&pdev->dev, gpio_chip, p); if (ret) { dev_err(&pdev->dev, "failed to add GPIO controller\n"); - goto err1; + return ret; } return 0; - -err1: - irq_domain_remove(p->irq_domain); -err0: - return ret; -} - -static int em_gio_remove(struct platform_device *pdev) -{ - struct em_gio_priv *p = platform_get_drvdata(pdev); - - gpiochip_remove(&p->gpio_chip); - - irq_domain_remove(p->irq_domain); - return 0; } static const struct of_device_id em_gio_dt_ids[] = { @@ -390,7 +374,6 @@ MODULE_DEVICE_TABLE(of, em_gio_dt_ids); static struct platform_driver em_gio_device_driver = { .probe = em_gio_probe, - .remove = em_gio_remove, .driver = { .name = "em_gio", .of_match_table = em_gio_dt_ids, 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-exar.c b/drivers/gpio/gpio-exar.c index a09d2f9ebacc..fae327d5b06e 100644 --- a/drivers/gpio/gpio-exar.c +++ b/drivers/gpio/gpio-exar.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * GPIO driver for Exar XR17V35X chip * * Copyright (C) 2015 Sudip Mukherjee <sudip.mukherjee@codethink.co.uk> - * - * 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/bitops.h> #include <linux/device.h> 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 7df48e76baea..0937b605e134 100644 --- a/drivers/gpio/gpio-grgpio.c +++ b/drivers/gpio/gpio-grgpio.c @@ -329,7 +329,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; @@ -340,8 +339,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-iop.c b/drivers/gpio/gpio-iop.c index e355c5961eb9..7390b5ca09e3 100644 --- a/drivers/gpio/gpio-iop.c +++ b/drivers/gpio/gpio-iop.c @@ -36,6 +36,7 @@ static int iop3xx_gpio_probe(struct platform_device *pdev) gc->base = 0; gc->owner = THIS_MODULE; + gc->label = "gpio-iop"; return devm_gpiochip_add_data(&pdev->dev, gc, NULL); } 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 6b5b5a8b9173..cdf50e4ea165 100644 --- a/drivers/gpio/gpio-janz-ttl.c +++ b/drivers/gpio/gpio-janz-ttl.c @@ -140,18 +140,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; @@ -177,9 +176,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-madera.c b/drivers/gpio/gpio-madera.c index c9dad0543672..4dbc837d1215 100644 --- a/drivers/gpio/gpio-madera.c +++ b/drivers/gpio/gpio-madera.c @@ -1,12 +1,8 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * GPIO support for Cirrus Logic Madera codecs * * Copyright (C) 2015-2018 Cirrus Logic - * - * 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; version 2. */ #include <linux/gpio/driver.h> diff --git a/drivers/gpio/gpio-max3191x.c b/drivers/gpio/gpio-max3191x.c index 9a8876abeb57..4b4b2ceb82fc 100644 --- a/drivers/gpio/gpio-max3191x.c +++ b/drivers/gpio/gpio-max3191x.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * gpio-max3191x.c - GPIO driver for Maxim MAX3191x industrial serializer * @@ -27,10 +28,6 @@ * https://datasheets.maximintegrated.com/en/ds/MAX31912.pdf * https://datasheets.maximintegrated.com/en/ds/MAX31913.pdf * https://datasheets.maximintegrated.com/en/ds/MAX31953-MAX31963.pdf - * - * 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/bitmap.h> diff --git a/drivers/gpio/gpio-max7300.c b/drivers/gpio/gpio-max7300.c index 1ae9ba851c9a..19cc2ed6a3f5 100644 --- a/drivers/gpio/gpio-max7300.c +++ b/drivers/gpio/gpio-max7300.c @@ -1,10 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2009 Wolfram Sang, Pengutronix * - * 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. - * * Check max730x.c for further details. */ diff --git a/drivers/gpio/gpio-max7301.c b/drivers/gpio/gpio-max7301.c index 647dfbbc4e1c..1307c243b4e9 100644 --- a/drivers/gpio/gpio-max7301.c +++ b/drivers/gpio/gpio-max7301.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2006 Juergen Beisert, Pengutronix * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix * Copyright (C) 2009 Wolfram Sang, Pengutronix * - * 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. - * * Check max730x.c for further details. */ diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/gpio-max730x.c index 198a36b07773..1e1935c51096 100644 --- a/drivers/gpio/gpio-max730x.c +++ b/drivers/gpio/gpio-max730x.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /** * Copyright (C) 2006 Juergen Beisert, Pengutronix * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix * Copyright (C) 2009 Wolfram Sang, Pengutronix * - * 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. - * * The Maxim MAX7300/1 device is an I2C/SPI driven GPIO expander. There are * 28 GPIOs. 8 of them can trigger an interrupt. See datasheet for more * details diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c index 5e4102e7b1f9..5fb0bcf31142 100644 --- a/drivers/gpio/gpio-max732x.c +++ b/drivers/gpio/gpio-max732x.c @@ -649,12 +649,12 @@ static int max732x_probe(struct i2c_client *client, case 0x60: chip->client_group_a = client; if (nr_port > 8) { - c = i2c_new_dummy(client->adapter, addr_b); - if (!c) { + c = devm_i2c_new_dummy_device(&client->dev, + client->adapter, addr_b); + if (IS_ERR(c)) { dev_err(&client->dev, "Failed to allocate I2C device\n"); - ret = -ENODEV; - goto out_failed; + return PTR_ERR(c); } chip->client_group_b = chip->client_dummy = c; } @@ -662,12 +662,12 @@ static int max732x_probe(struct i2c_client *client, case 0x50: chip->client_group_b = client; if (nr_port > 8) { - c = i2c_new_dummy(client->adapter, addr_a); - if (!c) { + c = devm_i2c_new_dummy_device(&client->dev, + client->adapter, addr_a); + if (IS_ERR(c)) { dev_err(&client->dev, "Failed to allocate I2C device\n"); - ret = -ENODEV; - goto out_failed; + return PTR_ERR(c); } chip->client_group_a = chip->client_dummy = c; } @@ -675,37 +675,33 @@ static int max732x_probe(struct i2c_client *client, default: dev_err(&client->dev, "invalid I2C address specified %02x\n", client->addr); - ret = -EINVAL; - goto out_failed; + return -EINVAL; } if (nr_port > 8 && !chip->client_dummy) { dev_err(&client->dev, "Failed to allocate second group I2C device\n"); - ret = -ENODEV; - goto out_failed; + return -ENODEV; } mutex_init(&chip->lock); ret = max732x_readb(chip, is_group_a(chip, 0), &chip->reg_out[0]); if (ret) - goto out_failed; + return ret; if (nr_port > 8) { ret = max732x_readb(chip, is_group_a(chip, 8), &chip->reg_out[1]); if (ret) - goto out_failed; + return ret; } - ret = gpiochip_add_data(&chip->gpio_chip, chip); + ret = devm_gpiochip_add_data(&client->dev, &chip->gpio_chip, chip); if (ret) - goto out_failed; + return ret; ret = max732x_irq_setup(chip, id); - if (ret) { - gpiochip_remove(&chip->gpio_chip); - goto out_failed; - } + if (ret) + return ret; if (pdata && pdata->setup) { ret = pdata->setup(client, chip->gpio_chip.base, @@ -716,10 +712,6 @@ static int max732x_probe(struct i2c_client *client, i2c_set_clientdata(client, chip); return 0; - -out_failed: - i2c_unregister_device(chip->client_dummy); - return ret; } static int max732x_remove(struct i2c_client *client) @@ -739,11 +731,6 @@ static int max732x_remove(struct i2c_client *client) } } - gpiochip_remove(&chip->gpio_chip); - - /* unregister any dummy i2c_client */ - i2c_unregister_device(chip->client_dummy); - return 0; } diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c index 9bfff171f9fe..8f466993cd24 100644 --- a/drivers/gpio/gpio-mb86s7x.c +++ b/drivers/gpio/gpio-mb86s7x.c @@ -6,6 +6,7 @@ * Copyright (C) 2015 Linaro Ltd. */ +#include <linux/acpi.h> #include <linux/io.h> #include <linux/init.h> #include <linux/clk.h> @@ -19,6 +20,8 @@ #include <linux/spinlock.h> #include <linux/slab.h> +#include "gpiolib.h" + /* * Only first 8bits of a register correspond to each pin, * so there are 4 registers for 32 pins. @@ -135,6 +138,20 @@ static void mb86s70_gpio_set(struct gpio_chip *gc, unsigned gpio, int value) spin_unlock_irqrestore(&gchip->lock, flags); } +static int mb86s70_gpio_to_irq(struct gpio_chip *gc, unsigned int offset) +{ + int irq, index; + + for (index = 0;; index++) { + irq = platform_get_irq(to_platform_device(gc->parent), index); + if (irq <= 0) + break; + if (irq_get_irq_data(irq)->hwirq == offset) + return irq; + } + return -EINVAL; +} + static int mb86s70_gpio_probe(struct platform_device *pdev) { struct mb86s70_gpio_chip *gchip; @@ -150,13 +167,15 @@ static int mb86s70_gpio_probe(struct platform_device *pdev) if (IS_ERR(gchip->base)) return PTR_ERR(gchip->base); - gchip->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(gchip->clk)) - return PTR_ERR(gchip->clk); + if (!has_acpi_companion(&pdev->dev)) { + gchip->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(gchip->clk)) + return PTR_ERR(gchip->clk); - ret = clk_prepare_enable(gchip->clk); - if (ret) - return ret; + ret = clk_prepare_enable(gchip->clk); + if (ret) + return ret; + } spin_lock_init(&gchip->lock); @@ -172,19 +191,28 @@ static int mb86s70_gpio_probe(struct platform_device *pdev) gchip->gc.parent = &pdev->dev; gchip->gc.base = -1; + if (has_acpi_companion(&pdev->dev)) + gchip->gc.to_irq = mb86s70_gpio_to_irq; + ret = gpiochip_add_data(&gchip->gc, gchip); if (ret) { dev_err(&pdev->dev, "couldn't register gpio driver\n"); clk_disable_unprepare(gchip->clk); + return ret; } - return ret; + if (has_acpi_companion(&pdev->dev)) + acpi_gpiochip_request_interrupts(&gchip->gc); + + return 0; } static int mb86s70_gpio_remove(struct platform_device *pdev) { struct mb86s70_gpio_chip *gchip = platform_get_drvdata(pdev); + if (has_acpi_companion(&pdev->dev)) + acpi_gpiochip_free_interrupts(&gchip->gc); gpiochip_remove(&gchip->gc); clk_disable_unprepare(gchip->clk); @@ -197,10 +225,19 @@ static const struct of_device_id mb86s70_gpio_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, mb86s70_gpio_dt_ids); +#ifdef CONFIG_ACPI +static const struct acpi_device_id mb86s70_gpio_acpi_ids[] = { + { "SCX0007" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(acpi, mb86s70_gpio_acpi_ids); +#endif + static struct platform_driver mb86s70_gpio_driver = { .driver = { .name = "mb86s70-gpio", .of_match_table = mb86s70_gpio_dt_ids, + .acpi_match_table = ACPI_PTR(mb86s70_gpio_acpi_ids), }, .probe = mb86s70_gpio_probe, .remove = mb86s70_gpio_remove, diff --git a/drivers/gpio/gpio-mm-lantiq.c b/drivers/gpio/gpio-mm-lantiq.c index b0754fe69e77..f460d71b0c92 100644 --- a/drivers/gpio/gpio-mm-lantiq.c +++ b/drivers/gpio/gpio-mm-lantiq.c @@ -1,7 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0-only /* - * 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. * * Copyright (C) 2012 John Crispin <john@phrozen.org> */ diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index b6a4efce7c92..f1a9c0544e3f 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -315,7 +315,6 @@ static void gpio_mockup_debugfs_setup(struct device *dev, struct gpio_mockup_chip *chip) { struct gpio_mockup_dbgfs_private *priv; - struct dentry *evfile; struct gpio_chip *gc; const char *devname; char *name; @@ -325,32 +324,25 @@ static void gpio_mockup_debugfs_setup(struct device *dev, devname = dev_name(&gc->gpiodev->dev); chip->dbg_dir = debugfs_create_dir(devname, gpio_mockup_dbg_dir); - if (IS_ERR_OR_NULL(chip->dbg_dir)) - goto err; for (i = 0; i < gc->ngpio; i++) { name = devm_kasprintf(dev, GFP_KERNEL, "%d", i); if (!name) - goto err; + return; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) - goto err; + return; priv->chip = chip; priv->offset = i; priv->desc = &gc->gpiodev->descs[i]; - evfile = debugfs_create_file(name, 0200, chip->dbg_dir, priv, - &gpio_mockup_debugfs_ops); - if (IS_ERR_OR_NULL(evfile)) - goto err; + debugfs_create_file(name, 0200, chip->dbg_dir, priv, + &gpio_mockup_debugfs_ops); } return; - -err: - dev_err(dev, "error creating debugfs files\n"); } static int gpio_mockup_name_lines(struct device *dev, @@ -447,8 +439,7 @@ static int gpio_mockup_probe(struct platform_device *pdev) if (rv) return rv; - if (!IS_ERR_OR_NULL(gpio_mockup_dbg_dir)) - gpio_mockup_debugfs_setup(dev, chip); + gpio_mockup_debugfs_setup(dev, chip); return 0; } @@ -501,8 +492,6 @@ static int __init gpio_mockup_init(void) } gpio_mockup_dbg_dir = debugfs_create_dir("gpio-mockup", NULL); - if (IS_ERR_OR_NULL(gpio_mockup_dbg_dir)) - gpio_mockup_err("error creating debugfs directory\n"); err = platform_driver_register(&gpio_mockup_driver); if (err) { 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..d0f27084a942 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Support functions for OMAP GPIO * @@ -6,10 +7,6 @@ * * Copyright (C) 2009 Texas Instruments * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.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> @@ -47,8 +44,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 +73,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 +89,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 +133,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 +178,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 +194,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 +273,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 +283,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 +297,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 +313,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 +363,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 +391,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 +501,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 +544,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 +556,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 +576,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 +630,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 +637,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 +647,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 +670,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 +677,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 +690,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 +697,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 +769,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 +823,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 +851,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 +917,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 +958,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 +1023,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 +1055,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 +1067,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 +1127,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 +1257,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 +1280,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 +1289,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 +1366,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 +1410,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 +1469,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 cfe827cefad8..378b206d2dc9 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -1178,6 +1178,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-pl061.c b/drivers/gpio/gpio-pl061.c index dc42571e6fdc..722ce5cf861e 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2008, 2009 Provigent Ltd. * * Author: Baruch Siach <baruch@tkos.co.il> * - * 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. - * * Driver for the ARM PrimeCell(tm) General Purpose Input/Output (PL061) * * Data sheet: ARM DDI 0190B, September 2000 @@ -286,6 +283,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 +311,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 +329,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 registered\n"); return 0; } diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 26f77fdb217e..9888b62f37af 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * linux/arch/arm/plat-pxa/gpio.c * @@ -6,10 +7,6 @@ * Author: Nicolas Pitre * Created: Jun 15, 2001 * Copyright: MontaVista Software Inc. - * - * 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/module.h> #include <linux/clk.h> 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-reg.c b/drivers/gpio/gpio-reg.c index e85903eddc68..fdc7a9d5b382 100644 --- a/drivers/gpio/gpio-reg.c +++ b/drivers/gpio/gpio-reg.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * gpio-reg: single register individually fixed-direction GPIOs * * Copyright (C) 2016 Russell King - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. */ #include <linux/gpio/driver.h> #include <linux/gpio/gpio-reg.h> diff --git a/drivers/gpio/gpio-sa1100.c b/drivers/gpio/gpio-sa1100.c index 986eb3b231ac..46b7cf23fb0f 100644 --- a/drivers/gpio/gpio-sa1100.c +++ b/drivers/gpio/gpio-sa1100.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * linux/arch/arm/mach-sa1100/gpio.c * * Generic SA-1100 GPIO handling - * - * 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/gpio/driver.h> #include <linux/init.h> diff --git a/drivers/gpio/gpio-siox.c b/drivers/gpio/gpio-siox.c index 571b2a81c6de..006a7e6a75f2 100644 --- a/drivers/gpio/gpio-siox.c +++ b/drivers/gpio/gpio-siox.c @@ -211,20 +211,22 @@ static int gpio_siox_get_direction(struct gpio_chip *chip, unsigned int offset) static int gpio_siox_probe(struct siox_device *sdevice) { struct gpio_siox_ddata *ddata; + struct gpio_irq_chip *girq; + struct device *dev = &sdevice->dev; int ret; - ddata = devm_kzalloc(&sdevice->dev, sizeof(*ddata), GFP_KERNEL); + ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL); if (!ddata) return -ENOMEM; - dev_set_drvdata(&sdevice->dev, ddata); + dev_set_drvdata(dev, ddata); mutex_init(&ddata->lock); spin_lock_init(&ddata->irqlock); ddata->gchip.base = -1; ddata->gchip.can_sleep = 1; - ddata->gchip.parent = &sdevice->dev; + ddata->gchip.parent = dev; ddata->gchip.owner = THIS_MODULE; ddata->gchip.get = gpio_siox_get; ddata->gchip.set = gpio_siox_set; @@ -239,54 +241,27 @@ static int gpio_siox_probe(struct siox_device *sdevice) ddata->ichip.irq_unmask = gpio_siox_irq_unmask; ddata->ichip.irq_set_type = gpio_siox_irq_set_type; - ret = gpiochip_add(&ddata->gchip); - if (ret) { - dev_err(&sdevice->dev, - "Failed to register gpio chip (%d)\n", ret); - goto err_gpiochip; - } + girq = &ddata->gchip.irq; + girq->chip = &ddata->ichip; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_level_irq; - ret = gpiochip_irqchip_add(&ddata->gchip, &ddata->ichip, - 0, handle_level_irq, IRQ_TYPE_EDGE_RISING); - if (ret) { - dev_err(&sdevice->dev, - "Failed to register irq chip (%d)\n", ret); -err_gpiochip: - gpiochip_remove(&ddata->gchip); - } + ret = devm_gpiochip_add_data(dev, &ddata->gchip, NULL); + if (ret) + dev_err(dev, "Failed to register gpio chip (%d)\n", ret); return ret; } -static int gpio_siox_remove(struct siox_device *sdevice) -{ - struct gpio_siox_ddata *ddata = dev_get_drvdata(&sdevice->dev); - - gpiochip_remove(&ddata->gchip); - return 0; -} - static struct siox_driver gpio_siox_driver = { .probe = gpio_siox_probe, - .remove = gpio_siox_remove, .set_data = gpio_siox_set_data, .get_data = gpio_siox_get_data, .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-stmpe.c b/drivers/gpio/gpio-stmpe.c index 65a2315f1673..dbf9cbe36b2b 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c @@ -1,7 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) ST-Ericsson SA 2010 * - * License Terms: GNU General Public License, version 2 * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson */ diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c index 8a319d56c5de..9e23a5ae8108 100644 --- a/drivers/gpio/gpio-stp-xway.c +++ b/drivers/gpio/gpio-stp-xway.c @@ -1,10 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-only /* - * 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. * * Copyright (C) 2012 John Crispin <john@phrozen.org> - * */ #include <linux/slab.h> @@ -18,8 +15,6 @@ #include <linux/clk.h> #include <linux/err.h> -#include <lantiq_soc.h> - /* * The Serial To Parallel (STP) is found on MIPS based Lantiq socs. It is a * peripheral controller used to drive external shift register cascades. At most @@ -74,8 +69,7 @@ #define xway_stp_r32(m, reg) __raw_readl(m + reg) #define xway_stp_w32(m, val, reg) __raw_writel(val, m + reg) #define xway_stp_w32_mask(m, clear, set, reg) \ - ltq_w32((ltq_r32(m + reg) & ~(clear)) | (set), \ - m + reg) + xway_stp_w32(m, (xway_stp_r32(m, reg) & ~(clear)) | (set), reg) struct xway_stp { struct gpio_chip gc; @@ -159,9 +153,9 @@ static int xway_stp_request(struct gpio_chip *gc, unsigned gpio) /** * xway_stp_hw_init() - Configure the STP unit and enable the clock gate - * @virt: pointer to the remapped register range + * @chip: Pointer to the xway_stp chip structure */ -static int xway_stp_hw_init(struct xway_stp *chip) +static void xway_stp_hw_init(struct xway_stp *chip) { /* sane defaults */ xway_stp_w32(chip->virt, 0, XWAY_STP_AR); @@ -204,8 +198,6 @@ static int xway_stp_hw_init(struct xway_stp *chip) if (chip->reserved) xway_stp_w32_mask(chip->virt, XWAY_STP_UPD_MASK, XWAY_STP_UPD_FPI, XWAY_STP_CON1); - - return 0; } static int xway_stp_probe(struct platform_device *pdev) @@ -261,21 +253,27 @@ static int xway_stp_probe(struct platform_device *pdev) if (!of_find_property(pdev->dev.of_node, "lantiq,rising", NULL)) chip->edge = XWAY_STP_FALLING; - clk = clk_get(&pdev->dev, NULL); + clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(clk)) { dev_err(&pdev->dev, "Failed to get clock\n"); return PTR_ERR(clk); } - clk_enable(clk); - ret = xway_stp_hw_init(chip); - if (!ret) - ret = devm_gpiochip_add_data(&pdev->dev, &chip->gc, chip); + ret = clk_prepare_enable(clk); + if (ret) + return ret; - if (!ret) - dev_info(&pdev->dev, "Init done\n"); + xway_stp_hw_init(chip); - return ret; + ret = devm_gpiochip_add_data(&pdev->dev, &chip->gc, chip); + if (ret) { + clk_disable_unprepare(clk); + return ret; + } + + dev_info(&pdev->dev, "Init done\n"); + + return 0; } static const struct of_device_id xway_stp_match[] = { diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 91a8ef8e7f3f..75b1135b383a 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c @@ -1,7 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) ST-Ericsson SA 2010 * - * License Terms: GNU General Public License, version 2 * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson */ diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index f57bfc07ae22..0f59161a4701 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -541,8 +541,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-tegra186.c b/drivers/gpio/gpio-tegra186.c index 7d42e3d7572c..a9058fda187e 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2017 NVIDIA Corporation * * Author: Thierry Reding <treding@nvidia.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. */ #include <linux/gpio/driver.h> diff --git a/drivers/gpio/gpio-ucb1400.c b/drivers/gpio/gpio-ucb1400.c index 5dbe31bf6699..d2a8644864c3 100644 --- a/drivers/gpio/gpio-ucb1400.c +++ b/drivers/gpio/gpio-ucb1400.c @@ -1,12 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Philips UCB1400 GPIO driver * * Author: Marek Vasut <marek.vasut@gmail.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/module.h> 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.c b/drivers/gpio/gpio-xgene.c index f1c6ec17b90a..2918363884de 100644 --- a/drivers/gpio/gpio-xgene.c +++ b/drivers/gpio/gpio-xgene.c @@ -1,20 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * AppliedMicro X-Gene SoC GPIO Driver * * Copyright (c) 2014, Applied Micro Circuits Corporation * Author: Feng Kan <fkan@apm.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. - * - * 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/acpi.h> diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index 32944eb886c1..a9748b5198e6 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -11,7 +11,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> @@ -33,14 +32,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]; @@ -84,11 +85,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))); @@ -106,7 +106,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); @@ -119,7 +118,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); @@ -138,7 +137,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; @@ -150,7 +148,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); @@ -166,7 +164,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); @@ -184,7 +182,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); @@ -193,7 +190,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); @@ -216,7 +213,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); @@ -228,12 +224,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); @@ -243,43 +239,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 * @@ -340,21 +316,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; } @@ -370,7 +353,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/gpio-zevio.c b/drivers/gpio/gpio-zevio.c index 57432397e5e5..f6f8a541348f 100644 --- a/drivers/gpio/gpio-zevio.c +++ b/drivers/gpio/gpio-zevio.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * GPIO controller in LSI ZEVIO SoCs. * * Author: Fabian Vogt <fabian@ritter-vogt.de> - * - * 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/spinlock.h> diff --git a/drivers/gpio/gpio-zx.c b/drivers/gpio/gpio-zx.c index fb927559aefa..8637adb6bc20 100644 --- a/drivers/gpio/gpio-zx.c +++ b/drivers/gpio/gpio-zx.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * ZTE ZX296702 GPIO driver * * Author: Jun Nie <jun.nie@linaro.org> * * Copyright (C) 2015 Linaro Ltd. - * - * 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/bitops.h> #include <linux/device.h> 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..567fb98c0892 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -154,10 +154,17 @@ static void of_gpio_flags_quirks(struct device_node *np, of_node_full_name(child)); *flags |= OF_GPIO_ACTIVE_LOW; } + of_node_put(child); break; } } } + + /* 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 +262,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 +363,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..f497003f119c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -956,9 +956,11 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) } if (eflags & GPIOEVENT_REQUEST_RISING_EDGE) - irqflags |= IRQF_TRIGGER_RISING; + irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? + IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; if (eflags & GPIOEVENT_REQUEST_FALLING_EDGE) - irqflags |= IRQF_TRIGGER_FALLING; + irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? + IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING; irqflags |= IRQF_ONESHOT; INIT_KFIFO(le->events); @@ -1392,12 +1394,17 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, for (i = 0; i < chip->ngpio; i++) { struct gpio_desc *desc = &gdev->descs[i]; - if (chip->get_direction && gpiochip_line_is_valid(chip, i)) - desc->flags = !chip->get_direction(chip, i) ? - (1 << FLAG_IS_OUT) : 0; - else - desc->flags = !chip->direction_input ? - (1 << FLAG_IS_OUT) : 0; + if (chip->get_direction && gpiochip_line_is_valid(chip, i)) { + if (!chip->get_direction(chip, i)) + set_bit(FLAG_IS_OUT, &desc->flags); + else + clear_bit(FLAG_IS_OUT, &desc->flags); + } else { + if (!chip->direction_input) + set_bit(FLAG_IS_OUT, &desc->flags); + else + clear_bit(FLAG_IS_OUT, &desc->flags); + } } acpi_gpiochip_add(chip); @@ -1644,39 +1651,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 +2518,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 +2536,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 +2551,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); @@ -3019,13 +3038,13 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep, * Return the GPIO's raw value, i.e. the value of the physical line disregarding * its ACTIVE_LOW status, or negative errno on failure. * - * This function should be called from contexts where we cannot sleep, and will + * This function can be called from contexts where we cannot sleep, and will * complain if the GPIO chip functions potentially sleep. */ int gpiod_get_raw_value(const struct gpio_desc *desc) { VALIDATE_DESC(desc); - /* Should be using gpio_get_value_cansleep() */ + /* Should be using gpiod_get_raw_value_cansleep() */ WARN_ON(desc->gdev->chip->can_sleep); return gpiod_get_raw_value_commit(desc); } @@ -3038,7 +3057,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_raw_value); * Return the GPIO's logical value, i.e. taking the ACTIVE_LOW status into * account, or negative errno on failure. * - * This function should be called from contexts where we cannot sleep, and will + * This function can be called from contexts where we cannot sleep, and will * complain if the GPIO chip functions potentially sleep. */ int gpiod_get_value(const struct gpio_desc *desc) @@ -3046,7 +3065,7 @@ int gpiod_get_value(const struct gpio_desc *desc) int value; VALIDATE_DESC(desc); - /* Should be using gpio_get_value_cansleep() */ + /* Should be using gpiod_get_value_cansleep() */ WARN_ON(desc->gdev->chip->can_sleep); value = gpiod_get_raw_value_commit(desc); @@ -3071,7 +3090,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_value); * without regard for their ACTIVE_LOW status. Return 0 in case of success, * else an error code. * - * This function should be called from contexts where we cannot sleep, + * This function can be called from contexts where we cannot sleep, * and it will complain if the GPIO chip functions potentially sleep. */ int gpiod_get_raw_array_value(unsigned int array_size, @@ -3097,7 +3116,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_raw_array_value); * Read the logical values of the GPIOs, i.e. taking their ACTIVE_LOW status * into account. Return 0 in case of success, else an error code. * - * This function should be called from contexts where we cannot sleep, + * This function can be called from contexts where we cannot sleep, * and it will complain if the GPIO chip functions potentially sleep. */ int gpiod_get_array_value(unsigned int array_size, @@ -3311,13 +3330,13 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, * Set the raw value of the GPIO, i.e. the value of its physical line without * regard for its ACTIVE_LOW status. * - * This function should be called from contexts where we cannot sleep, and will + * This function can be called from contexts where we cannot sleep, and will * complain if the GPIO chip functions potentially sleep. */ void gpiod_set_raw_value(struct gpio_desc *desc, int value) { VALIDATE_DESC_VOID(desc); - /* Should be using gpiod_set_value_cansleep() */ + /* Should be using gpiod_set_raw_value_cansleep() */ WARN_ON(desc->gdev->chip->can_sleep); gpiod_set_raw_value_commit(desc, value); } @@ -3352,12 +3371,13 @@ static void gpiod_set_value_nocheck(struct gpio_desc *desc, int value) * Set the logical value of the GPIO, i.e. taking its ACTIVE_LOW, * OPEN_DRAIN and OPEN_SOURCE flags into account. * - * This function should be called from contexts where we cannot sleep, and will + * This function can be called from contexts where we cannot sleep, and will * complain if the GPIO chip functions potentially sleep. */ void gpiod_set_value(struct gpio_desc *desc, int value) { VALIDATE_DESC_VOID(desc); + /* Should be using gpiod_set_value_cansleep() */ WARN_ON(desc->gdev->chip->can_sleep); gpiod_set_value_nocheck(desc, value); } @@ -3373,7 +3393,7 @@ EXPORT_SYMBOL_GPL(gpiod_set_value); * Set the raw values of the GPIOs, i.e. the values of the physical lines * without regard for their ACTIVE_LOW status. * - * This function should be called from contexts where we cannot sleep, and will + * This function can be called from contexts where we cannot sleep, and will * complain if the GPIO chip functions potentially sleep. */ int gpiod_set_raw_array_value(unsigned int array_size, @@ -3398,7 +3418,7 @@ EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value); * Set the logical values of the GPIOs, i.e. taking their ACTIVE_LOW status * into account. * - * This function should be called from contexts where we cannot sleep, and will + * This function can be called from contexts where we cannot sleep, and will * complain if the GPIO chip functions potentially sleep. */ int gpiod_set_array_value(unsigned int array_size, @@ -4244,8 +4264,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_index); * * Returns: * On successful request the GPIO pin is configured in accordance with - * provided @dflags. If the node does not have the requested GPIO - * property, NULL is returned. + * provided @dflags. * * In case of error an ERR_PTR() is returned. */ @@ -4267,9 +4286,6 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, index, &flags); if (!desc || IS_ERR(desc)) { - /* If it is not there, just return NULL */ - if (PTR_ERR(desc) == -ENOENT) - return NULL; return desc; } @@ -4420,15 +4436,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 +4445,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 +4806,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); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 7a65dad43932..7c52c2442173 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -210,7 +210,7 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, struct gpio_array *array_info, unsigned long *value_bitmap); -extern struct spinlock gpio_lock; +extern spinlock_t gpio_lock; extern struct list_head gpio_devices; struct gpio_desc { |