diff options
Diffstat (limited to 'drivers/gpio')
91 files changed, 7232 insertions, 2446 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b6ed304863e..4a1b5113e52 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -30,10 +30,6 @@ config ARCH_REQUIRE_GPIOLIB  	  Selecting this from the architecture code will cause the gpiolib  	  code to always get built in. -config GPIO_DEVRES -	def_bool y -	depends on HAS_IOMEM -  menuconfig GPIOLIB  	bool "GPIO Support" @@ -47,6 +43,10 @@ menuconfig GPIOLIB  if GPIOLIB +config GPIO_DEVRES +	def_bool y +	depends on HAS_IOMEM +  config OF_GPIO  	def_bool y  	depends on OF @@ -55,6 +55,10 @@ config GPIO_ACPI  	def_bool y  	depends on ACPI +config GPIOLIB_IRQCHIP +	select IRQ_DOMAIN +	bool +  config DEBUG_GPIO  	bool "Debug GPIO calls"  	depends on DEBUG_KERNEL @@ -110,17 +114,33 @@ comment "Memory mapped GPIO drivers:"  config GPIO_CLPS711X  	tristate "CLPS711X GPIO support" -	depends on ARCH_CLPS711X +	depends on ARCH_CLPS711X || COMPILE_TEST  	select GPIO_GENERIC  	help  	  Say yes here to support GPIO on CLPS711X SoCs. +config GPIO_DAVINCI +	bool "TI Davinci/Keystone GPIO support" +	default y if ARCH_DAVINCI +	depends on ARM && (ARCH_DAVINCI || ARCH_KEYSTONE) +	help +	  Say yes here to enable GPIO support for TI Davinci/Keystone SoCs. +  config GPIO_GENERIC_PLATFORM  	tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"  	select GPIO_GENERIC  	help  	  Say yes here to support basic platform_device memory-mapped GPIO controllers. +config GPIO_DWAPB +	tristate "Synopsys DesignWare APB GPIO driver" +	select GPIO_GENERIC +	select GENERIC_IRQ_CHIP +	depends on OF_GPIO +	help +	  Say Y or M here to build support for the Synopsys DesignWare APB +	  GPIO block. +  config GPIO_IT8761E  	tristate "IT8761E GPIO support"  	depends on X86  # unconditional access to IO space. @@ -129,7 +149,7 @@ config GPIO_IT8761E  config GPIO_EM  	tristate "Emma Mobile GPIO" -	depends on ARM +	depends on ARM && OF_GPIO  	help  	  Say yes here to support GPIO on Renesas Emma Mobile SoCs. @@ -138,6 +158,12 @@ config GPIO_EP93XX  	depends on ARCH_EP93XX  	select GPIO_GENERIC +config GPIO_ZEVIO +	bool "LSI ZEVIO SoC memory mapped GPIOs" +	depends on ARM && OF_GPIO +	help +	  Say yes here to support the GPIO controller in LSI ZEVIO SoCs. +  config GPIO_MM_LANTIQ  	bool "Lantiq Memory mapped GPIOs"  	depends on LANTIQ && SOC_XWAY @@ -156,6 +182,13 @@ config GPIO_F7188X  	  To compile this driver as a module, choose M here: the module will  	  be called f7188x-gpio. +config GPIO_MOXART +	bool "MOXART GPIO support" +	depends on ARCH_MOXART +	help +	  Select this option to enable GPIO driver for +	  MOXA ART SoC devices. +  config GPIO_MPC5200  	def_bool y  	depends on PPC_MPC52xx @@ -178,7 +211,7 @@ config GPIO_MSM_V1  config GPIO_MSM_V2  	tristate "Qualcomm MSM GPIO v2" -	depends on GPIOLIB && OF && ARCH_MSM +	depends on GPIOLIB && OF && ARCH_QCOM  	help  	  Say yes here to support the GPIO interface on ARM v7 based  	  Qualcomm MSM chips.  Most of the pins on the MSM can be @@ -211,10 +244,20 @@ config GPIO_OCTEON  	  Say yes here to support the on-chip GPIO lines on the OCTEON  	  family of SOCs. +config GPIO_OMAP +	bool "TI OMAP GPIO support" if COMPILE_TEST && !ARCH_OMAP2PLUS +	default y if ARCH_OMAP +	depends on ARM +	select GENERIC_IRQ_CHIP +	select GPIOLIB_IRQCHIP +	help +	  Say yes here to enable GPIO support for TI OMAP SoCs. +  config GPIO_PL061  	bool "PrimeCell PL061 GPIO support" -	depends on ARM && ARM_AMBA -	select GENERIC_IRQ_CHIP +	depends on ARM_AMBA +	select IRQ_DOMAIN +	select GPIOLIB_IRQCHIP  	help  	  Say yes here to support the PrimeCell PL061 GPIO device @@ -226,7 +269,7 @@ config GPIO_PXA  config GPIO_RCAR  	tristate "Renesas R-Car GPIO" -	depends on ARM +	depends on ARM && (ARCH_SHMOBILE || COMPILE_TEST)  	help  	  Say yes here to support GPIO on Renesas R-Car SoCs. @@ -237,6 +280,15 @@ config GPIO_SAMSUNG  	  Legacy GPIO support. Use only for platforms without support for  	  pinctrl. +config GPIO_SCH311X +	tristate "SMSC SCH311x SuperI/O GPIO" +	help +	  Driver to enable the GPIOs found on SMSC SMSC SCH3112, SCH3114 and +	  SCH3116 "Super I/O" chipsets. + +	  To compile this driver as a module, choose M here: the module will +	  be called gpio-sch311x. +  config GPIO_SPEAR_SPICS  	bool "ST SPEAr13xx SPI Chip Select as GPIO support"  	depends on PLAT_SPEAR @@ -252,8 +304,15 @@ config GPIO_STA2X11  	  Say yes here to support the STA2x11/ConneXt GPIO device.  	  The GPIO module has 128 GPIO pins with alternate functions. +config GPIO_SYSCON +	tristate "GPIO based on SYSCON" +	depends on MFD_SYSCON && OF +	help +	  Say yes here to support GPIO functionality though SYSCON driver. +  config GPIO_TS5500  	tristate "TS-5500 DIO blocks and compatibles" +	depends on TS5500 || COMPILE_TEST  	help  	  This driver supports Digital I/O exposed by pin blocks found on some  	  Technologic Systems platforms. It includes, but is not limited to, 3 @@ -281,6 +340,15 @@ config GPIO_XILINX  	help  	  Say yes here to support the Xilinx FPGA GPIO device +config GPIO_XTENSA +	bool "Xtensa GPIO32 support" +	depends on XTENSA +	depends on HAVE_XTENSA_GPIO32 +	depends on !SMP +	help +	  Say yes here to support the Xtensa internal GPIO32 IMPWIRE (input) +	  and EXPSTATE (output) ports +  config GPIO_VR41XX  	tristate "NEC VR4100 series General-purpose I/O Uint support"  	depends on CPU_VR41XX @@ -320,6 +388,15 @@ config GPIO_ICH  	  If unsure, say N. +config GPIO_IOP +	tristate "Intel IOP GPIO" +	depends on ARM && (ARCH_IOP32X || ARCH_IOP33X) +	help +	  Say yes here to support the GPIO functionality of a number of Intel +	  IOP32X or IOP33X. + +	  If unsure, say N. +  config GPIO_VX855  	tristate "VIA VX855/VX875 GPIO"  	depends on PCI @@ -344,7 +421,7 @@ config GPIO_GE_FPGA  	  board computers.  config GPIO_LYNXPOINT -	bool "Intel Lynxpoint GPIO support" +	tristate "Intel Lynxpoint GPIO support"  	depends on ACPI && X86  	select IRQ_DOMAIN  	help @@ -360,6 +437,11 @@ config GPIO_GRGPIO  	  Select this to support Aeroflex Gaisler GRGPIO cores from the GRLIB  	  VHDL IP core library. +config GPIO_TB10X +	bool +	select GENERIC_IRQ_CHIP +	select OF_GPIO +  comment "I2C GPIO expanders:"  config GPIO_ARIZONA @@ -368,6 +450,14 @@ config GPIO_ARIZONA  	help  	  Support for GPIOs on Wolfson Arizona class devices. +config GPIO_LP3943 +	tristate "TI/National Semiconductor LP3943 GPIO expander" +	depends on MFD_LP3943 +	help +	  GPIO driver for LP3943 MFD. +	  LP3943 can be used as a GPIO expander which provides up to 16 GPIOs. +	  Open drain outputs are required for this usage. +  config GPIO_MAX7300  	tristate "Maxim MAX7300 GPIO expander"  	depends on I2C @@ -408,7 +498,7 @@ config GPIO_MC9S08DZ60  	  Select this to enable the MC9S08DZ60 GPIO driver  config GPIO_PCA953X -	tristate "PCA953x, PCA955x, PCA957x, TCA64xx, and MAX7310 I/O ports" +	tristate "PCA95[357]x, PCA9698, TCA64xx, and MAX7310 I/O ports"  	depends on I2C  	help  	  Say yes here to provide access to several register-oriented @@ -418,14 +508,19 @@ config GPIO_PCA953X  	  4 bits:	pca9536, pca9537  	  8 bits:	max7310, max7315, pca6107, pca9534, pca9538, pca9554, -			pca9556, pca9557, pca9574, tca6408 +			pca9556, pca9557, pca9574, tca6408, xra1202  	  16 bits:	max7312, max7313, pca9535, pca9539, pca9555, pca9575,  			tca6416 +	  24 bits:	tca6424 + +	  40 bits:	pca9505, pca9698 +  config GPIO_PCA953X_IRQ  	bool "Interrupt controller support for PCA953x"  	depends on GPIO_PCA953X=y +	select GPIOLIB_IRQCHIP  	help  	  Say yes here to enable the pca953x to be used as an interrupt  	  controller. It requires the driver to be built in the kernel. @@ -495,6 +590,7 @@ config GPIO_STP_XWAY  config GPIO_TC3589X  	bool "TC3589X GPIOs"  	depends on MFD_TC3589X +	select GPIOLIB_IRQCHIP  	help  	  This enables support for the GPIOs found on the TC3589X  	  I/O Expander. @@ -576,7 +672,7 @@ comment "PCI GPIO expanders:"  config GPIO_CS5535  	tristate "AMD CS5535/CS5536 GPIO support" -	depends on PCI && X86 && MFD_CS5535 +	depends on MFD_CS5535  	help  	  The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that  	  can be used for quite a number of things.  The CS5535/6 is found on @@ -588,7 +684,7 @@ config GPIO_BT8XX  	tristate "BT8XX GPIO abuser"  	depends on PCI && VIDEO_BT848=n  	help -	  The BT8xx frame grabber chip has 24 GPIO pins than can be abused +	  The BT8xx frame grabber chip has 24 GPIO pins that can be abused  	  as a cheap PCI GPIO card.  	  This chip can be found on Miro, Hauppauge and STB TV-cards. @@ -612,16 +708,16 @@ config GPIO_AMD8111  	  If unsure, say N -config GPIO_LANGWELL -	bool "Intel Langwell/Penwell GPIO support" +config GPIO_INTEL_MID +	bool "Intel Mid GPIO support"  	depends on PCI && X86 -	select IRQ_DOMAIN +	select GPIOLIB_IRQCHIP  	help -	  Say Y here to support Intel Langwell/Penwell GPIO. +	  Say Y here to support Intel Mid GPIO.  config GPIO_PCH  	tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7223/ML7831) GPIO" -	depends on PCI && X86 +	depends on PCI && (X86_32 || COMPILE_TEST)  	select GENERIC_IRQ_CHIP  	help  	  This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff @@ -655,7 +751,7 @@ config GPIO_SODAVILLE  config GPIO_TIMBERDALE  	bool "Support for timberdale GPIO IP" -	depends on MFD_TIMBERDALE && HAS_IOMEM +	depends on MFD_TIMBERDALE  	---help---  	Add support for the GPIO IP in the timberdale FPGA. @@ -679,11 +775,13 @@ config GPIO_MAX7301  config GPIO_MCP23S08  	tristate "Microchip MCP23xxx I/O expander" +	depends on OF_GPIO  	depends on (SPI_MASTER && !I2C) || I2C  	help  	  SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017  	  I/O expanders.  	  This provides a GPIO interface supporting inputs and outputs. +	  The I2C versions of the chips can be used as interrupt-controller.  config GPIO_MC33880  	tristate "Freescale MC33880 high-side/low-side switch" @@ -694,16 +792,16 @@ config GPIO_MC33880  config GPIO_74X164  	tristate "74x164 serial-in/parallel-out 8-bits shift register" -	depends on SPI_MASTER +	depends on SPI_MASTER && OF  	help -	  Platform driver for 74x164 compatible serial-in/parallel-out -	  8-outputs shift registers. This driver can be used to provide access +	  Driver for 74x164 compatible serial-in/parallel-out 8-outputs +	  shift registers. This driver can be used to provide access  	  to more gpio outputs.  comment "AC97 GPIO expanders:"  config GPIO_UCB1400 -	bool "Philips UCB1400 GPIO" +	tristate "Philips UCB1400 GPIO"  	depends on UCB1400_CORE  	help  	  This enables support for the Philips UCB1400 GPIO pins. @@ -759,6 +857,12 @@ config GPIO_MSIC  	  Enable support for GPIO on intel MSIC controllers found in  	  intel MID devices +config GPIO_BCM_KONA +	bool "Broadcom Kona GPIO" +	depends on OF_GPIO +	help +	  Turn on GPIO support for Broadcom "Kona" chips. +  comment "USB GPIO expanders:"  config GPIO_VIPERBOARD diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 98e23ebba2c..d10f6a9d875 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -16,23 +16,27 @@ obj-$(CONFIG_GPIO_ADP5520)	+= gpio-adp5520.o  obj-$(CONFIG_GPIO_ADP5588)	+= gpio-adp5588.o  obj-$(CONFIG_GPIO_AMD8111)	+= gpio-amd8111.o  obj-$(CONFIG_GPIO_ARIZONA)	+= gpio-arizona.o +obj-$(CONFIG_GPIO_BCM_KONA)	+= gpio-bcm-kona.o  obj-$(CONFIG_GPIO_BT8XX)	+= gpio-bt8xx.o  obj-$(CONFIG_GPIO_CLPS711X)	+= gpio-clps711x.o  obj-$(CONFIG_GPIO_CS5535)	+= gpio-cs5535.o  obj-$(CONFIG_GPIO_DA9052)	+= gpio-da9052.o  obj-$(CONFIG_GPIO_DA9055)	+= gpio-da9055.o -obj-$(CONFIG_ARCH_DAVINCI)	+= gpio-davinci.o +obj-$(CONFIG_GPIO_DAVINCI)	+= gpio-davinci.o +obj-$(CONFIG_GPIO_DWAPB)	+= gpio-dwapb.o  obj-$(CONFIG_GPIO_EM)		+= gpio-em.o  obj-$(CONFIG_GPIO_EP93XX)	+= gpio-ep93xx.o  obj-$(CONFIG_GPIO_F7188X)	+= gpio-f7188x.o  obj-$(CONFIG_GPIO_GE_FPGA)	+= gpio-ge.o  obj-$(CONFIG_GPIO_GRGPIO)	+= gpio-grgpio.o  obj-$(CONFIG_GPIO_ICH)		+= gpio-ich.o +obj-$(CONFIG_GPIO_IOP)		+= gpio-iop.o  obj-$(CONFIG_GPIO_IT8761E)	+= gpio-it8761e.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_LANGWELL)	+= gpio-langwell.o +obj-$(CONFIG_GPIO_INTEL_MID)	+= gpio-intel-mid.o +obj-$(CONFIG_GPIO_LP3943)	+= gpio-lp3943.o  obj-$(CONFIG_ARCH_LPC32XX)	+= gpio-lpc32xx.o  obj-$(CONFIG_GPIO_LYNXPOINT)	+= gpio-lynxpoint.o  obj-$(CONFIG_GPIO_MAX730X)	+= gpio-max730x.o @@ -44,6 +48,7 @@ obj-$(CONFIG_GPIO_MC9S08DZ60)	+= gpio-mc9s08dz60.o  obj-$(CONFIG_GPIO_MCP23S08)	+= gpio-mcp23s08.o  obj-$(CONFIG_GPIO_ML_IOH)	+= gpio-ml-ioh.o  obj-$(CONFIG_GPIO_MM_LANTIQ)	+= gpio-mm-lantiq.o +obj-$(CONFIG_GPIO_MOXART)	+= gpio-moxart.o  obj-$(CONFIG_GPIO_MPC5200)	+= gpio-mpc5200.o  obj-$(CONFIG_GPIO_MPC8XXX)	+= gpio-mpc8xxx.o  obj-$(CONFIG_GPIO_MSIC)		+= gpio-msic.o @@ -53,7 +58,7 @@ 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_ARCH_OMAP)		+= gpio-omap.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 @@ -65,16 +70,18 @@ obj-$(CONFIG_GPIO_RCAR)		+= gpio-rcar.o  obj-$(CONFIG_GPIO_SAMSUNG)	+= gpio-samsung.o  obj-$(CONFIG_ARCH_SA1100)	+= gpio-sa1100.o  obj-$(CONFIG_GPIO_SCH)		+= gpio-sch.o +obj-$(CONFIG_GPIO_SCH311X)	+= gpio-sch311x.o  obj-$(CONFIG_GPIO_SODAVILLE)	+= gpio-sodaville.o  obj-$(CONFIG_GPIO_SPEAR_SPICS)	+= gpio-spear-spics.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_SX150X)	+= gpio-sx150x.o +obj-$(CONFIG_GPIO_SYSCON)	+= gpio-syscon.o +obj-$(CONFIG_GPIO_TB10X)	+= gpio-tb10x.o  obj-$(CONFIG_GPIO_TC3589X)	+= gpio-tc3589x.o  obj-$(CONFIG_ARCH_TEGRA)	+= gpio-tegra.o  obj-$(CONFIG_GPIO_TIMBERDALE)	+= gpio-timberdale.o -obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o  obj-$(CONFIG_GPIO_PALMAS)	+= gpio-palmas.o  obj-$(CONFIG_GPIO_TPS6586X)	+= gpio-tps6586x.o  obj-$(CONFIG_GPIO_TPS65910)	+= gpio-tps65910.o @@ -92,3 +99,5 @@ obj-$(CONFIG_GPIO_WM831X)	+= gpio-wm831x.o  obj-$(CONFIG_GPIO_WM8350)	+= gpio-wm8350.o  obj-$(CONFIG_GPIO_WM8994)	+= gpio-wm8994.o  obj-$(CONFIG_GPIO_XILINX)	+= gpio-xilinx.o +obj-$(CONFIG_GPIO_XTENSA)	+= gpio-xtensa.o +obj-$(CONFIG_GPIO_ZEVIO)	+= gpio-zevio.o diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c index 3e7812f0405..65978cf85f7 100644 --- a/drivers/gpio/devres.c +++ b/drivers/gpio/devres.c @@ -15,10 +15,138 @@   */  #include <linux/module.h> +#include <linux/err.h>  #include <linux/gpio.h> +#include <linux/gpio/consumer.h>  #include <linux/device.h>  #include <linux/gfp.h> +static void devm_gpiod_release(struct device *dev, void *res) +{ +	struct gpio_desc **desc = res; + +	gpiod_put(*desc); +} + +static int devm_gpiod_match(struct device *dev, void *res, void *data) +{ +	struct gpio_desc **this = res, **gpio = data; + +	return *this == *gpio; +} + +/** + * devm_gpiod_get - Resource-managed gpiod_get() + * @dev:	GPIO consumer + * @con_id:	function within the GPIO consumer + * + * Managed gpiod_get(). GPIO descriptors returned from this function are + * automatically disposed on driver detach. See gpiod_get() for detailed + * information about behavior and return values. + */ +struct gpio_desc *__must_check devm_gpiod_get(struct device *dev, +					      const char *con_id) +{ +	return devm_gpiod_get_index(dev, con_id, 0); +} +EXPORT_SYMBOL(devm_gpiod_get); + +/** + * devm_gpiod_get_optional - Resource-managed gpiod_get_optional() + * @dev: GPIO consumer + * @con_id: function within the GPIO consumer + * + * Managed gpiod_get_optional(). GPIO descriptors returned from this function + * are automatically disposed on driver detach. See gpiod_get_optional() for + * detailed information about behavior and return values. + */ +struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev, +						       const char *con_id) +{ +	return devm_gpiod_get_index_optional(dev, con_id, 0); +} +EXPORT_SYMBOL(devm_gpiod_get_optional); + +/** + * devm_gpiod_get_index - Resource-managed gpiod_get_index() + * @dev:	GPIO consumer + * @con_id:	function within the GPIO consumer + * @idx:	index of the GPIO to obtain in the consumer + * + * Managed gpiod_get_index(). GPIO descriptors returned from this function are + * automatically disposed on driver detach. See gpiod_get_index() for detailed + * information about behavior and return values. + */ +struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev, +						    const char *con_id, +						    unsigned int idx) +{ +	struct gpio_desc **dr; +	struct gpio_desc *desc; + +	dr = devres_alloc(devm_gpiod_release, sizeof(struct gpiod_desc *), +			  GFP_KERNEL); +	if (!dr) +		return ERR_PTR(-ENOMEM); + +	desc = gpiod_get_index(dev, con_id, idx); +	if (IS_ERR(desc)) { +		devres_free(dr); +		return desc; +	} + +	*dr = desc; +	devres_add(dev, dr); + +	return desc; +} +EXPORT_SYMBOL(devm_gpiod_get_index); + +/** + * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional() + * @dev: GPIO consumer + * @con_id: function within the GPIO consumer + * @index: index of the GPIO to obtain in the consumer + * + * Managed gpiod_get_index_optional(). GPIO descriptors returned from this + * function are automatically disposed on driver detach. See + * gpiod_get_index_optional() for detailed information about behavior and + * return values. + */ +struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev, +							     const char *con_id, +							     unsigned int index) +{ +	struct gpio_desc *desc; + +	desc = devm_gpiod_get_index(dev, con_id, index); +	if (IS_ERR(desc)) { +		if (PTR_ERR(desc) == -ENOENT) +			return NULL; +	} + +	return desc; +} +EXPORT_SYMBOL(devm_gpiod_get_index_optional); + +/** + * devm_gpiod_put - Resource-managed gpiod_put() + * @desc:	GPIO descriptor to dispose of + * + * Dispose of a GPIO descriptor obtained with devm_gpiod_get() or + * devm_gpiod_get_index(). Normally this function will not be called as the GPIO + * will be disposed of by the resource management code. + */ +void devm_gpiod_put(struct device *dev, struct gpio_desc *desc) +{ +	WARN_ON(devres_release(dev, devm_gpiod_release, devm_gpiod_match, +		&desc)); +} +EXPORT_SYMBOL(devm_gpiod_put); + + + +  static void devm_gpio_release(struct device *dev, void *res)  {  	unsigned *gpio = res; diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index 5d518d5db7a..e4ae29824c3 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -12,7 +12,6 @@  #include <linux/init.h>  #include <linux/mutex.h>  #include <linux/spi/spi.h> -#include <linux/spi/74x164.h>  #include <linux/gpio.h>  #include <linux/of_gpio.h>  #include <linux/slab.h> @@ -21,7 +20,6 @@  #define GEN_74X164_NUMBER_GPIOS	8  struct gen_74x164_chip { -	struct spi_device	*spi;  	u8			*buffer;  	struct gpio_chip	gpio_chip;  	struct mutex		lock; @@ -35,6 +33,7 @@ static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc)  static int __gen_74x164_write_config(struct gen_74x164_chip *chip)  { +	struct spi_device *spi = to_spi_device(chip->gpio_chip.dev);  	struct spi_message message;  	struct spi_transfer *msg_buf;  	int i, ret = 0; @@ -55,12 +54,12 @@ static int __gen_74x164_write_config(struct gen_74x164_chip *chip)  	 * byte of the buffer will end up in the last register.  	 */  	for (i = chip->registers - 1; i >= 0; i--) { -		msg_buf[i].tx_buf = chip->buffer +i; +		msg_buf[i].tx_buf = chip->buffer + i;  		msg_buf[i].len = sizeof(u8);  		spi_message_add_tail(msg_buf + i, &message);  	} -	ret = spi_sync(chip->spi, &message); +	ret = spi_sync(spi, &message);  	kfree(msg_buf); @@ -108,14 +107,8 @@ static int gen_74x164_direction_output(struct gpio_chip *gc,  static int gen_74x164_probe(struct spi_device *spi)  {  	struct gen_74x164_chip *chip; -	struct gen_74x164_chip_platform_data *pdata;  	int ret; -	if (!spi->dev.of_node) { -		dev_err(&spi->dev, "No device tree data available.\n"); -		return -EINVAL; -	} -  	/*  	 * bits_per_word cannot be configured in platform data  	 */ @@ -129,40 +122,32 @@ static int gen_74x164_probe(struct spi_device *spi)  	if (!chip)  		return -ENOMEM; -	pdata = dev_get_platdata(&spi->dev); -	if (pdata && pdata->base) -		chip->gpio_chip.base = pdata->base; -	else -		chip->gpio_chip.base = -1; - -	mutex_init(&chip->lock); -  	spi_set_drvdata(spi, chip); -	chip->spi = spi; -  	chip->gpio_chip.label = spi->modalias;  	chip->gpio_chip.direction_output = gen_74x164_direction_output;  	chip->gpio_chip.get = gen_74x164_get_value;  	chip->gpio_chip.set = gen_74x164_set_value; +	chip->gpio_chip.base = -1; -	if (of_property_read_u32(spi->dev.of_node, "registers-number", &chip->registers)) { -		dev_err(&spi->dev, "Missing registers-number property in the DT.\n"); -		ret = -EINVAL; -		goto exit_destroy; +	if (of_property_read_u32(spi->dev.of_node, "registers-number", +				 &chip->registers)) { +		dev_err(&spi->dev, +			"Missing registers-number property in the DT.\n"); +		return -EINVAL;  	}  	chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers;  	chip->buffer = devm_kzalloc(&spi->dev, chip->registers, GFP_KERNEL); -	if (!chip->buffer) { -		ret = -ENOMEM; -		goto exit_destroy; -	} +	if (!chip->buffer) +		return -ENOMEM; -	chip->gpio_chip.can_sleep = 1; +	chip->gpio_chip.can_sleep = true;  	chip->gpio_chip.dev = &spi->dev;  	chip->gpio_chip.owner = THIS_MODULE; +	mutex_init(&chip->lock); +  	ret = __gen_74x164_write_config(chip);  	if (ret) {  		dev_err(&spi->dev, "Failed writing: %d\n", ret); @@ -170,34 +155,23 @@ static int gen_74x164_probe(struct spi_device *spi)  	}  	ret = gpiochip_add(&chip->gpio_chip); -	if (ret) -		goto exit_destroy; - -	return ret; +	if (!ret) +		return 0;  exit_destroy: -	spi_set_drvdata(spi, NULL);  	mutex_destroy(&chip->lock); +  	return ret;  }  static int gen_74x164_remove(struct spi_device *spi)  { -	struct gen_74x164_chip *chip; +	struct gen_74x164_chip *chip = spi_get_drvdata(spi);  	int ret; -	chip = spi_get_drvdata(spi); -	if (chip == NULL) -		return -ENODEV; - -	spi_set_drvdata(spi, NULL); -  	ret = gpiochip_remove(&chip->gpio_chip);  	if (!ret)  		mutex_destroy(&chip->lock); -	else -		dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n", -				ret);  	return ret;  } @@ -212,7 +186,7 @@ static struct spi_driver gen_74x164_driver = {  	.driver = {  		.name		= "74x164",  		.owner		= THIS_MODULE, -		.of_match_table	= of_match_ptr(gen_74x164_dt_ids), +		.of_match_table	= gen_74x164_dt_ids,  	},  	.probe		= gen_74x164_probe,  	.remove		= gen_74x164_remove, diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c index c0f3fc44ab0..b2239d678d0 100644 --- a/drivers/gpio/gpio-adnp.c +++ b/drivers/gpio/gpio-adnp.c @@ -260,7 +260,7 @@ static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios)  	chip->direction_output = adnp_gpio_direction_output;  	chip->get = adnp_gpio_get;  	chip->set = adnp_gpio_set; -	chip->can_sleep = 1; +	chip->can_sleep = true;  	if (IS_ENABLED(CONFIG_DEBUG_FS))  		chip->dbg_show = adnp_gpio_dbg_show; @@ -325,9 +325,9 @@ static irqreturn_t adnp_irq(int irq, void *data)  		pending &= isr & ier;  		for_each_set_bit(bit, &pending, 8) { -			unsigned int virq; -			virq = irq_find_mapping(adnp->domain, base + bit); -			handle_nested_irq(virq); +			unsigned int child_irq; +			child_irq = irq_find_mapping(adnp->domain, base + bit); +			handle_nested_irq(child_irq);  		}  	} @@ -408,6 +408,26 @@ static void adnp_irq_bus_unlock(struct irq_data *data)  	mutex_unlock(&adnp->irq_lock);  } +static int adnp_irq_reqres(struct irq_data *data) +{ +	struct adnp *adnp = irq_data_get_irq_chip_data(data); + +	if (gpio_lock_as_irq(&adnp->gpio, data->hwirq)) { +		dev_err(adnp->gpio.dev, +			"unable to lock HW IRQ %lu for IRQ\n", +			data->hwirq); +		return -EINVAL; +	} +	return 0; +} + +static void adnp_irq_relres(struct irq_data *data) +{ +	struct adnp *adnp = irq_data_get_irq_chip_data(data); + +	gpio_unlock_as_irq(&adnp->gpio, data->hwirq); +} +  static struct irq_chip adnp_irq_chip = {  	.name = "gpio-adnp",  	.irq_mask = adnp_irq_mask, @@ -415,6 +435,8 @@ static struct irq_chip adnp_irq_chip = {  	.irq_set_type = adnp_irq_set_type,  	.irq_bus_lock = adnp_irq_bus_lock,  	.irq_bus_sync_unlock = adnp_irq_bus_unlock, +	.irq_request_resources = adnp_irq_reqres, +	.irq_release_resources = adnp_irq_relres,  };  static int adnp_irq_map(struct irq_domain *domain, unsigned int irq, @@ -594,7 +616,7 @@ static struct i2c_driver adnp_i2c_driver = {  	.driver = {  		.name = "gpio-adnp",  		.owner = THIS_MODULE, -		.of_match_table = of_match_ptr(adnp_of_match), +		.of_match_table = adnp_of_match,  	},  	.probe = adnp_i2c_probe,  	.remove = adnp_i2c_remove, diff --git a/drivers/gpio/gpio-adp5520.c b/drivers/gpio/gpio-adp5520.c index 084337d5514..f1ade8fa321 100644 --- a/drivers/gpio/gpio-adp5520.c +++ b/drivers/gpio/gpio-adp5520.c @@ -106,10 +106,8 @@ static int adp5520_gpio_probe(struct platform_device *pdev)  	}  	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); -	if (dev == NULL) { -		dev_err(&pdev->dev, "failed to alloc memory\n"); +	if (dev == NULL)  		return -ENOMEM; -	}  	dev->master = pdev->dev.parent; @@ -127,7 +125,7 @@ static int adp5520_gpio_probe(struct platform_device *pdev)  	gc->direction_output = adp5520_gpio_direction_output;  	gc->get = adp5520_gpio_get_value;  	gc->set = adp5520_gpio_set_value; -	gc->can_sleep = 1; +	gc->can_sleep = true;  	gc->base = pdata->gpio_start;  	gc->ngpio = gpios; diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c index 90fc4c99c02..ef19bc33f2b 100644 --- a/drivers/gpio/gpio-adp5588.c +++ b/drivers/gpio/gpio-adp5588.c @@ -67,9 +67,20 @@ static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)  {  	struct adp5588_gpio *dev =  	    container_of(chip, struct adp5588_gpio, gpio_chip); +	unsigned bank = ADP5588_BANK(off); +	unsigned bit = ADP5588_BIT(off); +	int val; -	return !!(adp5588_gpio_read(dev->client, -		  GPIO_DAT_STAT1 + ADP5588_BANK(off)) & ADP5588_BIT(off)); +	mutex_lock(&dev->lock); + +	if (dev->dir[bank] & bit) +		val = dev->dat_out[bank]; +	else +		val = adp5588_gpio_read(dev->client, GPIO_DAT_STAT1 + bank); + +	mutex_unlock(&dev->lock); + +	return !!(val & bit);  }  static void adp5588_gpio_set_value(struct gpio_chip *chip, @@ -368,10 +379,8 @@ static int adp5588_gpio_probe(struct i2c_client *client,  	}  	dev = kzalloc(sizeof(*dev), GFP_KERNEL); -	if (dev == NULL) { -		dev_err(&client->dev, "failed to alloc memory\n"); +	if (dev == NULL)  		return -ENOMEM; -	}  	dev->client = client; @@ -380,12 +389,13 @@ static int adp5588_gpio_probe(struct i2c_client *client,  	gc->direction_output = adp5588_gpio_direction_output;  	gc->get = adp5588_gpio_get_value;  	gc->set = adp5588_gpio_set_value; -	gc->can_sleep = 1; +	gc->can_sleep = true;  	gc->base = pdata->gpio_start;  	gc->ngpio = ADP5588_MAXGPIO;  	gc->label = client->name;  	gc->owner = THIS_MODULE; +	gc->names = pdata->names;  	mutex_init(&dev->lock); diff --git a/drivers/gpio/gpio-amd8111.c b/drivers/gpio/gpio-amd8111.c index 710fafcdd1b..94e9992f890 100644 --- a/drivers/gpio/gpio-amd8111.c +++ b/drivers/gpio/gpio-amd8111.c @@ -60,7 +60,7 @@   * register a pci_driver, because someone else might one day   * want to register another driver on the same PCI id.   */ -static DEFINE_PCI_DEVICE_TABLE(pci_tbl) = { +static const struct pci_device_id pci_tbl[] = {  	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS), 0 },  	{ 0, },	/* terminate list */  }; diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c index fa8b6a76276..29bdff55898 100644 --- a/drivers/gpio/gpio-arizona.c +++ b/drivers/gpio/gpio-arizona.c @@ -91,7 +91,7 @@ static struct gpio_chip template_chip = {  	.get			= arizona_gpio_get,  	.direction_output	= arizona_gpio_direction_out,  	.set			= arizona_gpio_set, -	.can_sleep		= 1, +	.can_sleep		= true,  };  static int arizona_gpio_probe(struct platform_device *pdev) @@ -109,10 +109,14 @@ static int arizona_gpio_probe(struct platform_device *pdev)  	arizona_gpio->arizona = arizona;  	arizona_gpio->gpio_chip = template_chip;  	arizona_gpio->gpio_chip.dev = &pdev->dev; +#ifdef CONFIG_OF_GPIO +	arizona_gpio->gpio_chip.of_node = arizona->dev->of_node; +#endif  	switch (arizona->type) {  	case WM5102:  	case WM5110: +	case WM8997:  		arizona_gpio->gpio_chip.ngpio = 5;  		break;  	default: diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c new file mode 100644 index 00000000000..3f6b33ce9bd --- /dev/null +++ b/drivers/gpio/gpio-bcm-kona.c @@ -0,0 +1,681 @@ +/* + * Copyright (C) 2012-2014 Broadcom Corporation + * + * 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. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + */ + +#include <linux/bitops.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/gpio.h> +#include <linux/of_device.h> +#include <linux/of_irq.h> +#include <linux/module.h> +#include <linux/irqdomain.h> +#include <linux/irqchip/chained_irq.h> + +#define BCM_GPIO_PASSWD				0x00a5a501 +#define GPIO_PER_BANK				32 +#define GPIO_MAX_BANK_NUM			8 + +#define GPIO_BANK(gpio)				((gpio) >> 5) +#define GPIO_BIT(gpio)				((gpio) & (GPIO_PER_BANK - 1)) + +/* There is a GPIO control register for each GPIO */ +#define GPIO_CONTROL(gpio)			(0x00000100 + ((gpio) << 2)) + +/* The remaining registers are per GPIO bank */ +#define GPIO_OUT_STATUS(bank)			(0x00000000 + ((bank) << 2)) +#define GPIO_IN_STATUS(bank)			(0x00000020 + ((bank) << 2)) +#define GPIO_OUT_SET(bank)			(0x00000040 + ((bank) << 2)) +#define GPIO_OUT_CLEAR(bank)			(0x00000060 + ((bank) << 2)) +#define GPIO_INT_STATUS(bank)			(0x00000080 + ((bank) << 2)) +#define GPIO_INT_MASK(bank)			(0x000000a0 + ((bank) << 2)) +#define GPIO_INT_MSKCLR(bank)			(0x000000c0 + ((bank) << 2)) +#define GPIO_PWD_STATUS(bank)			(0x00000500 + ((bank) << 2)) + +#define GPIO_GPPWR_OFFSET			0x00000520 + +#define GPIO_GPCTR0_DBR_SHIFT			5 +#define GPIO_GPCTR0_DBR_MASK			0x000001e0 + +#define GPIO_GPCTR0_ITR_SHIFT			3 +#define GPIO_GPCTR0_ITR_MASK			0x00000018 +#define GPIO_GPCTR0_ITR_CMD_RISING_EDGE		0x00000001 +#define GPIO_GPCTR0_ITR_CMD_FALLING_EDGE	0x00000002 +#define GPIO_GPCTR0_ITR_CMD_BOTH_EDGE		0x00000003 + +#define GPIO_GPCTR0_IOTR_MASK			0x00000001 +#define GPIO_GPCTR0_IOTR_CMD_0UTPUT		0x00000000 +#define GPIO_GPCTR0_IOTR_CMD_INPUT		0x00000001 + +#define GPIO_GPCTR0_DB_ENABLE_MASK		0x00000100 + +#define LOCK_CODE				0xffffffff +#define UNLOCK_CODE				0x00000000 + +struct bcm_kona_gpio { +	void __iomem *reg_base; +	int num_bank; +	spinlock_t lock; +	struct gpio_chip gpio_chip; +	struct irq_domain *irq_domain; +	struct bcm_kona_gpio_bank *banks; +	struct platform_device *pdev; +}; + +struct bcm_kona_gpio_bank { +	int id; +	int irq; +	/* Used in the interrupt handler */ +	struct bcm_kona_gpio *kona_gpio; +}; + +static inline struct bcm_kona_gpio *to_kona_gpio(struct gpio_chip *chip) +{ +	return container_of(chip, struct bcm_kona_gpio, gpio_chip); +} + +static inline void bcm_kona_gpio_write_lock_regs(void __iomem *reg_base, +						int bank_id, u32 lockcode) +{ +	writel(BCM_GPIO_PASSWD, reg_base + GPIO_GPPWR_OFFSET); +	writel(lockcode, reg_base + GPIO_PWD_STATUS(bank_id)); +} + +static void bcm_kona_gpio_lock_gpio(struct bcm_kona_gpio *kona_gpio, +					unsigned gpio) +{ +	u32 val; +	unsigned long flags; +	int bank_id = GPIO_BANK(gpio); + +	spin_lock_irqsave(&kona_gpio->lock, flags); + +	val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id)); +	val |= BIT(gpio); +	bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val); + +	spin_unlock_irqrestore(&kona_gpio->lock, flags); +} + +static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio, +					unsigned gpio) +{ +	u32 val; +	unsigned long flags; +	int bank_id = GPIO_BANK(gpio); + +	spin_lock_irqsave(&kona_gpio->lock, flags); + +	val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id)); +	val &= ~BIT(gpio); +	bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val); + +	spin_unlock_irqrestore(&kona_gpio->lock, flags); +} + +static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value) +{ +	struct bcm_kona_gpio *kona_gpio; +	void __iomem *reg_base; +	int bank_id = GPIO_BANK(gpio); +	int bit = GPIO_BIT(gpio); +	u32 val, reg_offset; +	unsigned long flags; + +	kona_gpio = to_kona_gpio(chip); +	reg_base = kona_gpio->reg_base; +	spin_lock_irqsave(&kona_gpio->lock, flags); + +	/* determine the GPIO pin direction */ +	val = readl(reg_base + GPIO_CONTROL(gpio)); +	val &= GPIO_GPCTR0_IOTR_MASK; + +	/* this function only applies to output pin */ +	if (GPIO_GPCTR0_IOTR_CMD_INPUT == val) +		goto out; + +	reg_offset = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id); + +	val = readl(reg_base + reg_offset); +	val |= BIT(bit); +	writel(val, reg_base + reg_offset); + +out: +	spin_unlock_irqrestore(&kona_gpio->lock, flags); +} + +static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio) +{ +	struct bcm_kona_gpio *kona_gpio; +	void __iomem *reg_base; +	int bank_id = GPIO_BANK(gpio); +	int bit = GPIO_BIT(gpio); +	u32 val, reg_offset; +	unsigned long flags; + +	kona_gpio = to_kona_gpio(chip); +	reg_base = kona_gpio->reg_base; +	spin_lock_irqsave(&kona_gpio->lock, flags); + +	/* determine the GPIO pin direction */ +	val = readl(reg_base + GPIO_CONTROL(gpio)); +	val &= GPIO_GPCTR0_IOTR_MASK; + +	/* read the GPIO bank status */ +	reg_offset = (GPIO_GPCTR0_IOTR_CMD_INPUT == val) ? +	    GPIO_IN_STATUS(bank_id) : GPIO_OUT_STATUS(bank_id); +	val = readl(reg_base + reg_offset); + +	spin_unlock_irqrestore(&kona_gpio->lock, flags); + +	/* return the specified bit status */ +	return !!(val & BIT(bit)); +} + +static int bcm_kona_gpio_request(struct gpio_chip *chip, unsigned gpio) +{ +	struct bcm_kona_gpio *kona_gpio = to_kona_gpio(chip); + +	bcm_kona_gpio_unlock_gpio(kona_gpio, gpio); +	return 0; +} + +static void bcm_kona_gpio_free(struct gpio_chip *chip, unsigned gpio) +{ +	struct bcm_kona_gpio *kona_gpio = to_kona_gpio(chip); + +	bcm_kona_gpio_lock_gpio(kona_gpio, gpio); +} + +static int bcm_kona_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) +{ +	struct bcm_kona_gpio *kona_gpio; +	void __iomem *reg_base; +	u32 val; +	unsigned long flags; + +	kona_gpio = to_kona_gpio(chip); +	reg_base = kona_gpio->reg_base; +	spin_lock_irqsave(&kona_gpio->lock, flags); + +	val = readl(reg_base + GPIO_CONTROL(gpio)); +	val &= ~GPIO_GPCTR0_IOTR_MASK; +	val |= GPIO_GPCTR0_IOTR_CMD_INPUT; +	writel(val, reg_base + GPIO_CONTROL(gpio)); + +	spin_unlock_irqrestore(&kona_gpio->lock, flags); + +	return 0; +} + +static int bcm_kona_gpio_direction_output(struct gpio_chip *chip, +					  unsigned gpio, int value) +{ +	struct bcm_kona_gpio *kona_gpio; +	void __iomem *reg_base; +	int bank_id = GPIO_BANK(gpio); +	int bit = GPIO_BIT(gpio); +	u32 val, reg_offset; +	unsigned long flags; + +	kona_gpio = to_kona_gpio(chip); +	reg_base = kona_gpio->reg_base; +	spin_lock_irqsave(&kona_gpio->lock, flags); + +	val = readl(reg_base + GPIO_CONTROL(gpio)); +	val &= ~GPIO_GPCTR0_IOTR_MASK; +	val |= GPIO_GPCTR0_IOTR_CMD_0UTPUT; +	writel(val, reg_base + GPIO_CONTROL(gpio)); +	reg_offset = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id); + +	val = readl(reg_base + reg_offset); +	val |= BIT(bit); +	writel(val, reg_base + reg_offset); + +	spin_unlock_irqrestore(&kona_gpio->lock, flags); + +	return 0; +} + +static int bcm_kona_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) +{ +	struct bcm_kona_gpio *kona_gpio; + +	kona_gpio = to_kona_gpio(chip); +	if (gpio >= kona_gpio->gpio_chip.ngpio) +		return -ENXIO; +	return irq_create_mapping(kona_gpio->irq_domain, gpio); +} + +static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio, +				      unsigned debounce) +{ +	struct bcm_kona_gpio *kona_gpio; +	void __iomem *reg_base; +	u32 val, res; +	unsigned long flags; + +	kona_gpio = to_kona_gpio(chip); +	reg_base = kona_gpio->reg_base; +	/* debounce must be 1-128ms (or 0) */ +	if ((debounce > 0 && debounce < 1000) || debounce > 128000) { +		dev_err(chip->dev, "Debounce value %u not in range\n", +			debounce); +		return -EINVAL; +	} + +	/* calculate debounce bit value */ +	if (debounce != 0) { +		/* Convert to ms */ +		debounce /= 1000; +		/* find the MSB */ +		res = fls(debounce) - 1; +		/* Check if MSB-1 is set (round up or down) */ +		if (res > 0 && (debounce & BIT(res - 1))) +			res++; +	} + +	/* spin lock for read-modify-write of the GPIO register */ +	spin_lock_irqsave(&kona_gpio->lock, flags); + +	val = readl(reg_base + GPIO_CONTROL(gpio)); +	val &= ~GPIO_GPCTR0_DBR_MASK; + +	if (debounce == 0) { +		/* disable debounce */ +		val &= ~GPIO_GPCTR0_DB_ENABLE_MASK; +	} else { +		val |= GPIO_GPCTR0_DB_ENABLE_MASK | +		    (res << GPIO_GPCTR0_DBR_SHIFT); +	} + +	writel(val, reg_base + GPIO_CONTROL(gpio)); + +	spin_unlock_irqrestore(&kona_gpio->lock, flags); + +	return 0; +} + +static struct gpio_chip template_chip = { +	.label = "bcm-kona-gpio", +	.owner = THIS_MODULE, +	.request = bcm_kona_gpio_request, +	.free = bcm_kona_gpio_free, +	.direction_input = bcm_kona_gpio_direction_input, +	.get = bcm_kona_gpio_get, +	.direction_output = bcm_kona_gpio_direction_output, +	.set = bcm_kona_gpio_set, +	.set_debounce = bcm_kona_gpio_set_debounce, +	.to_irq = bcm_kona_gpio_to_irq, +	.base = 0, +}; + +static void bcm_kona_gpio_irq_ack(struct irq_data *d) +{ +	struct bcm_kona_gpio *kona_gpio; +	void __iomem *reg_base; +	unsigned gpio = d->hwirq; +	int bank_id = GPIO_BANK(gpio); +	int bit = GPIO_BIT(gpio); +	u32 val; +	unsigned long flags; + +	kona_gpio = irq_data_get_irq_chip_data(d); +	reg_base = kona_gpio->reg_base; +	spin_lock_irqsave(&kona_gpio->lock, flags); + +	val = readl(reg_base + GPIO_INT_STATUS(bank_id)); +	val |= BIT(bit); +	writel(val, reg_base + GPIO_INT_STATUS(bank_id)); + +	spin_unlock_irqrestore(&kona_gpio->lock, flags); +} + +static void bcm_kona_gpio_irq_mask(struct irq_data *d) +{ +	struct bcm_kona_gpio *kona_gpio; +	void __iomem *reg_base; +	unsigned gpio = d->hwirq; +	int bank_id = GPIO_BANK(gpio); +	int bit = GPIO_BIT(gpio); +	u32 val; +	unsigned long flags; + +	kona_gpio = irq_data_get_irq_chip_data(d); +	reg_base = kona_gpio->reg_base; +	spin_lock_irqsave(&kona_gpio->lock, flags); + +	val = readl(reg_base + GPIO_INT_MASK(bank_id)); +	val |= BIT(bit); +	writel(val, reg_base + GPIO_INT_MASK(bank_id)); + +	spin_unlock_irqrestore(&kona_gpio->lock, flags); +} + +static void bcm_kona_gpio_irq_unmask(struct irq_data *d) +{ +	struct bcm_kona_gpio *kona_gpio; +	void __iomem *reg_base; +	unsigned gpio = d->hwirq; +	int bank_id = GPIO_BANK(gpio); +	int bit = GPIO_BIT(gpio); +	u32 val; +	unsigned long flags; + +	kona_gpio = irq_data_get_irq_chip_data(d); +	reg_base = kona_gpio->reg_base; +	spin_lock_irqsave(&kona_gpio->lock, flags); + +	val = readl(reg_base + GPIO_INT_MSKCLR(bank_id)); +	val |= BIT(bit); +	writel(val, reg_base + GPIO_INT_MSKCLR(bank_id)); + +	spin_unlock_irqrestore(&kona_gpio->lock, flags); +} + +static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type) +{ +	struct bcm_kona_gpio *kona_gpio; +	void __iomem *reg_base; +	unsigned gpio = d->hwirq; +	u32 lvl_type; +	u32 val; +	unsigned long flags; + +	kona_gpio = irq_data_get_irq_chip_data(d); +	reg_base = kona_gpio->reg_base; +	switch (type & IRQ_TYPE_SENSE_MASK) { +	case IRQ_TYPE_EDGE_RISING: +		lvl_type = GPIO_GPCTR0_ITR_CMD_RISING_EDGE; +		break; + +	case IRQ_TYPE_EDGE_FALLING: +		lvl_type = GPIO_GPCTR0_ITR_CMD_FALLING_EDGE; +		break; + +	case IRQ_TYPE_EDGE_BOTH: +		lvl_type = GPIO_GPCTR0_ITR_CMD_BOTH_EDGE; +		break; + +	case IRQ_TYPE_LEVEL_HIGH: +	case IRQ_TYPE_LEVEL_LOW: +		/* BCM GPIO doesn't support level triggering */ +	default: +		dev_err(kona_gpio->gpio_chip.dev, +			"Invalid BCM GPIO irq type 0x%x\n", type); +		return -EINVAL; +	} + +	spin_lock_irqsave(&kona_gpio->lock, flags); + +	val = readl(reg_base + GPIO_CONTROL(gpio)); +	val &= ~GPIO_GPCTR0_ITR_MASK; +	val |= lvl_type << GPIO_GPCTR0_ITR_SHIFT; +	writel(val, reg_base + GPIO_CONTROL(gpio)); + +	spin_unlock_irqrestore(&kona_gpio->lock, flags); + +	return 0; +} + +static void bcm_kona_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) +{ +	void __iomem *reg_base; +	int bit, bank_id; +	unsigned long sta; +	struct bcm_kona_gpio_bank *bank = irq_get_handler_data(irq); +	struct irq_chip *chip = irq_desc_get_chip(desc); + +	chained_irq_enter(chip, desc); + +	/* +	 * For bank interrupts, we can't use chip_data to store the kona_gpio +	 * pointer, since GIC needs it for its own purposes. Therefore, we get +	 * our pointer from the bank structure. +	 */ +	reg_base = bank->kona_gpio->reg_base; +	bank_id = bank->id; + +	while ((sta = readl(reg_base + GPIO_INT_STATUS(bank_id)) & +		    (~(readl(reg_base + GPIO_INT_MASK(bank_id)))))) { +		for_each_set_bit(bit, &sta, 32) { +			int hwirq = GPIO_PER_BANK * bank_id + bit; +			int child_irq = +				irq_find_mapping(bank->kona_gpio->irq_domain, +						 hwirq); +			/* +			 * Clear interrupt before handler is called so we don't +			 * miss any interrupt occurred during executing them. +			 */ +			writel(readl(reg_base + GPIO_INT_STATUS(bank_id)) | +			       BIT(bit), reg_base + GPIO_INT_STATUS(bank_id)); +			/* Invoke interrupt handler */ +			generic_handle_irq(child_irq); +		} +	} + +	chained_irq_exit(chip, desc); +} + +static int bcm_kona_gpio_irq_reqres(struct irq_data *d) +{ +	struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d); + +	if (gpio_lock_as_irq(&kona_gpio->gpio_chip, d->hwirq)) { +		dev_err(kona_gpio->gpio_chip.dev, +			"unable to lock HW IRQ %lu for IRQ\n", +			d->hwirq); +		return -EINVAL; +	} +	return 0; +} + +static void bcm_kona_gpio_irq_relres(struct irq_data *d) +{ +	struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d); + +	gpio_unlock_as_irq(&kona_gpio->gpio_chip, d->hwirq); +} + +static struct irq_chip bcm_gpio_irq_chip = { +	.name = "bcm-kona-gpio", +	.irq_ack = bcm_kona_gpio_irq_ack, +	.irq_mask = bcm_kona_gpio_irq_mask, +	.irq_unmask = bcm_kona_gpio_irq_unmask, +	.irq_set_type = bcm_kona_gpio_irq_set_type, +	.irq_request_resources = bcm_kona_gpio_irq_reqres, +	.irq_release_resources = bcm_kona_gpio_irq_relres, +}; + +static struct __initconst of_device_id bcm_kona_gpio_of_match[] = { +	{ .compatible = "brcm,kona-gpio" }, +	{} +}; + +MODULE_DEVICE_TABLE(of, bcm_kona_gpio_of_match); + +/* + * This lock class tells lockdep that GPIO irqs are in a different + * category than their parents, so it won't report false recursion. + */ +static struct lock_class_key gpio_lock_class; + +static int bcm_kona_gpio_irq_map(struct irq_domain *d, unsigned int irq, +				 irq_hw_number_t hwirq) +{ +	int ret; + +	ret = irq_set_chip_data(irq, d->host_data); +	if (ret < 0) +		return ret; +	irq_set_lockdep_class(irq, &gpio_lock_class); +	irq_set_chip_and_handler(irq, &bcm_gpio_irq_chip, handle_simple_irq); +#ifdef CONFIG_ARM +	set_irq_flags(irq, IRQF_VALID); +#else +	irq_set_noprobe(irq); +#endif + +	return 0; +} + +static void bcm_kona_gpio_irq_unmap(struct irq_domain *d, unsigned int irq) +{ +	irq_set_chip_and_handler(irq, NULL, NULL); +	irq_set_chip_data(irq, NULL); +} + +static struct irq_domain_ops bcm_kona_irq_ops = { +	.map = bcm_kona_gpio_irq_map, +	.unmap = bcm_kona_gpio_irq_unmap, +	.xlate = irq_domain_xlate_twocell, +}; + +static void bcm_kona_gpio_reset(struct bcm_kona_gpio *kona_gpio) +{ +	void __iomem *reg_base; +	int i; + +	reg_base = kona_gpio->reg_base; +	/* disable interrupts and clear status */ +	for (i = 0; i < kona_gpio->num_bank; i++) { +		/* Unlock the entire bank first */ +		bcm_kona_gpio_write_lock_regs(kona_gpio, i, UNLOCK_CODE); +		writel(0xffffffff, reg_base + GPIO_INT_MASK(i)); +		writel(0xffffffff, reg_base + GPIO_INT_STATUS(i)); +		/* Now re-lock the bank */ +		bcm_kona_gpio_write_lock_regs(kona_gpio, i, LOCK_CODE); +	} +} + +static int bcm_kona_gpio_probe(struct platform_device *pdev) +{ +	struct device *dev = &pdev->dev; +	const struct of_device_id *match; +	struct resource *res; +	struct bcm_kona_gpio_bank *bank; +	struct bcm_kona_gpio *kona_gpio; +	struct gpio_chip *chip; +	int ret; +	int i; + +	match = of_match_device(bcm_kona_gpio_of_match, dev); +	if (!match) { +		dev_err(dev, "Failed to find gpio controller\n"); +		return -ENODEV; +	} + +	kona_gpio = devm_kzalloc(dev, sizeof(*kona_gpio), GFP_KERNEL); +	if (!kona_gpio) +		return -ENOMEM; + +	kona_gpio->gpio_chip = template_chip; +	chip = &kona_gpio->gpio_chip; +	kona_gpio->num_bank = of_irq_count(dev->of_node); +	if (kona_gpio->num_bank == 0) { +		dev_err(dev, "Couldn't determine # GPIO banks\n"); +		return -ENOENT; +	} +	if (kona_gpio->num_bank > GPIO_MAX_BANK_NUM) { +		dev_err(dev, "Too many GPIO banks configured (max=%d)\n", +			GPIO_MAX_BANK_NUM); +		return -ENXIO; +	} +	kona_gpio->banks = devm_kzalloc(dev, +					kona_gpio->num_bank * +					sizeof(*kona_gpio->banks), GFP_KERNEL); +	if (!kona_gpio->banks) +		return -ENOMEM; + +	kona_gpio->pdev = pdev; +	platform_set_drvdata(pdev, kona_gpio); +	chip->of_node = dev->of_node; +	chip->ngpio = kona_gpio->num_bank * GPIO_PER_BANK; + +	kona_gpio->irq_domain = irq_domain_add_linear(dev->of_node, +						      chip->ngpio, +						      &bcm_kona_irq_ops, +						      kona_gpio); +	if (!kona_gpio->irq_domain) { +		dev_err(dev, "Couldn't allocate IRQ domain\n"); +		return -ENXIO; +	} + +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	kona_gpio->reg_base = devm_ioremap_resource(dev, res); +	if (IS_ERR(kona_gpio->reg_base)) { +		ret = -ENXIO; +		goto err_irq_domain; +	} + +	for (i = 0; i < kona_gpio->num_bank; i++) { +		bank = &kona_gpio->banks[i]; +		bank->id = i; +		bank->irq = platform_get_irq(pdev, i); +		bank->kona_gpio = kona_gpio; +		if (bank->irq < 0) { +			dev_err(dev, "Couldn't get IRQ for bank %d", i); +			ret = -ENOENT; +			goto err_irq_domain; +		} +	} + +	dev_info(&pdev->dev, "Setting up Kona GPIO\n"); + +	bcm_kona_gpio_reset(kona_gpio); + +	ret = gpiochip_add(chip); +	if (ret < 0) { +		dev_err(dev, "Couldn't add GPIO chip -- %d\n", ret); +		goto err_irq_domain; +	} +	for (i = 0; i < chip->ngpio; i++) { +		int irq = bcm_kona_gpio_to_irq(chip, i); +		irq_set_lockdep_class(irq, &gpio_lock_class); +		irq_set_chip_and_handler(irq, &bcm_gpio_irq_chip, +					 handle_simple_irq); +#ifdef CONFIG_ARM +		set_irq_flags(irq, IRQF_VALID); +#else +		irq_set_noprobe(irq); +#endif +	} +	for (i = 0; i < kona_gpio->num_bank; i++) { +		bank = &kona_gpio->banks[i]; +		irq_set_chained_handler(bank->irq, bcm_kona_gpio_irq_handler); +		irq_set_handler_data(bank->irq, bank); +	} + +	spin_lock_init(&kona_gpio->lock); + +	return 0; + +err_irq_domain: +	irq_domain_remove(kona_gpio->irq_domain); + +	return ret; +} + +static struct platform_driver bcm_kona_gpio_driver = { +	.driver = { +			.name = "bcm-kona-gpio", +			.owner = THIS_MODULE, +			.of_match_table = bcm_kona_gpio_of_match, +	}, +	.probe = bcm_kona_gpio_probe, +}; + +module_platform_driver(bcm_kona_gpio_driver); + +MODULE_AUTHOR("Broadcom Corporation <bcm-kernel-feedback-list@broadcom.com>"); +MODULE_DESCRIPTION("Broadcom Kona GPIO Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpio/gpio-bt8xx.c b/drivers/gpio/gpio-bt8xx.c index 8369e71ebe4..6557147d933 100644 --- a/drivers/gpio/gpio-bt8xx.c +++ b/drivers/gpio/gpio-bt8xx.c @@ -169,7 +169,7 @@ static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg)  	c->dbg_show = NULL;  	c->base = modparam_gpiobase;  	c->ngpio = BT8XXGPIO_NR_GPIOS; -	c->can_sleep = 0; +	c->can_sleep = false;  }  static int bt8xxgpio_probe(struct pci_dev *dev, @@ -178,7 +178,7 @@ static int bt8xxgpio_probe(struct pci_dev *dev,  	struct bt8xxgpio *bg;  	int err; -	bg = kzalloc(sizeof(*bg), GFP_KERNEL); +	bg = devm_kzalloc(&dev->dev, sizeof(struct bt8xxgpio), GFP_KERNEL);  	if (!bg)  		return -ENOMEM; @@ -188,9 +188,9 @@ static int bt8xxgpio_probe(struct pci_dev *dev,  	err = pci_enable_device(dev);  	if (err) {  		printk(KERN_ERR "bt8xxgpio: Can't enable device.\n"); -		goto err_freebg; +		return err;  	} -	if (!request_mem_region(pci_resource_start(dev, 0), +	if (!devm_request_mem_region(&dev->dev, pci_resource_start(dev, 0),  				pci_resource_len(dev, 0),  				"bt8xxgpio")) {  		printk(KERN_WARNING "bt8xxgpio: Can't request iomem (0x%llx).\n", @@ -201,11 +201,11 @@ static int bt8xxgpio_probe(struct pci_dev *dev,  	pci_set_master(dev);  	pci_set_drvdata(dev, bg); -	bg->mmio = ioremap(pci_resource_start(dev, 0), 0x1000); +	bg->mmio = devm_ioremap(&dev->dev, pci_resource_start(dev, 0), 0x1000);  	if (!bg->mmio) {  		printk(KERN_ERR "bt8xxgpio: ioremap() failed\n");  		err = -EIO; -		goto err_release_mem; +		goto err_disable;  	}  	/* Disable interrupts */ @@ -220,19 +220,13 @@ static int bt8xxgpio_probe(struct pci_dev *dev,  	err = gpiochip_add(&bg->gpio);  	if (err) {  		printk(KERN_ERR "bt8xxgpio: Failed to register GPIOs\n"); -		goto err_release_mem; +		goto err_disable;  	}  	return 0; -err_release_mem: -	release_mem_region(pci_resource_start(dev, 0), -			   pci_resource_len(dev, 0)); -	pci_set_drvdata(dev, NULL);  err_disable:  	pci_disable_device(dev); -err_freebg: -	kfree(bg);  	return err;  } @@ -251,9 +245,6 @@ static void bt8xxgpio_remove(struct pci_dev *pdev)  	release_mem_region(pci_resource_start(pdev, 0),  			   pci_resource_len(pdev, 0));  	pci_disable_device(pdev); - -	pci_set_drvdata(pdev, NULL); -	kfree(bg);  }  #ifdef CONFIG_PM @@ -310,7 +301,7 @@ static int bt8xxgpio_resume(struct pci_dev *pdev)  #define bt8xxgpio_resume NULL  #endif /* CONFIG_PM */ -static DEFINE_PCI_DEVICE_TABLE(bt8xxgpio_pci_tbl) = { +static const struct pci_device_id bt8xxgpio_pci_tbl[] = {  	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) },  	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) },  	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) }, diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c index 0edaf2ce926..e1e861239e9 100644 --- a/drivers/gpio/gpio-clps711x.c +++ b/drivers/gpio/gpio-clps711x.c @@ -65,6 +65,7 @@ static int clps711x_gpio_probe(struct platform_device *pdev)  	}  	bgc->gc.base = id * 8; +	bgc->gc.owner = THIS_MODULE;  	platform_set_drvdata(pdev, bgc);  	return gpiochip_add(&bgc->gc); @@ -77,7 +78,7 @@ static int clps711x_gpio_remove(struct platform_device *pdev)  	return bgpio_remove(bgc);  } -static const struct of_device_id clps711x_gpio_ids[] = { +static const struct of_device_id __maybe_unused clps711x_gpio_ids[] = {  	{ .compatible = "cirrus,clps711x-gpio" },  	{ }  }; @@ -97,3 +98,4 @@ module_platform_driver(clps711x_gpio_driver);  MODULE_LICENSE("GPL");  MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");  MODULE_DESCRIPTION("CLPS711X GPIO driver"); +MODULE_ALIAS("platform:clps711x-gpio"); diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c index 9b77dc05d4a..416cdf786b0 100644 --- a/drivers/gpio/gpio-da9052.c +++ b/drivers/gpio/gpio-da9052.c @@ -200,7 +200,7 @@ static struct gpio_chip reference_gp = {  	.direction_input = da9052_gpio_direction_input,  	.direction_output = da9052_gpio_direction_output,  	.to_irq = da9052_gpio_to_irq, -	.can_sleep = 1, +	.can_sleep = true,  	.ngpio = 16,  	.base = -1,  }; diff --git a/drivers/gpio/gpio-da9055.c b/drivers/gpio/gpio-da9055.c index 7ef0820032b..f992997bc30 100644 --- a/drivers/gpio/gpio-da9055.c +++ b/drivers/gpio/gpio-da9055.c @@ -134,7 +134,7 @@ static struct gpio_chip reference_gp = {  	.direction_input = da9055_gpio_direction_input,  	.direction_output = da9055_gpio_direction_output,  	.to_irq = da9055_gpio_to_irq, -	.can_sleep = 1, +	.can_sleep = true,  	.ngpio = 3,  	.base = -1,  }; diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 17df6db5dca..9f0682534e2 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -15,8 +15,14 @@  #include <linux/clk.h>  #include <linux/err.h>  #include <linux/io.h> - -#include <asm/mach/irq.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/platform_data/gpio-davinci.h> +#include <linux/irqchip/chained_irq.h>  struct davinci_gpio_regs {  	u32	dir; @@ -31,13 +37,16 @@ struct davinci_gpio_regs {  	u32	intstat;  }; +typedef struct irq_chip *(*gpio_get_irq_chip_cb_t)(unsigned int irq); + +#define BINTEN	0x8 /* GPIO Interrupt Per-Bank Enable Register */ +  #define chip2controller(chip)	\  	container_of(chip, struct davinci_gpio_controller, chip) -static struct davinci_gpio_controller chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)];  static void __iomem *gpio_base; -static struct davinci_gpio_regs __iomem __init *gpio2regs(unsigned gpio) +static struct davinci_gpio_regs __iomem *gpio2regs(unsigned gpio)  {  	void __iomem *ptr; @@ -65,7 +74,7 @@ static inline struct davinci_gpio_regs __iomem *irq2regs(int irq)  	return g;  } -static int __init davinci_gpio_irq_setup(void); +static int davinci_gpio_irq_setup(struct platform_device *pdev);  /*--------------------------------------------------------------------------*/ @@ -80,14 +89,14 @@ static inline int __davinci_direction(struct gpio_chip *chip,  	u32 mask = 1 << offset;  	spin_lock_irqsave(&d->lock, flags); -	temp = __raw_readl(&g->dir); +	temp = readl_relaxed(&g->dir);  	if (out) {  		temp &= ~mask; -		__raw_writel(mask, value ? &g->set_data : &g->clr_data); +		writel_relaxed(mask, value ? &g->set_data : &g->clr_data);  	} else {  		temp |= mask;  	} -	__raw_writel(temp, &g->dir); +	writel_relaxed(temp, &g->dir);  	spin_unlock_irqrestore(&d->lock, flags);  	return 0; @@ -116,7 +125,7 @@ static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset)  	struct davinci_gpio_controller *d = chip2controller(chip);  	struct davinci_gpio_regs __iomem *g = d->regs; -	return (1 << offset) & __raw_readl(&g->in_data); +	return (1 << offset) & readl_relaxed(&g->in_data);  }  /* @@ -128,37 +137,112 @@ davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value)  	struct davinci_gpio_controller *d = chip2controller(chip);  	struct davinci_gpio_regs __iomem *g = d->regs; -	__raw_writel((1 << offset), value ? &g->set_data : &g->clr_data); +	writel_relaxed((1 << offset), value ? &g->set_data : &g->clr_data); +} + +static struct davinci_gpio_platform_data * +davinci_gpio_get_pdata(struct platform_device *pdev) +{ +	struct device_node *dn = pdev->dev.of_node; +	struct davinci_gpio_platform_data *pdata; +	int ret; +	u32 val; + +	if (!IS_ENABLED(CONFIG_OF) || !pdev->dev.of_node) +		return pdev->dev.platform_data; + +	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); +	if (!pdata) +		return NULL; + +	ret = of_property_read_u32(dn, "ti,ngpio", &val); +	if (ret) +		goto of_err; + +	pdata->ngpio = val; + +	ret = of_property_read_u32(dn, "ti,davinci-gpio-unbanked", &val); +	if (ret) +		goto of_err; + +	pdata->gpio_unbanked = val; + +	return pdata; + +of_err: +	dev_err(&pdev->dev, "Populating pdata from DT failed: err %d\n", ret); +	return NULL;  } -static int __init davinci_gpio_setup(void) +#ifdef CONFIG_OF_GPIO +static int davinci_gpio_of_xlate(struct gpio_chip *gc, +			     const struct of_phandle_args *gpiospec, +			     u32 *flags) +{ +	struct davinci_gpio_controller *chips = dev_get_drvdata(gc->dev); +	struct davinci_gpio_platform_data *pdata = dev_get_platdata(gc->dev); + +	if (gpiospec->args[0] > pdata->ngpio) +		return -EINVAL; + +	if (gc != &chips[gpiospec->args[0] / 32].chip) +		return -EINVAL; + +	if (flags) +		*flags = gpiospec->args[1]; + +	return gpiospec->args[0] % 32; +} +#endif + +static int davinci_gpio_probe(struct platform_device *pdev)  {  	int i, base;  	unsigned ngpio; -	struct davinci_soc_info *soc_info = &davinci_soc_info; -	struct davinci_gpio_regs *regs; +	struct davinci_gpio_controller *chips; +	struct davinci_gpio_platform_data *pdata; +	struct davinci_gpio_regs __iomem *regs; +	struct device *dev = &pdev->dev; +	struct resource *res; + +	pdata = davinci_gpio_get_pdata(pdev); +	if (!pdata) { +		dev_err(dev, "No platform data found\n"); +		return -EINVAL; +	} -	if (soc_info->gpio_type != GPIO_TYPE_DAVINCI) -		return 0; +	dev->platform_data = pdata;  	/*  	 * The gpio banks conceptually expose a segmented bitmap,  	 * and "ngpio" is one more than the largest zero-based  	 * bit index that's valid.  	 */ -	ngpio = soc_info->gpio_num; +	ngpio = pdata->ngpio;  	if (ngpio == 0) { -		pr_err("GPIO setup:  how many GPIOs?\n"); +		dev_err(dev, "How many GPIOs?\n");  		return -EINVAL;  	} -	if (WARN_ON(DAVINCI_N_GPIO < ngpio)) -		ngpio = DAVINCI_N_GPIO; +	if (WARN_ON(ARCH_NR_GPIOS < ngpio)) +		ngpio = ARCH_NR_GPIOS; -	gpio_base = ioremap(soc_info->gpio_base, SZ_4K); -	if (WARN_ON(!gpio_base)) +	chips = devm_kzalloc(dev, +			     ngpio * sizeof(struct davinci_gpio_controller), +			     GFP_KERNEL); +	if (!chips)  		return -ENOMEM; +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	if (!res) { +		dev_err(dev, "Invalid memory resource\n"); +		return -EBUSY; +	} + +	gpio_base = devm_ioremap_resource(dev, res); +	if (IS_ERR(gpio_base)) +		return PTR_ERR(gpio_base); +  	for (i = 0, base = 0; base < ngpio; i++, base += 32) {  		chips[i].chip.label = "DaVinci"; @@ -172,6 +256,12 @@ static int __init davinci_gpio_setup(void)  		if (chips[i].chip.ngpio > 32)  			chips[i].chip.ngpio = 32; +#ifdef CONFIG_OF_GPIO +		chips[i].chip.of_gpio_n_cells = 2; +		chips[i].chip.of_xlate = davinci_gpio_of_xlate; +		chips[i].chip.dev = dev; +		chips[i].chip.of_node = dev->of_node; +#endif  		spin_lock_init(&chips[i].lock);  		regs = gpio2regs(base); @@ -183,13 +273,10 @@ static int __init davinci_gpio_setup(void)  		gpiochip_add(&chips[i].chip);  	} -	soc_info->gpio_ctlrs = chips; -	soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32); - -	davinci_gpio_irq_setup(); +	platform_set_drvdata(pdev, chips); +	davinci_gpio_irq_setup(pdev);  	return 0;  } -pure_initcall(davinci_gpio_setup);  /*--------------------------------------------------------------------------*/  /* @@ -208,8 +295,8 @@ static void gpio_irq_disable(struct irq_data *d)  	struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);  	u32 mask = (u32) irq_data_get_irq_handler_data(d); -	__raw_writel(mask, &g->clr_falling); -	__raw_writel(mask, &g->clr_rising); +	writel_relaxed(mask, &g->clr_falling); +	writel_relaxed(mask, &g->clr_rising);  }  static void gpio_irq_enable(struct irq_data *d) @@ -223,9 +310,9 @@ static void gpio_irq_enable(struct irq_data *d)  		status = IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;  	if (status & IRQ_TYPE_EDGE_FALLING) -		__raw_writel(mask, &g->set_falling); +		writel_relaxed(mask, &g->set_falling);  	if (status & IRQ_TYPE_EDGE_RISING) -		__raw_writel(mask, &g->set_rising); +		writel_relaxed(mask, &g->set_rising);  }  static int gpio_irq_type(struct irq_data *d, unsigned trigger) @@ -259,34 +346,28 @@ gpio_irq_handler(unsigned irq, struct irq_desc *desc)  		mask <<= 16;  	/* temporarily mask (level sensitive) parent IRQ */ -	desc->irq_data.chip->irq_mask(&desc->irq_data); -	desc->irq_data.chip->irq_ack(&desc->irq_data); +	chained_irq_enter(irq_desc_get_chip(desc), desc);  	while (1) {  		u32		status; -		int		n; -		int		res; +		int		bit;  		/* ack any irqs */ -		status = __raw_readl(&g->intstat) & mask; +		status = readl_relaxed(&g->intstat) & mask;  		if (!status)  			break; -		__raw_writel(status, &g->intstat); +		writel_relaxed(status, &g->intstat);  		/* now demux them to the right lowlevel handler */ -		n = d->irq_base; -		if (irq & 1) { -			n += 16; -			status >>= 16; -		}  		while (status) { -			res = ffs(status); -			n += res; -			generic_handle_irq(n - 1); -			status >>= res; +			bit = __ffs(status); +			status &= ~BIT(bit); +			generic_handle_irq( +				irq_find_mapping(d->irq_domain, +						 d->chip.base + bit));  		}  	} -	desc->irq_data.chip->irq_unmask(&desc->irq_data); +	chained_irq_exit(irq_desc_get_chip(desc), desc);  	/* now it may re-trigger */  } @@ -294,21 +375,22 @@ static int gpio_to_irq_banked(struct gpio_chip *chip, unsigned offset)  {  	struct davinci_gpio_controller *d = chip2controller(chip); -	if (d->irq_base >= 0) -		return d->irq_base + offset; +	if (d->irq_domain) +		return irq_create_mapping(d->irq_domain, d->chip.base + offset);  	else -		return -ENODEV; +		return -ENXIO;  }  static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset)  { -	struct davinci_soc_info *soc_info = &davinci_soc_info; +	struct davinci_gpio_controller *d = chip2controller(chip); -	/* NOTE:  we assume for now that only irqs in the first gpio_chip +	/* +	 * NOTE:  we assume for now that only irqs in the first gpio_chip  	 * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs).  	 */ -	if (offset < soc_info->gpio_unbanked) -		return soc_info->gpio_irq + offset; +	if (offset < d->gpio_unbanked) +		return d->gpio_irq + offset;  	else  		return -ENODEV;  } @@ -317,24 +399,64 @@ static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger)  {  	struct davinci_gpio_controller *d;  	struct davinci_gpio_regs __iomem *g; -	struct davinci_soc_info *soc_info = &davinci_soc_info;  	u32 mask;  	d = (struct davinci_gpio_controller *)data->handler_data;  	g = (struct davinci_gpio_regs __iomem *)d->regs; -	mask = __gpio_mask(data->irq - soc_info->gpio_irq); +	mask = __gpio_mask(data->irq - d->gpio_irq);  	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))  		return -EINVAL; -	__raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING) +	writel_relaxed(mask, (trigger & IRQ_TYPE_EDGE_FALLING)  		     ? &g->set_falling : &g->clr_falling); -	__raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING) +	writel_relaxed(mask, (trigger & IRQ_TYPE_EDGE_RISING)  		     ? &g->set_rising : &g->clr_rising);  	return 0;  } +static int +davinci_gpio_irq_map(struct irq_domain *d, unsigned int irq, +		     irq_hw_number_t hw) +{ +	struct davinci_gpio_regs __iomem *g = gpio2regs(hw); + +	irq_set_chip_and_handler_name(irq, &gpio_irqchip, handle_simple_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)); +	set_irq_flags(irq, IRQF_VALID); + +	return 0; +} + +static const struct irq_domain_ops davinci_gpio_irq_ops = { +	.map = davinci_gpio_irq_map, +	.xlate = irq_domain_xlate_onetwocell, +}; + +static struct irq_chip *davinci_gpio_get_irq_chip(unsigned int irq) +{ +	static struct irq_chip_type gpio_unbanked; + +	gpio_unbanked = *container_of(irq_get_chip(irq), +				      struct irq_chip_type, chip); + +	return &gpio_unbanked.chip; +}; + +static struct irq_chip *keystone_gpio_get_irq_chip(unsigned int irq) +{ +	static struct irq_chip gpio_unbanked; + +	gpio_unbanked = *irq_get_chip(irq); +	return &gpio_unbanked; +}; + +static const struct of_device_id davinci_gpio_ids[]; +  /*   * NOTE:  for suspend/resume, probably best to make a platform_device with   * suspend_late/resume_resume calls hooking into results of the set_wake() @@ -343,24 +465,47 @@ static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger)   * (dm6446) can be set appropriately for GPIOV33 pins.   */ -static int __init davinci_gpio_irq_setup(void) +static int davinci_gpio_irq_setup(struct platform_device *pdev)  { -	unsigned	gpio, irq, bank; +	unsigned	gpio, bank; +	int		irq;  	struct clk	*clk;  	u32		binten = 0;  	unsigned	ngpio, bank_irq; -	struct davinci_soc_info *soc_info = &davinci_soc_info; -	struct davinci_gpio_regs	__iomem *g; +	struct device *dev = &pdev->dev; +	struct resource	*res; +	struct davinci_gpio_controller *chips = platform_get_drvdata(pdev); +	struct davinci_gpio_platform_data *pdata = dev->platform_data; +	struct davinci_gpio_regs __iomem *g; +	struct irq_domain	*irq_domain = NULL; +	const struct of_device_id *match; +	struct irq_chip *irq_chip; +	gpio_get_irq_chip_cb_t gpio_get_irq_chip; + +	/* +	 * Use davinci_gpio_get_irq_chip by default to handle non DT cases +	 */ +	gpio_get_irq_chip = davinci_gpio_get_irq_chip; +	match = of_match_device(of_match_ptr(davinci_gpio_ids), +				dev); +	if (match) +		gpio_get_irq_chip = (gpio_get_irq_chip_cb_t)match->data; + +	ngpio = pdata->ngpio; +	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); +	if (!res) { +		dev_err(dev, "Invalid IRQ resource\n"); +		return -EBUSY; +	} -	ngpio = soc_info->gpio_num; +	bank_irq = res->start; -	bank_irq = soc_info->gpio_irq; -	if (bank_irq == 0) { -		printk(KERN_ERR "Don't know first GPIO bank IRQ.\n"); -		return -EINVAL; +	if (!bank_irq) { +		dev_err(dev, "Invalid IRQ resource\n"); +		return -ENODEV;  	} -	clk = clk_get(NULL, "gpio"); +	clk = devm_clk_get(dev, "gpio");  	if (IS_ERR(clk)) {  		printk(KERN_ERR "Error %ld getting gpio clock?\n",  		       PTR_ERR(clk)); @@ -368,16 +513,31 @@ static int __init davinci_gpio_irq_setup(void)  	}  	clk_prepare_enable(clk); -	/* Arrange gpio_to_irq() support, handling either direct IRQs or +	if (!pdata->gpio_unbanked) { +		irq = irq_alloc_descs(-1, 0, ngpio, 0); +		if (irq < 0) { +			dev_err(dev, "Couldn't allocate IRQ numbers\n"); +			return irq; +		} + +		irq_domain = irq_domain_add_legacy(NULL, ngpio, irq, 0, +							&davinci_gpio_irq_ops, +							chips); +		if (!irq_domain) { +			dev_err(dev, "Couldn't register an IRQ domain\n"); +			return -ENODEV; +		} +	} + +	/* +	 * Arrange gpio_to_irq() support, handling either direct IRQs or  	 * banked IRQs.  Having GPIOs in the first GPIO bank use direct  	 * IRQs, while the others use banked IRQs, would need some setup  	 * tweaks to recognize hardware which can do that.  	 */  	for (gpio = 0, bank = 0; gpio < ngpio; bank++, gpio += 32) {  		chips[bank].chip.to_irq = gpio_to_irq_banked; -		chips[bank].irq_base = soc_info->gpio_unbanked -			? -EINVAL -			: (soc_info->intc_irq_num + gpio); +		chips[bank].irq_domain = irq_domain;  	}  	/* @@ -385,28 +545,27 @@ static int __init davinci_gpio_irq_setup(void)  	 * controller only handling trigger modes.  We currently assume no  	 * IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs.  	 */ -	if (soc_info->gpio_unbanked) { -		static struct irq_chip_type gpio_unbanked; - +	if (pdata->gpio_unbanked) {  		/* pass "bank 0" GPIO IRQs to AINTC */  		chips[0].chip.to_irq = gpio_to_irq_unbanked; +		chips[0].gpio_irq = bank_irq; +		chips[0].gpio_unbanked = pdata->gpio_unbanked;  		binten = BIT(0);  		/* AINTC handles mask/unmask; GPIO handles triggering */  		irq = bank_irq; -		gpio_unbanked = *container_of(irq_get_chip(irq), -					      struct irq_chip_type, chip); -		gpio_unbanked.chip.name = "GPIO-AINTC"; -		gpio_unbanked.chip.irq_set_type = gpio_irq_type_unbanked; +		irq_chip = gpio_get_irq_chip(irq); +		irq_chip->name = "GPIO-AINTC"; +		irq_chip->irq_set_type = gpio_irq_type_unbanked;  		/* default trigger: both edges */  		g = gpio2regs(0); -		__raw_writel(~0, &g->set_falling); -		__raw_writel(~0, &g->set_rising); +		writel_relaxed(~0, &g->set_falling); +		writel_relaxed(~0, &g->set_rising);  		/* set the direct IRQs up to use that irqchip */ -		for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) { -			irq_set_chip(irq, &gpio_unbanked.chip); +		for (gpio = 0; gpio < pdata->gpio_unbanked; gpio++, irq++) { +			irq_set_chip(irq, irq_chip);  			irq_set_handler_data(irq, &chips[gpio / 32]);  			irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH);  		} @@ -418,15 +577,11 @@ static int __init davinci_gpio_irq_setup(void)  	 * Or, AINTC can handle IRQs for banks of 16 GPIO IRQs, which we  	 * then chain through our own handler.  	 */ -	for (gpio = 0, irq = gpio_to_irq(0), bank = 0; -			gpio < ngpio; -			bank++, bank_irq++) { -		unsigned		i; - +	for (gpio = 0, bank = 0; gpio < ngpio; bank++, bank_irq++, gpio += 16) {  		/* disabled by default, enabled only as needed */  		g = gpio2regs(gpio); -		__raw_writel(~0, &g->clr_falling); -		__raw_writel(~0, &g->clr_rising); +		writel_relaxed(~0, &g->clr_falling); +		writel_relaxed(~0, &g->clr_rising);  		/* set up all irqs in this bank */  		irq_set_chained_handler(bank_irq, gpio_irq_handler); @@ -438,24 +593,43 @@ static int __init davinci_gpio_irq_setup(void)  		 */  		irq_set_handler_data(bank_irq, &chips[gpio / 32]); -		for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) { -			irq_set_chip(irq, &gpio_irqchip); -			irq_set_chip_data(irq, (__force void *)g); -			irq_set_handler_data(irq, (void *)__gpio_mask(gpio)); -			irq_set_handler(irq, handle_simple_irq); -			set_irq_flags(irq, IRQF_VALID); -		} -  		binten |= BIT(bank);  	}  done: -	/* BINTEN -- per-bank interrupt enable. genirq would also let these +	/* +	 * BINTEN -- per-bank interrupt enable. genirq would also let these  	 * bits be set/cleared dynamically.  	 */ -	__raw_writel(binten, gpio_base + 0x08); - -	printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0)); +	writel_relaxed(binten, gpio_base + BINTEN);  	return 0;  } + +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id davinci_gpio_ids[] = { +	{ .compatible = "ti,keystone-gpio", keystone_gpio_get_irq_chip}, +	{ .compatible = "ti,dm6441-gpio", davinci_gpio_get_irq_chip}, +	{ /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, davinci_gpio_ids); +#endif + +static struct platform_driver davinci_gpio_driver = { +	.probe		= davinci_gpio_probe, +	.driver		= { +		.name		= "davinci_gpio", +		.owner		= THIS_MODULE, +		.of_match_table	= of_match_ptr(davinci_gpio_ids), +	}, +}; + +/** + * GPIO driver registration needs to be done before machine_init functions + * access GPIO. Hence davinci_gpio_drv_reg() is a postcore_initcall. + */ +static int __init davinci_gpio_drv_reg(void) +{ +	return platform_driver_register(&davinci_gpio_driver); +} +postcore_initcall(davinci_gpio_drv_reg); diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c new file mode 100644 index 00000000000..cd3b8143527 --- /dev/null +++ b/drivers/gpio/gpio-dwapb.c @@ -0,0 +1,444 @@ +/* + * 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/basic_mmio_gpio.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/platform_device.h> +#include <linux/spinlock.h> + +#define GPIO_SWPORTA_DR		0x00 +#define GPIO_SWPORTA_DDR	0x04 +#define GPIO_SWPORTB_DR		0x0c +#define GPIO_SWPORTB_DDR	0x10 +#define GPIO_SWPORTC_DR		0x18 +#define GPIO_SWPORTC_DDR	0x1c +#define GPIO_SWPORTD_DR		0x24 +#define GPIO_SWPORTD_DDR	0x28 +#define GPIO_INTEN		0x30 +#define GPIO_INTMASK		0x34 +#define GPIO_INTTYPE_LEVEL	0x38 +#define GPIO_INT_POLARITY	0x3c +#define GPIO_INTSTATUS		0x40 +#define GPIO_PORTA_EOI		0x4c +#define GPIO_EXT_PORTA		0x50 +#define GPIO_EXT_PORTB		0x54 +#define GPIO_EXT_PORTC		0x58 +#define GPIO_EXT_PORTD		0x5c + +#define DWAPB_MAX_PORTS		4 +#define GPIO_EXT_PORT_SIZE	(GPIO_EXT_PORTB - GPIO_EXT_PORTA) +#define GPIO_SWPORT_DR_SIZE	(GPIO_SWPORTB_DR - GPIO_SWPORTA_DR) +#define GPIO_SWPORT_DDR_SIZE	(GPIO_SWPORTB_DDR - GPIO_SWPORTA_DDR) + +struct dwapb_gpio; + +struct dwapb_gpio_port { +	struct bgpio_chip	bgc; +	bool			is_registered; +	struct dwapb_gpio	*gpio; +}; + +struct dwapb_gpio { +	struct	device		*dev; +	void __iomem		*regs; +	struct dwapb_gpio_port	*ports; +	unsigned int		nr_ports; +	struct irq_domain	*domain; +}; + +static int dwapb_gpio_to_irq(struct gpio_chip *gc, unsigned offset) +{ +	struct bgpio_chip *bgc = to_bgpio_chip(gc); +	struct dwapb_gpio_port *port = container_of(bgc, struct +						    dwapb_gpio_port, bgc); +	struct dwapb_gpio *gpio = port->gpio; + +	return irq_find_mapping(gpio->domain, offset); +} + +static void dwapb_toggle_trigger(struct dwapb_gpio *gpio, unsigned int offs) +{ +	u32 v = readl(gpio->regs + GPIO_INT_POLARITY); + +	if (gpio_get_value(gpio->ports[0].bgc.gc.base + offs)) +		v &= ~BIT(offs); +	else +		v |= BIT(offs); + +	writel(v, gpio->regs + GPIO_INT_POLARITY); +} + +static void dwapb_irq_handler(u32 irq, struct irq_desc *desc) +{ +	struct dwapb_gpio *gpio = irq_get_handler_data(irq); +	struct irq_chip *chip = irq_desc_get_chip(desc); +	u32 irq_status = readl_relaxed(gpio->regs + GPIO_INTSTATUS); + +	while (irq_status) { +		int hwirq = fls(irq_status) - 1; +		int gpio_irq = irq_find_mapping(gpio->domain, hwirq); + +		generic_handle_irq(gpio_irq); +		irq_status &= ~BIT(hwirq); + +		if ((irq_get_trigger_type(gpio_irq) & IRQ_TYPE_SENSE_MASK) +			== IRQ_TYPE_EDGE_BOTH) +			dwapb_toggle_trigger(gpio, hwirq); +	} + +	if (chip->irq_eoi) +		chip->irq_eoi(irq_desc_get_irq_data(desc)); +} + +static void dwapb_irq_enable(struct irq_data *d) +{ +	struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d); +	struct dwapb_gpio *gpio = igc->private; +	struct bgpio_chip *bgc = &gpio->ports[0].bgc; +	unsigned long flags; +	u32 val; + +	spin_lock_irqsave(&bgc->lock, flags); +	val = readl(gpio->regs + GPIO_INTEN); +	val |= BIT(d->hwirq); +	writel(val, gpio->regs + GPIO_INTEN); +	spin_unlock_irqrestore(&bgc->lock, flags); +} + +static void dwapb_irq_disable(struct irq_data *d) +{ +	struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d); +	struct dwapb_gpio *gpio = igc->private; +	struct bgpio_chip *bgc = &gpio->ports[0].bgc; +	unsigned long flags; +	u32 val; + +	spin_lock_irqsave(&bgc->lock, flags); +	val = readl(gpio->regs + GPIO_INTEN); +	val &= ~BIT(d->hwirq); +	writel(val, gpio->regs + GPIO_INTEN); +	spin_unlock_irqrestore(&bgc->lock, flags); +} + +static int dwapb_irq_reqres(struct irq_data *d) +{ +	struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d); +	struct dwapb_gpio *gpio = igc->private; +	struct bgpio_chip *bgc = &gpio->ports[0].bgc; + +	if (gpio_lock_as_irq(&bgc->gc, irqd_to_hwirq(d))) { +		dev_err(gpio->dev, "unable to lock HW IRQ %lu for IRQ\n", +			irqd_to_hwirq(d)); +		return -EINVAL; +	} +	return 0; +} + +static void dwapb_irq_relres(struct irq_data *d) +{ +	struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d); +	struct dwapb_gpio *gpio = igc->private; +	struct bgpio_chip *bgc = &gpio->ports[0].bgc; + +	gpio_unlock_as_irq(&bgc->gc, irqd_to_hwirq(d)); +} + +static int dwapb_irq_set_type(struct irq_data *d, u32 type) +{ +	struct irq_chip_generic *igc = irq_data_get_irq_chip_data(d); +	struct dwapb_gpio *gpio = igc->private; +	struct bgpio_chip *bgc = &gpio->ports[0].bgc; +	int bit = d->hwirq; +	unsigned long level, polarity, flags; + +	if (type & ~(IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | +		     IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) +		return -EINVAL; + +	spin_lock_irqsave(&bgc->lock, flags); +	level = readl(gpio->regs + GPIO_INTTYPE_LEVEL); +	polarity = readl(gpio->regs + GPIO_INT_POLARITY); + +	switch (type) { +	case IRQ_TYPE_EDGE_BOTH: +		level |= BIT(bit); +		dwapb_toggle_trigger(gpio, bit); +		break; +	case IRQ_TYPE_EDGE_RISING: +		level |= BIT(bit); +		polarity |= BIT(bit); +		break; +	case IRQ_TYPE_EDGE_FALLING: +		level |= BIT(bit); +		polarity &= ~BIT(bit); +		break; +	case IRQ_TYPE_LEVEL_HIGH: +		level &= ~BIT(bit); +		polarity |= BIT(bit); +		break; +	case IRQ_TYPE_LEVEL_LOW: +		level &= ~BIT(bit); +		polarity &= ~BIT(bit); +		break; +	} + +	irq_setup_alt_chip(d, type); + +	writel(level, gpio->regs + GPIO_INTTYPE_LEVEL); +	writel(polarity, gpio->regs + GPIO_INT_POLARITY); +	spin_unlock_irqrestore(&bgc->lock, flags); + +	return 0; +} + +static void dwapb_configure_irqs(struct dwapb_gpio *gpio, +				 struct dwapb_gpio_port *port) +{ +	struct gpio_chip *gc = &port->bgc.gc; +	struct device_node *node =  gc->of_node; +	struct irq_chip_generic	*irq_gc; +	unsigned int hwirq, ngpio = gc->ngpio; +	struct irq_chip_type *ct; +	int err, irq, i; + +	irq = irq_of_parse_and_map(node, 0); +	if (!irq) { +		dev_warn(gpio->dev, "no irq for bank %s\n", +			port->bgc.gc.of_node->full_name); +		return; +	} + +	gpio->domain = irq_domain_add_linear(node, ngpio, +					     &irq_generic_chip_ops, gpio); +	if (!gpio->domain) +		return; + +	err = irq_alloc_domain_generic_chips(gpio->domain, ngpio, 2, +					     "gpio-dwapb", handle_level_irq, +					     IRQ_NOREQUEST, 0, +					     IRQ_GC_INIT_NESTED_LOCK); +	if (err) { +		dev_info(gpio->dev, "irq_alloc_domain_generic_chips failed\n"); +		irq_domain_remove(gpio->domain); +		gpio->domain = NULL; +		return; +	} + +	irq_gc = irq_get_domain_generic_chip(gpio->domain, 0); +	if (!irq_gc) { +		irq_domain_remove(gpio->domain); +		gpio->domain = NULL; +		return; +	} + +	irq_gc->reg_base = gpio->regs; +	irq_gc->private = gpio; + +	for (i = 0; i < 2; i++) { +		ct = &irq_gc->chip_types[i]; +		ct->chip.irq_ack = irq_gc_ack_set_bit; +		ct->chip.irq_mask = irq_gc_mask_set_bit; +		ct->chip.irq_unmask = irq_gc_mask_clr_bit; +		ct->chip.irq_set_type = dwapb_irq_set_type; +		ct->chip.irq_enable = dwapb_irq_enable; +		ct->chip.irq_disable = dwapb_irq_disable; +		ct->chip.irq_request_resources = dwapb_irq_reqres; +		ct->chip.irq_release_resources = dwapb_irq_relres; +		ct->regs.ack = GPIO_PORTA_EOI; +		ct->regs.mask = GPIO_INTMASK; +		ct->type = IRQ_TYPE_LEVEL_MASK; +	} + +	irq_gc->chip_types[0].type = IRQ_TYPE_LEVEL_MASK; +	irq_gc->chip_types[1].type = IRQ_TYPE_EDGE_BOTH; +	irq_gc->chip_types[1].handler = handle_edge_irq; + +	irq_set_chained_handler(irq, dwapb_irq_handler); +	irq_set_handler_data(irq, gpio); + +	for (hwirq = 0 ; hwirq < ngpio ; hwirq++) +		irq_create_mapping(gpio->domain, hwirq); + +	port->bgc.gc.to_irq = dwapb_gpio_to_irq; +} + +static void dwapb_irq_teardown(struct dwapb_gpio *gpio) +{ +	struct dwapb_gpio_port *port = &gpio->ports[0]; +	struct gpio_chip *gc = &port->bgc.gc; +	unsigned int ngpio = gc->ngpio; +	irq_hw_number_t hwirq; + +	if (!gpio->domain) +		return; + +	for (hwirq = 0 ; hwirq < ngpio ; hwirq++) +		irq_dispose_mapping(irq_find_mapping(gpio->domain, hwirq)); + +	irq_domain_remove(gpio->domain); +	gpio->domain = NULL; +} + +static int dwapb_gpio_add_port(struct dwapb_gpio *gpio, +			       struct device_node *port_np, +			       unsigned int offs) +{ +	struct dwapb_gpio_port *port; +	u32 port_idx, ngpio; +	void __iomem *dat, *set, *dirout; +	int err; + +	if (of_property_read_u32(port_np, "reg", &port_idx) || +		port_idx >= DWAPB_MAX_PORTS) { +		dev_err(gpio->dev, "missing/invalid port index for %s\n", +			port_np->full_name); +		return -EINVAL; +	} + +	port = &gpio->ports[offs]; +	port->gpio = gpio; + +	if (of_property_read_u32(port_np, "snps,nr-gpios", &ngpio)) { +		dev_info(gpio->dev, "failed to get number of gpios for %s\n", +			 port_np->full_name); +		ngpio = 32; +	} + +	dat = gpio->regs + GPIO_EXT_PORTA + (port_idx * GPIO_EXT_PORT_SIZE); +	set = gpio->regs + GPIO_SWPORTA_DR + (port_idx * GPIO_SWPORT_DR_SIZE); +	dirout = gpio->regs + GPIO_SWPORTA_DDR + +		(port_idx * GPIO_SWPORT_DDR_SIZE); + +	err = bgpio_init(&port->bgc, gpio->dev, 4, dat, set, NULL, dirout, +			 NULL, false); +	if (err) { +		dev_err(gpio->dev, "failed to init gpio chip for %s\n", +			port_np->full_name); +		return err; +	} + +	port->bgc.gc.ngpio = ngpio; +	port->bgc.gc.of_node = port_np; + +	/* +	 * Only port A can provide interrupts in all configurations of the IP. +	 */ +	if (port_idx == 0 && +	    of_property_read_bool(port_np, "interrupt-controller")) +		dwapb_configure_irqs(gpio, port); + +	err = gpiochip_add(&port->bgc.gc); +	if (err) +		dev_err(gpio->dev, "failed to register gpiochip for %s\n", +			port_np->full_name); +	else +		port->is_registered = true; + +	return err; +} + +static void dwapb_gpio_unregister(struct dwapb_gpio *gpio) +{ +	unsigned int m; + +	for (m = 0; m < gpio->nr_ports; ++m) +		if (gpio->ports[m].is_registered) +			WARN_ON(gpiochip_remove(&gpio->ports[m].bgc.gc)); +} + +static int dwapb_gpio_probe(struct platform_device *pdev) +{ +	struct resource *res; +	struct dwapb_gpio *gpio; +	struct device_node *np; +	int err; +	unsigned int offs = 0; + +	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); +	if (!gpio) +		return -ENOMEM; +	gpio->dev = &pdev->dev; + +	gpio->nr_ports = of_get_child_count(pdev->dev.of_node); +	if (!gpio->nr_ports) { +		err = -EINVAL; +		goto out_err; +	} +	gpio->ports = devm_kzalloc(&pdev->dev, gpio->nr_ports * +				   sizeof(*gpio->ports), GFP_KERNEL); +	if (!gpio->ports) { +		err = -ENOMEM; +		goto out_err; +	} + +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	gpio->regs = devm_ioremap_resource(&pdev->dev, res); +	if (IS_ERR(gpio->regs)) { +		err = PTR_ERR(gpio->regs); +		goto out_err; +	} + +	for_each_child_of_node(pdev->dev.of_node, np) { +		err = dwapb_gpio_add_port(gpio, np, offs++); +		if (err) +			goto out_unregister; +	} +	platform_set_drvdata(pdev, gpio); + +	return 0; + +out_unregister: +	dwapb_gpio_unregister(gpio); +	dwapb_irq_teardown(gpio); + +out_err: +	return err; +} + +static int dwapb_gpio_remove(struct platform_device *pdev) +{ +	struct dwapb_gpio *gpio = platform_get_drvdata(pdev); + +	dwapb_gpio_unregister(gpio); +	dwapb_irq_teardown(gpio); + +	return 0; +} + +static const struct of_device_id dwapb_of_match[] = { +	{ .compatible = "snps,dw-apb-gpio" }, +	{ /* Sentinel */ } +}; +MODULE_DEVICE_TABLE(of, dwapb_of_match); + +static struct platform_driver dwapb_gpio_driver = { +	.driver		= { +		.name	= "gpio-dwapb", +		.owner	= THIS_MODULE, +		.of_match_table = of_match_ptr(dwapb_of_match), +	}, +	.probe		= dwapb_gpio_probe, +	.remove		= dwapb_gpio_remove, +}; + +module_platform_driver(dwapb_gpio_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jamie Iles"); +MODULE_DESCRIPTION("Synopsys DesignWare APB GPIO driver"); diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index c6e1f086efe..cde36054c38 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -99,6 +99,27 @@ static void em_gio_irq_enable(struct irq_data *d)  	em_gio_write(p, GIO_IEN, BIT(irqd_to_hwirq(d)));  } +static int em_gio_irq_reqres(struct irq_data *d) +{ +	struct em_gio_priv *p = irq_data_get_irq_chip_data(d); + +	if (gpio_lock_as_irq(&p->gpio_chip, irqd_to_hwirq(d))) { +		dev_err(p->gpio_chip.dev, +			"unable to lock HW IRQ %lu for IRQ\n", +			irqd_to_hwirq(d)); +		return -EINVAL; +	} +	return 0; +} + +static void em_gio_irq_relres(struct irq_data *d) +{ +	struct em_gio_priv *p = irq_data_get_irq_chip_data(d); + +	gpio_unlock_as_irq(&p->gpio_chip, irqd_to_hwirq(d)); +} + +  #define GIO_ASYNC(x) (x + 8)  static unsigned char em_gio_sense_table[IRQ_TYPE_SENSE_MASK + 1] = { @@ -191,7 +212,7 @@ static void __em_gio_set(struct gpio_chip *chip, unsigned int reg,  {  	/* upper 16 bits contains mask and lower 16 actual value */  	em_gio_write(gpio_to_priv(chip), reg, -		     (1 << (shift + 16)) | (value << shift)); +		     (BIT(shift + 16)) | (value << shift));  }  static void em_gio_set(struct gpio_chip *chip, unsigned offset, int value) @@ -232,16 +253,16 @@ static void em_gio_free(struct gpio_chip *chip, unsigned offset)  	em_gio_direction_input(chip, offset);  } -static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int virq, -				 irq_hw_number_t hw) +static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int irq, +				 irq_hw_number_t hwirq)  {  	struct em_gio_priv *p = h->host_data; -	pr_debug("gio: map hw irq = %d, virq = %d\n", (int)hw, virq); +	pr_debug("gio: map hw irq = %d, irq = %d\n", (int)hwirq, irq); -	irq_set_chip_data(virq, h->host_data); -	irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq); -	set_irq_flags(virq, IRQF_VALID); /* kill me now */ +	irq_set_chip_data(irq, h->host_data); +	irq_set_chip_and_handler(irq, &p->irq_chip, handle_level_irq); +	set_irq_flags(irq, IRQF_VALID); /* kill me now */  	return 0;  } @@ -263,7 +284,6 @@ static int em_gio_probe(struct platform_device *pdev)  	p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);  	if (!p) { -		dev_err(&pdev->dev, "failed to allocate driver data\n");  		ret = -ENOMEM;  		goto err0;  	} @@ -319,6 +339,7 @@ static int em_gio_probe(struct platform_device *pdev)  	}  	gpio_chip = &p->gpio_chip; +	gpio_chip->of_node = pdev->dev.of_node;  	gpio_chip->direction_input = em_gio_direction_input;  	gpio_chip->get = em_gio_get;  	gpio_chip->direction_output = em_gio_direction_output; @@ -327,6 +348,7 @@ static int em_gio_probe(struct platform_device *pdev)  	gpio_chip->request = em_gio_request;  	gpio_chip->free = em_gio_free;  	gpio_chip->label = name; +	gpio_chip->dev = &pdev->dev;  	gpio_chip->owner = THIS_MODULE;  	gpio_chip->base = pdata->gpio_base;  	gpio_chip->ngpio = pdata->number_of_pins; @@ -335,10 +357,10 @@ static int em_gio_probe(struct platform_device *pdev)  	irq_chip->name = name;  	irq_chip->irq_mask = em_gio_irq_disable;  	irq_chip->irq_unmask = em_gio_irq_enable; -	irq_chip->irq_enable = em_gio_irq_enable; -	irq_chip->irq_disable = em_gio_irq_disable;  	irq_chip->irq_set_type = em_gio_irq_set_type; -	irq_chip->flags	= IRQCHIP_SKIP_SET_WAKE; +	irq_chip->irq_request_resources = em_gio_irq_reqres; +	irq_chip->irq_release_resources = em_gio_irq_relres; +	irq_chip->flags	= IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;  	p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,  					      pdata->number_of_pins, diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c index 56b98eebe1f..dcc2bb4074e 100644 --- a/drivers/gpio/gpio-ep93xx.c +++ b/drivers/gpio/gpio-ep93xx.c @@ -51,15 +51,15 @@ static void ep93xx_gpio_update_int_params(unsigned port)  {  	BUG_ON(port > 2); -	__raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port])); +	writeb_relaxed(0, EP93XX_GPIO_REG(int_en_register_offset[port])); -	__raw_writeb(gpio_int_type2[port], +	writeb_relaxed(gpio_int_type2[port],  		EP93XX_GPIO_REG(int_type2_register_offset[port])); -	__raw_writeb(gpio_int_type1[port], +	writeb_relaxed(gpio_int_type1[port],  		EP93XX_GPIO_REG(int_type1_register_offset[port])); -	__raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port], +	writeb(gpio_int_unmasked[port] & gpio_int_enabled[port],  		EP93XX_GPIO_REG(int_en_register_offset[port]));  } @@ -74,7 +74,7 @@ static void ep93xx_gpio_int_debounce(unsigned int irq, bool enable)  	else  		gpio_int_debounce[port] &= ~port_mask; -	__raw_writeb(gpio_int_debounce[port], +	writeb(gpio_int_debounce[port],  		EP93XX_GPIO_REG(int_debounce_register_offset[port]));  } @@ -83,7 +83,7 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)  	unsigned char status;  	int i; -	status = __raw_readb(EP93XX_GPIO_A_INT_STATUS); +	status = readb(EP93XX_GPIO_A_INT_STATUS);  	for (i = 0; i < 8; i++) {  		if (status & (1 << i)) {  			int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i; @@ -91,7 +91,7 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)  		}  	} -	status = __raw_readb(EP93XX_GPIO_B_INT_STATUS); +	status = readb(EP93XX_GPIO_B_INT_STATUS);  	for (i = 0; i < 8; i++) {  		if (status & (1 << i)) {  			int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i; @@ -124,7 +124,7 @@ static void ep93xx_gpio_irq_ack(struct irq_data *d)  		ep93xx_gpio_update_int_params(port);  	} -	__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port])); +	writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));  }  static void ep93xx_gpio_irq_mask_ack(struct irq_data *d) @@ -139,7 +139,7 @@ static void ep93xx_gpio_irq_mask_ack(struct irq_data *d)  	gpio_int_unmasked[port] &= ~port_mask;  	ep93xx_gpio_update_int_params(port); -	__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port])); +	writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));  }  static void ep93xx_gpio_irq_mask(struct irq_data *d) @@ -344,37 +344,24 @@ static int ep93xx_gpio_probe(struct platform_device *pdev)  {  	struct ep93xx_gpio *ep93xx_gpio;  	struct resource *res; -	void __iomem *mmio;  	int i; -	int ret; +	struct device *dev = &pdev->dev; -	ep93xx_gpio = kzalloc(sizeof(*ep93xx_gpio), GFP_KERNEL); +	ep93xx_gpio = devm_kzalloc(dev, sizeof(struct ep93xx_gpio), GFP_KERNEL);  	if (!ep93xx_gpio)  		return -ENOMEM;  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		ret = -ENXIO; -		goto exit_free; -	} - -	if (!request_mem_region(res->start, resource_size(res), pdev->name)) { -		ret = -EBUSY; -		goto exit_free; -	} - -	mmio = ioremap(res->start, resource_size(res)); -	if (!mmio) { -		ret = -ENXIO; -		goto exit_release; -	} -	ep93xx_gpio->mmio_base = mmio; +	ep93xx_gpio->mmio_base = devm_ioremap_resource(dev, res); +	if (IS_ERR(ep93xx_gpio->mmio_base)) +		return PTR_ERR(ep93xx_gpio->mmio_base);  	for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) {  		struct bgpio_chip *bgc = &ep93xx_gpio->bgc[i];  		struct ep93xx_gpio_bank *bank = &ep93xx_gpio_banks[i]; -		if (ep93xx_gpio_add_bank(bgc, &pdev->dev, mmio, bank)) +		if (ep93xx_gpio_add_bank(bgc, &pdev->dev, +					 ep93xx_gpio->mmio_base, bank))  			dev_warn(&pdev->dev, "Unable to add gpio bank %s\n",  				bank->label);  	} @@ -382,13 +369,6 @@ static int ep93xx_gpio_probe(struct platform_device *pdev)  	ep93xx_gpio_init_irq();  	return 0; - -exit_release: -	release_mem_region(res->start, resource_size(res)); -exit_free: -	kfree(ep93xx_gpio); -	dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, ret); -	return ret;  }  static struct platform_driver ep93xx_gpio_driver = { diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c index 9cb8320e118..8f73ee09373 100644 --- a/drivers/gpio/gpio-f7188x.c +++ b/drivers/gpio/gpio-f7188x.c @@ -135,6 +135,7 @@ static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value);  			.set              = f7188x_gpio_set,		\  			.base             = _base,			\  			.ngpio            = _ngpio,			\ +			.can_sleep        = true,			\  		},							\  		.regbase = _regbase,					\  	} diff --git a/drivers/gpio/gpio-ge.c b/drivers/gpio/gpio-ge.c index 7b95a4a8318..1237a73c3c9 100644 --- a/drivers/gpio/gpio-ge.c +++ b/drivers/gpio/gpio-ge.c @@ -18,15 +18,9 @@   */  #include <linux/kernel.h> -#include <linux/compiler.h> -#include <linux/init.h>  #include <linux/io.h> -#include <linux/of.h>  #include <linux/of_device.h> -#include <linux/of_platform.h>  #include <linux/of_gpio.h> -#include <linux/gpio.h> -#include <linux/slab.h>  #include <linux/module.h>  #define GEF_GPIO_DIRECT		0x00 @@ -39,28 +33,26 @@  #define GEF_GPIO_OVERRUN	0x1C  #define GEF_GPIO_MODE		0x20 -static void _gef_gpio_set(void __iomem *reg, unsigned int offset, int value) +static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)  { +	struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);  	unsigned int data; -	data = ioread32be(reg); -	/* value: 0=low; 1=high */ -	if (value & 0x1) -		data = data | (0x1 << offset); +	data = ioread32be(mmchip->regs + GEF_GPIO_OUT); +	if (value) +		data = data | BIT(offset);  	else -		data = data & ~(0x1 << offset); - -	iowrite32be(data, reg); +		data = data & ~BIT(offset); +	iowrite32be(data, mmchip->regs + GEF_GPIO_OUT);  } -  static int gef_gpio_dir_in(struct gpio_chip *chip, unsigned offset)  {  	unsigned int data;  	struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);  	data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT); -	data = data | (0x1 << offset); +	data = data | BIT(offset);  	iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);  	return 0; @@ -71,11 +63,11 @@ static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)  	unsigned int data;  	struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); -	/* Set direction before switching to input */ -	_gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value); +	/* Set value before switching to output */ +	gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);  	data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT); -	data = data & ~(0x1 << offset); +	data = data & ~BIT(offset);  	iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);  	return 0; @@ -83,116 +75,56 @@ static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)  static int gef_gpio_get(struct gpio_chip *chip, unsigned offset)  { -	unsigned int data; -	int state = 0;  	struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); -	data = ioread32be(mmchip->regs + GEF_GPIO_IN); -	state = (int)((data >> offset) & 0x1); - -	return state; +	return !!(ioread32be(mmchip->regs + GEF_GPIO_IN) & BIT(offset));  } -static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ -	struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); - -	_gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value); -} +static const struct of_device_id gef_gpio_ids[] = { +	{ +		.compatible	= "gef,sbc610-gpio", +		.data		= (void *)19, +	}, { +		.compatible	= "gef,sbc310-gpio", +		.data		= (void *)6, +	}, { +		.compatible	= "ge,imp3a-gpio", +		.data		= (void *)16, +	}, +	{ } +}; +MODULE_DEVICE_TABLE(of, gef_gpio_ids); -static int __init gef_gpio_init(void) +static int __init gef_gpio_probe(struct platform_device *pdev)  { -	struct device_node *np; -	int retval; -	struct of_mm_gpio_chip *gef_gpio_chip; - -	for_each_compatible_node(np, NULL, "gef,sbc610-gpio") { - -		pr_debug("%s: Initialising GEF GPIO\n", np->full_name); - -		/* Allocate chip structure */ -		gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL); -		if (!gef_gpio_chip) { -			pr_err("%s: Unable to allocate structure\n", -				np->full_name); -			continue; -		} - -		/* Setup pointers to chip functions */ -		gef_gpio_chip->gc.of_gpio_n_cells = 2; -		gef_gpio_chip->gc.ngpio = 19; -		gef_gpio_chip->gc.direction_input = gef_gpio_dir_in; -		gef_gpio_chip->gc.direction_output = gef_gpio_dir_out; -		gef_gpio_chip->gc.get = gef_gpio_get; -		gef_gpio_chip->gc.set = gef_gpio_set; - -		/* This function adds a memory mapped GPIO chip */ -		retval = of_mm_gpiochip_add(np, gef_gpio_chip); -		if (retval) { -			kfree(gef_gpio_chip); -			pr_err("%s: Unable to add GPIO\n", np->full_name); -		} -	} - -	for_each_compatible_node(np, NULL, "gef,sbc310-gpio") { - -		pr_debug("%s: Initialising GEF GPIO\n", np->full_name); - -		/* Allocate chip structure */ -		gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL); -		if (!gef_gpio_chip) { -			pr_err("%s: Unable to allocate structure\n", -				np->full_name); -			continue; -		} - -		/* Setup pointers to chip functions */ -		gef_gpio_chip->gc.of_gpio_n_cells = 2; -		gef_gpio_chip->gc.ngpio = 6; -		gef_gpio_chip->gc.direction_input = gef_gpio_dir_in; -		gef_gpio_chip->gc.direction_output = gef_gpio_dir_out; -		gef_gpio_chip->gc.get = gef_gpio_get; -		gef_gpio_chip->gc.set = gef_gpio_set; - -		/* This function adds a memory mapped GPIO chip */ -		retval = of_mm_gpiochip_add(np, gef_gpio_chip); -		if (retval) { -			kfree(gef_gpio_chip); -			pr_err("%s: Unable to add GPIO\n", np->full_name); -		} -	} - -	for_each_compatible_node(np, NULL, "ge,imp3a-gpio") { - -		pr_debug("%s: Initialising GE GPIO\n", np->full_name); - -		/* Allocate chip structure */ -		gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL); -		if (!gef_gpio_chip) { -			pr_err("%s: Unable to allocate structure\n", -				np->full_name); -			continue; -		} - -		/* Setup pointers to chip functions */ -		gef_gpio_chip->gc.of_gpio_n_cells = 2; -		gef_gpio_chip->gc.ngpio = 16; -		gef_gpio_chip->gc.direction_input = gef_gpio_dir_in; -		gef_gpio_chip->gc.direction_output = gef_gpio_dir_out; -		gef_gpio_chip->gc.get = gef_gpio_get; -		gef_gpio_chip->gc.set = gef_gpio_set; - -		/* This function adds a memory mapped GPIO chip */ -		retval = of_mm_gpiochip_add(np, gef_gpio_chip); -		if (retval) { -			kfree(gef_gpio_chip); -			pr_err("%s: Unable to add GPIO\n", np->full_name); -		} -	} +	const struct of_device_id *of_id = +		of_match_device(gef_gpio_ids, &pdev->dev); +	struct of_mm_gpio_chip *mmchip; + +	mmchip = devm_kzalloc(&pdev->dev, sizeof(*mmchip), GFP_KERNEL); +	if (!mmchip) +		return -ENOMEM; + +	/* Setup pointers to chip functions */ +	mmchip->gc.ngpio = (u16)(uintptr_t)of_id->data; +	mmchip->gc.of_gpio_n_cells = 2; +	mmchip->gc.direction_input = gef_gpio_dir_in; +	mmchip->gc.direction_output = gef_gpio_dir_out; +	mmchip->gc.get = gef_gpio_get; +	mmchip->gc.set = gef_gpio_set; + +	/* This function adds a memory mapped GPIO chip */ +	return of_mm_gpiochip_add(pdev->dev.of_node, mmchip); +}; -	return 0; +static struct platform_driver gef_gpio_driver = { +	.driver = { +		.name		= "gef-gpio", +		.owner		= THIS_MODULE, +		.of_match_table	= gef_gpio_ids, +	},  }; -arch_initcall(gef_gpio_init); +module_platform_driver_probe(gef_gpio_driver, gef_gpio_probe);  MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");  MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com"); diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c index d2196bf7384..fea8c82bb8f 100644 --- a/drivers/gpio/gpio-generic.c +++ b/drivers/gpio/gpio-generic.c @@ -139,7 +139,7 @@ static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)  {  	struct bgpio_chip *bgc = to_bgpio_chip(gc); -	return bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio); +	return !!(bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio));  }  static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) @@ -388,6 +388,14 @@ static int bgpio_setup_direction(struct bgpio_chip *bgc,  	return 0;  } +static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin) +{ +	if (gpio_pin < chip->ngpio) +		return 0; + +	return -EINVAL; +} +  int bgpio_remove(struct bgpio_chip *bgc)  {  	return gpiochip_remove(&bgc->gc); @@ -413,6 +421,7 @@ int bgpio_init(struct bgpio_chip *bgc, struct device *dev,  	bgc->gc.label = dev_name(dev);  	bgc->gc.base = -1;  	bgc->gc.ngpio = bgc->bits; +	bgc->gc.request = bgpio_request;  	ret = bgpio_setup_io(bgc, dat, set, clr);  	if (ret) @@ -488,7 +497,7 @@ static int bgpio_pdev_probe(struct platform_device *pdev)  	void __iomem *dirout;  	void __iomem *dirin;  	unsigned long sz; -	unsigned long flags = 0; +	unsigned long flags = pdev->id_entry->driver_data;  	int err;  	struct bgpio_chip *bgc;  	struct bgpio_pdata *pdata = dev_get_platdata(dev); @@ -519,9 +528,6 @@ static int bgpio_pdev_probe(struct platform_device *pdev)  	if (err)  		return err; -	if (!strcmp(platform_get_device_id(pdev)->name, "basic-mmio-gpio-be")) -		flags |= BGPIOF_BIG_ENDIAN; -  	bgc = devm_kzalloc(&pdev->dev, sizeof(*bgc), GFP_KERNEL);  	if (!bgc)  		return -ENOMEM; @@ -531,6 +537,8 @@ static int bgpio_pdev_probe(struct platform_device *pdev)  		return err;  	if (pdata) { +		if (pdata->label) +			bgc->gc.label = pdata->label;  		bgc->gc.base = pdata->base;  		if (pdata->ngpio > 0)  			bgc->gc.ngpio = pdata->ngpio; @@ -549,9 +557,14 @@ static int bgpio_pdev_remove(struct platform_device *pdev)  }  static const struct platform_device_id bgpio_id_table[] = { -	{ "basic-mmio-gpio", }, -	{ "basic-mmio-gpio-be", }, -	{}, +	{ +		.name		= "basic-mmio-gpio", +		.driver_data	= 0, +	}, { +		.name		= "basic-mmio-gpio-be", +		.driver_data	= BGPIOF_BIG_ENDIAN, +	}, +	{ }  };  MODULE_DEVICE_TABLE(platform, bgpio_id_table); diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c index 84d2478ec29..3c3f515b791 100644 --- a/drivers/gpio/gpio-grgpio.c +++ b/drivers/gpio/gpio-grgpio.c @@ -481,7 +481,7 @@ out:  	return ret;  } -static struct of_device_id grgpio_match[] = { +static const struct of_device_id grgpio_match[] = {  	{.name = "GAISLER_GPIO"},  	{.name = "01_01a"},  	{}, diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c index 814addb62d2..70304220a47 100644 --- a/drivers/gpio/gpio-ich.c +++ b/drivers/gpio/gpio-ich.c @@ -1,5 +1,5 @@  /* - * Intel ICH6-10, Series 5 and 6 GPIO driver + * Intel ICH6-10, Series 5 and 6, Atom C2000 (Avoton/Rangeley) GPIO driver   *   * Copyright (C) 2010 Extreme Engineering Solutions.   * @@ -55,6 +55,16 @@ static const u8 ichx_reglen[3] = {  	0x30, 0x10, 0x10,  }; +static const u8 avoton_regs[4][3] = { +	{0x00, 0x80, 0x00}, +	{0x04, 0x84, 0x00}, +	{0x08, 0x88, 0x00}, +}; + +static const u8 avoton_reglen[3] = { +	0x10, 0x10, 0x00, +}; +  #define ICHX_WRITE(val, reg, base_res)	outl(val, (reg) + (base_res)->start)  #define ICHX_READ(reg, base_res)	inl((reg) + (base_res)->start) @@ -62,6 +72,13 @@ struct ichx_desc {  	/* Max GPIO pins the chipset can have */  	uint ngpio; +	/* chipset registers */ +	const u8 (*regs)[3]; +	const u8 *reglen; + +	/* GPO_BLINK is available on this chipset */ +	bool have_blink; +  	/* Whether the chipset has GPIO in GPE0_STS in the PM IO region */  	bool uses_gpe0; @@ -71,6 +88,12 @@ struct ichx_desc {  	/* Some chipsets have quirks, let these use their own request/get */  	int (*request)(struct gpio_chip *chip, unsigned offset);  	int (*get)(struct gpio_chip *chip, unsigned offset); + +	/* +	 * Some chipsets don't let reading output values on GPIO_LVL register +	 * this option allows driver caching written output values +	 */ +	bool use_outlvl_cache;  };  static struct { @@ -82,6 +105,7 @@ static struct {  	struct ichx_desc *desc;	/* Pointer to chipset-specific description */  	u32 orig_gpio_ctrl;	/* Orig CTRL value, used to restore on exit */  	u8 use_gpio;		/* Which GPIO groups are usable */ +	int outlvl_cache[3];	/* cached output values */  } ichx_priv;  static int modparam_gpiobase = -1;	/* dynamic */ @@ -99,13 +123,23 @@ static int ichx_write_bit(int reg, unsigned nr, int val, int verify)  	spin_lock_irqsave(&ichx_priv.lock, flags); -	data = ICHX_READ(ichx_regs[reg][reg_nr], ichx_priv.gpio_base); +	if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) +		data = ichx_priv.outlvl_cache[reg_nr]; +	else +		data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], +				 ichx_priv.gpio_base); +  	if (val)  		data |= 1 << bit;  	else  		data &= ~(1 << bit); -	ICHX_WRITE(data, ichx_regs[reg][reg_nr], ichx_priv.gpio_base); -	tmp = ICHX_READ(ichx_regs[reg][reg_nr], ichx_priv.gpio_base); +	ICHX_WRITE(data, ichx_priv.desc->regs[reg][reg_nr], +			 ichx_priv.gpio_base); +	if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) +		ichx_priv.outlvl_cache[reg_nr] = data; + +	tmp = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], +			ichx_priv.gpio_base);  	if (verify && data != tmp)  		ret = -EPERM; @@ -123,7 +157,11 @@ static int ichx_read_bit(int reg, unsigned nr)  	spin_lock_irqsave(&ichx_priv.lock, flags); -	data = ICHX_READ(ichx_regs[reg][reg_nr], ichx_priv.gpio_base); +	data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], +			 ichx_priv.gpio_base); + +	if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) +		data = ichx_priv.outlvl_cache[reg_nr] | data;  	spin_unlock_irqrestore(&ichx_priv.lock, flags); @@ -151,7 +189,7 @@ static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,  					int val)  {  	/* Disable blink hardware which is available for GPIOs from 0 to 31. */ -	if (nr < 32) +	if (nr < 32 && ichx_priv.desc->have_blink)  		ichx_write_bit(GPO_BLINK, nr, 0, 0);  	/* Set GPIO output value. */ @@ -252,7 +290,7 @@ static void ichx_gpiolib_setup(struct gpio_chip *chip)  	chip->direction_output = ichx_gpio_direction_output;  	chip->base = modparam_gpiobase;  	chip->ngpio = ichx_priv.desc->ngpio; -	chip->can_sleep = 0; +	chip->can_sleep = false;  	chip->dbg_show = NULL;  } @@ -266,6 +304,9 @@ static struct ichx_desc ich6_desc = {  	.uses_gpe0 = true,  	.ngpio = 50, +	.have_blink = true, +	.regs = ichx_regs, +	.reglen = ichx_reglen,  };  /* Intel 3100 */ @@ -285,29 +326,56 @@ static struct ichx_desc i3100_desc = {  	.uses_gpe0 = true,  	.ngpio = 50, +	.regs = ichx_regs, +	.reglen = ichx_reglen,  };  /* ICH7 and ICH8-based */  static struct ichx_desc ich7_desc = {  	.ngpio = 50, +	.have_blink = true, +	.regs = ichx_regs, +	.reglen = ichx_reglen,  };  /* ICH9-based */  static struct ichx_desc ich9_desc = {  	.ngpio = 61, +	.have_blink = true, +	.regs = ichx_regs, +	.reglen = ichx_reglen,  };  /* ICH10-based - Consumer/corporate versions have different amount of GPIO */  static struct ichx_desc ich10_cons_desc = {  	.ngpio = 61, +	.have_blink = true, +	.regs = ichx_regs, +	.reglen = ichx_reglen,  };  static struct ichx_desc ich10_corp_desc = {  	.ngpio = 72, +	.have_blink = true, +	.regs = ichx_regs, +	.reglen = ichx_reglen,  };  /* Intel 5 series, 6 series, 3400 series, and C200 series */  static struct ichx_desc intel5_desc = {  	.ngpio = 76, +	.regs = ichx_regs, +	.reglen = ichx_reglen, +}; + +/* Avoton */ +static struct ichx_desc avoton_desc = { +	/* Avoton has only 59 GPIOs, but we assume the first set of register +	 * (Core) has 32 instead of 31 to keep gpio-ich compliance +	 */ +	.ngpio = 60, +	.regs = avoton_regs, +	.reglen = avoton_reglen, +	.use_outlvl_cache = true,  };  static int ichx_gpio_request_regions(struct resource *res_base, @@ -318,11 +386,12 @@ static int ichx_gpio_request_regions(struct resource *res_base,  	if (!res_base || !res_base->start || !res_base->end)  		return -ENODEV; -	for (i = 0; i < ARRAY_SIZE(ichx_regs[0]); i++) { +	for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) {  		if (!(use_gpio & (1 << i)))  			continue; -		if (!request_region(res_base->start + ichx_regs[0][i], -				    ichx_reglen[i], name)) +		if (!request_region( +				res_base->start + ichx_priv.desc->regs[0][i], +				ichx_priv.desc->reglen[i], name))  			goto request_err;  	}  	return 0; @@ -332,8 +401,8 @@ request_err:  	for (i--; i >= 0; i--) {  		if (!(use_gpio & (1 << i)))  			continue; -		release_region(res_base->start + ichx_regs[0][i], -			       ichx_reglen[i]); +		release_region(res_base->start + ichx_priv.desc->regs[0][i], +			       ichx_priv.desc->reglen[i]);  	}  	return -EBUSY;  } @@ -342,11 +411,11 @@ static void ichx_gpio_release_regions(struct resource *res_base, u8 use_gpio)  {  	int i; -	for (i = 0; i < ARRAY_SIZE(ichx_regs[0]); i++) { +	for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) {  		if (!(use_gpio & (1 << i)))  			continue; -		release_region(res_base->start + ichx_regs[0][i], -			       ichx_reglen[i]); +		release_region(res_base->start + ichx_priv.desc->regs[0][i], +			       ichx_priv.desc->reglen[i]);  	}  } @@ -383,6 +452,9 @@ static int ichx_gpio_probe(struct platform_device *pdev)  	case ICH_V10CONS_GPIO:  		ichx_priv.desc = &ich10_cons_desc;  		break; +	case AVOTON_GPIO: +		ichx_priv.desc = &avoton_desc; +		break;  	default:  		return -ENODEV;  	} diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c new file mode 100644 index 00000000000..118a6bf455d --- /dev/null +++ b/drivers/gpio/gpio-intel-mid.c @@ -0,0 +1,489 @@ +/* + * Intel MID GPIO driver + * + * Copyright (c) 2008-2014 Intel Corporation. + * + * 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. + */ + +/* Supports: + * Moorestown platform Langwell chip. + * Medfield platform Penwell chip. + * Clovertrail platform Cloverview chip. + * Merrifield platform Tangier chip. + */ + +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/platform_device.h> +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/stddef.h> +#include <linux/interrupt.h> +#include <linux/init.h> +#include <linux/irq.h> +#include <linux/io.h> +#include <linux/gpio.h> +#include <linux/slab.h> +#include <linux/pm_runtime.h> +#include <linux/irqdomain.h> + +#define INTEL_MID_IRQ_TYPE_EDGE		(1 << 0) +#define INTEL_MID_IRQ_TYPE_LEVEL	(1 << 1) + +/* + * Langwell chip has 64 pins and thus there are 2 32bit registers to control + * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit + * registers to control them, so we only define the order here instead of a + * structure, to get a bit offset for a pin (use GPDR as an example): + * + * nreg = ngpio / 32; + * reg = offset / 32; + * bit = offset % 32; + * reg_addr = reg_base + GPDR * nreg * 4 + reg * 4; + * + * so the bit of reg_addr is to control pin offset's GPDR feature +*/ + +enum GPIO_REG { +	GPLR = 0,	/* pin level read-only */ +	GPDR,		/* pin direction */ +	GPSR,		/* pin set */ +	GPCR,		/* pin clear */ +	GRER,		/* rising edge detect */ +	GFER,		/* falling edge detect */ +	GEDR,		/* edge detect result */ +	GAFR,		/* alt function */ +}; + +/* intel_mid gpio driver data */ +struct intel_mid_gpio_ddata { +	u16 ngpio;		/* number of gpio pins */ +	u32 gplr_offset;	/* offset of first GPLR register from base */ +	u32 flis_base;		/* base address of FLIS registers */ +	u32 flis_len;		/* length of FLIS registers */ +	u32 (*get_flis_offset)(int gpio); +	u32 chip_irq_type;	/* chip interrupt type */ +}; + +struct intel_mid_gpio { +	struct gpio_chip		chip; +	void __iomem			*reg_base; +	spinlock_t			lock; +	struct pci_dev			*pdev; +	struct irq_domain		*domain; +}; + +#define to_intel_gpio_priv(chip) container_of(chip, struct intel_mid_gpio, chip) + +static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset, +			      enum GPIO_REG reg_type) +{ +	struct intel_mid_gpio *priv = to_intel_gpio_priv(chip); +	unsigned nreg = chip->ngpio / 32; +	u8 reg = offset / 32; + +	return priv->reg_base + reg_type * nreg * 4 + reg * 4; +} + +static void __iomem *gpio_reg_2bit(struct gpio_chip *chip, unsigned offset, +				   enum GPIO_REG reg_type) +{ +	struct intel_mid_gpio *priv = to_intel_gpio_priv(chip); +	unsigned nreg = chip->ngpio / 32; +	u8 reg = offset / 16; + +	return priv->reg_base + reg_type * nreg * 4 + reg * 4; +} + +static int intel_gpio_request(struct gpio_chip *chip, unsigned offset) +{ +	void __iomem *gafr = gpio_reg_2bit(chip, offset, GAFR); +	u32 value = readl(gafr); +	int shift = (offset % 16) << 1, af = (value >> shift) & 3; + +	if (af) { +		value &= ~(3 << shift); +		writel(value, gafr); +	} +	return 0; +} + +static int intel_gpio_get(struct gpio_chip *chip, unsigned offset) +{ +	void __iomem *gplr = gpio_reg(chip, offset, GPLR); + +	return readl(gplr) & BIT(offset % 32); +} + +static void intel_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ +	void __iomem *gpsr, *gpcr; + +	if (value) { +		gpsr = gpio_reg(chip, offset, GPSR); +		writel(BIT(offset % 32), gpsr); +	} else { +		gpcr = gpio_reg(chip, offset, GPCR); +		writel(BIT(offset % 32), gpcr); +	} +} + +static int intel_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ +	struct intel_mid_gpio *priv = to_intel_gpio_priv(chip); +	void __iomem *gpdr = gpio_reg(chip, offset, GPDR); +	u32 value; +	unsigned long flags; + +	if (priv->pdev) +		pm_runtime_get(&priv->pdev->dev); + +	spin_lock_irqsave(&priv->lock, flags); +	value = readl(gpdr); +	value &= ~BIT(offset % 32); +	writel(value, gpdr); +	spin_unlock_irqrestore(&priv->lock, flags); + +	if (priv->pdev) +		pm_runtime_put(&priv->pdev->dev); + +	return 0; +} + +static int intel_gpio_direction_output(struct gpio_chip *chip, +			unsigned offset, int value) +{ +	struct intel_mid_gpio *priv = to_intel_gpio_priv(chip); +	void __iomem *gpdr = gpio_reg(chip, offset, GPDR); +	unsigned long flags; + +	intel_gpio_set(chip, offset, value); + +	if (priv->pdev) +		pm_runtime_get(&priv->pdev->dev); + +	spin_lock_irqsave(&priv->lock, flags); +	value = readl(gpdr); +	value |= BIT(offset % 32); +	writel(value, gpdr); +	spin_unlock_irqrestore(&priv->lock, flags); + +	if (priv->pdev) +		pm_runtime_put(&priv->pdev->dev); + +	return 0; +} + +static int intel_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ +	struct intel_mid_gpio *priv = to_intel_gpio_priv(chip); +	return irq_create_mapping(priv->domain, offset); +} + +static int intel_mid_irq_type(struct irq_data *d, unsigned type) +{ +	struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d); +	u32 gpio = irqd_to_hwirq(d); +	unsigned long flags; +	u32 value; +	void __iomem *grer = gpio_reg(&priv->chip, gpio, GRER); +	void __iomem *gfer = gpio_reg(&priv->chip, gpio, GFER); + +	if (gpio >= priv->chip.ngpio) +		return -EINVAL; + +	if (priv->pdev) +		pm_runtime_get(&priv->pdev->dev); + +	spin_lock_irqsave(&priv->lock, flags); +	if (type & IRQ_TYPE_EDGE_RISING) +		value = readl(grer) | BIT(gpio % 32); +	else +		value = readl(grer) & (~BIT(gpio % 32)); +	writel(value, grer); + +	if (type & IRQ_TYPE_EDGE_FALLING) +		value = readl(gfer) | BIT(gpio % 32); +	else +		value = readl(gfer) & (~BIT(gpio % 32)); +	writel(value, gfer); +	spin_unlock_irqrestore(&priv->lock, flags); + +	if (priv->pdev) +		pm_runtime_put(&priv->pdev->dev); + +	return 0; +} + +static void intel_mid_irq_unmask(struct irq_data *d) +{ +} + +static void intel_mid_irq_mask(struct irq_data *d) +{ +} + +static int intel_mid_irq_reqres(struct irq_data *d) +{ +	struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d); + +	if (gpio_lock_as_irq(&priv->chip, irqd_to_hwirq(d))) { +		dev_err(priv->chip.dev, +			"unable to lock HW IRQ %lu for IRQ\n", +			irqd_to_hwirq(d)); +		return -EINVAL; +	} +	return 0; +} + +static void intel_mid_irq_relres(struct irq_data *d) +{ +	struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d); + +	gpio_unlock_as_irq(&priv->chip, irqd_to_hwirq(d)); +} + +static struct irq_chip intel_mid_irqchip = { +	.name		= "INTEL_MID-GPIO", +	.irq_mask	= intel_mid_irq_mask, +	.irq_unmask	= intel_mid_irq_unmask, +	.irq_set_type	= intel_mid_irq_type, +	.irq_request_resources = intel_mid_irq_reqres, +	.irq_release_resources = intel_mid_irq_relres, +}; + +static const struct intel_mid_gpio_ddata gpio_lincroft = { +	.ngpio = 64, +}; + +static const struct intel_mid_gpio_ddata gpio_penwell_aon = { +	.ngpio = 96, +	.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE, +}; + +static const struct intel_mid_gpio_ddata gpio_penwell_core = { +	.ngpio = 96, +	.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE, +}; + +static const struct intel_mid_gpio_ddata gpio_cloverview_aon = { +	.ngpio = 96, +	.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE | INTEL_MID_IRQ_TYPE_LEVEL, +}; + +static const struct intel_mid_gpio_ddata gpio_cloverview_core = { +	.ngpio = 96, +	.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE, +}; + +static const struct intel_mid_gpio_ddata gpio_tangier = { +	.ngpio = 192, +	.gplr_offset = 4, +	.flis_base = 0xff0c0000, +	.flis_len = 0x8000, +	.get_flis_offset = NULL, +	.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE, +}; + +static const struct pci_device_id intel_gpio_ids[] = { +	{ +		/* Lincroft */ +		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), +		.driver_data = (kernel_ulong_t)&gpio_lincroft, +	}, +	{ +		/* Penwell AON */ +		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f), +		.driver_data = (kernel_ulong_t)&gpio_penwell_aon, +	}, +	{ +		/* Penwell Core */ +		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a), +		.driver_data = (kernel_ulong_t)&gpio_penwell_core, +	}, +	{ +		/* Cloverview Aon */ +		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08eb), +		.driver_data = (kernel_ulong_t)&gpio_cloverview_aon, +	}, +	{ +		/* Cloverview Core */ +		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08f7), +		.driver_data = (kernel_ulong_t)&gpio_cloverview_core, +	}, +	{ +		/* Tangier */ +		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1199), +		.driver_data = (kernel_ulong_t)&gpio_tangier, +	}, +	{ 0 } +}; +MODULE_DEVICE_TABLE(pci, intel_gpio_ids); + +static void intel_mid_irq_handler(unsigned irq, struct irq_desc *desc) +{ +	struct irq_data *data = irq_desc_get_irq_data(desc); +	struct intel_mid_gpio *priv = irq_data_get_irq_handler_data(data); +	struct irq_chip *chip = irq_data_get_irq_chip(data); +	u32 base, gpio, mask; +	unsigned long pending; +	void __iomem *gedr; + +	/* check GPIO controller to check which pin triggered the interrupt */ +	for (base = 0; base < priv->chip.ngpio; base += 32) { +		gedr = gpio_reg(&priv->chip, base, GEDR); +		while ((pending = readl(gedr))) { +			gpio = __ffs(pending); +			mask = BIT(gpio); +			/* Clear before handling so we can't lose an edge */ +			writel(mask, gedr); +			generic_handle_irq(irq_find_mapping(priv->domain, +							    base + gpio)); +		} +	} + +	chip->irq_eoi(data); +} + +static void intel_mid_irq_init_hw(struct intel_mid_gpio *priv) +{ +	void __iomem *reg; +	unsigned base; + +	for (base = 0; base < priv->chip.ngpio; base += 32) { +		/* Clear the rising-edge detect register */ +		reg = gpio_reg(&priv->chip, base, GRER); +		writel(0, reg); +		/* Clear the falling-edge detect register */ +		reg = gpio_reg(&priv->chip, base, GFER); +		writel(0, reg); +		/* Clear the edge detect status register */ +		reg = gpio_reg(&priv->chip, base, GEDR); +		writel(~0, reg); +	} +} + +static int intel_gpio_irq_map(struct irq_domain *d, unsigned int irq, +			    irq_hw_number_t hwirq) +{ +	struct intel_mid_gpio *priv = d->host_data; + +	irq_set_chip_and_handler(irq, &intel_mid_irqchip, handle_simple_irq); +	irq_set_chip_data(irq, priv); +	irq_set_irq_type(irq, IRQ_TYPE_NONE); + +	return 0; +} + +static const struct irq_domain_ops intel_gpio_irq_ops = { +	.map = intel_gpio_irq_map, +	.xlate = irq_domain_xlate_twocell, +}; + +static int intel_gpio_runtime_idle(struct device *dev) +{ +	int err = pm_schedule_suspend(dev, 500); +	return err ?: -EBUSY; +} + +static const struct dev_pm_ops intel_gpio_pm_ops = { +	SET_RUNTIME_PM_OPS(NULL, NULL, intel_gpio_runtime_idle) +}; + +static int intel_gpio_probe(struct pci_dev *pdev, +			  const struct pci_device_id *id) +{ +	void __iomem *base; +	struct intel_mid_gpio *priv; +	u32 gpio_base; +	u32 irq_base; +	int retval; +	struct intel_mid_gpio_ddata *ddata = +				(struct intel_mid_gpio_ddata *)id->driver_data; + +	retval = pcim_enable_device(pdev); +	if (retval) +		return retval; + +	retval = pcim_iomap_regions(pdev, 1 << 0 | 1 << 1, pci_name(pdev)); +	if (retval) { +		dev_err(&pdev->dev, "I/O memory mapping error\n"); +		return retval; +	} + +	base = pcim_iomap_table(pdev)[1]; + +	irq_base = readl(base); +	gpio_base = readl(sizeof(u32) + base); + +	/* release the IO mapping, since we already get the info from bar1 */ +	pcim_iounmap_regions(pdev, 1 << 1); + +	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); +	if (!priv) { +		dev_err(&pdev->dev, "can't allocate chip data\n"); +		return -ENOMEM; +	} + +	priv->reg_base = pcim_iomap_table(pdev)[0]; +	priv->chip.label = dev_name(&pdev->dev); +	priv->chip.dev = &pdev->dev; +	priv->chip.request = intel_gpio_request; +	priv->chip.direction_input = intel_gpio_direction_input; +	priv->chip.direction_output = intel_gpio_direction_output; +	priv->chip.get = intel_gpio_get; +	priv->chip.set = intel_gpio_set; +	priv->chip.to_irq = intel_gpio_to_irq; +	priv->chip.base = gpio_base; +	priv->chip.ngpio = ddata->ngpio; +	priv->chip.can_sleep = false; +	priv->pdev = pdev; + +	spin_lock_init(&priv->lock); + +	priv->domain = irq_domain_add_simple(pdev->dev.of_node, ddata->ngpio, +					irq_base, &intel_gpio_irq_ops, priv); +	if (!priv->domain) +		return -ENOMEM; + +	pci_set_drvdata(pdev, priv); +	retval = gpiochip_add(&priv->chip); +	if (retval) { +		dev_err(&pdev->dev, "gpiochip_add error %d\n", retval); +		return retval; +	} + +	intel_mid_irq_init_hw(priv); + +	irq_set_handler_data(pdev->irq, priv); +	irq_set_chained_handler(pdev->irq, intel_mid_irq_handler); + +	pm_runtime_put_noidle(&pdev->dev); +	pm_runtime_allow(&pdev->dev); + +	return 0; +} + +static struct pci_driver intel_gpio_driver = { +	.name		= "intel_mid_gpio", +	.id_table	= intel_gpio_ids, +	.probe		= intel_gpio_probe, +	.driver		= { +		.pm	= &intel_gpio_pm_ops, +	}, +}; + +static int __init intel_gpio_init(void) +{ +	return pci_register_driver(&intel_gpio_driver); +} + +device_initcall(intel_gpio_init); diff --git a/drivers/gpio/gpio-iop.c b/drivers/gpio/gpio-iop.c new file mode 100644 index 00000000000..0a5e9d3f308 --- /dev/null +++ b/drivers/gpio/gpio-iop.c @@ -0,0 +1,132 @@ +/* + * arch/arm/plat-iop/gpio.c + * GPIO handling for Intel IOP3xx processors. + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ + +#include <linux/device.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/gpio.h> +#include <linux/export.h> +#include <linux/platform_device.h> +#include <linux/bitops.h> +#include <linux/io.h> + +#define IOP3XX_N_GPIOS	8 + +#define GPIO_IN			0 +#define GPIO_OUT		1 +#define GPIO_LOW		0 +#define GPIO_HIGH		1 + +/* Memory base offset */ +static void __iomem *base; + +#define IOP3XX_GPIO_REG(reg)	(base + (reg)) +#define IOP3XX_GPOE		IOP3XX_GPIO_REG(0x0000) +#define IOP3XX_GPID		IOP3XX_GPIO_REG(0x0004) +#define IOP3XX_GPOD		IOP3XX_GPIO_REG(0x0008) + +static void gpio_line_config(int line, int direction) +{ +	unsigned long flags; +	u32 val; + +	local_irq_save(flags); +	val = readl(IOP3XX_GPOE); +	if (direction == GPIO_IN) { +		val |= BIT(line); +	} else if (direction == GPIO_OUT) { +		val &= ~BIT(line); +	} +	writel(val, IOP3XX_GPOE); +	local_irq_restore(flags); +} + +static int gpio_line_get(int line) +{ +	return !!(readl(IOP3XX_GPID) & BIT(line)); +} + +static void gpio_line_set(int line, int value) +{ +	unsigned long flags; +	u32 val; + +	local_irq_save(flags); +	val = readl(IOP3XX_GPOD); +	if (value == GPIO_LOW) { +		val &= ~BIT(line); +	} else if (value == GPIO_HIGH) { +		val |= BIT(line); +	} +	writel(val, IOP3XX_GPOD); +	local_irq_restore(flags); +} + +static int iop3xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) +{ +	gpio_line_config(gpio, GPIO_IN); +	return 0; +} + +static int iop3xx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int level) +{ +	gpio_line_set(gpio, level); +	gpio_line_config(gpio, GPIO_OUT); +	return 0; +} + +static int iop3xx_gpio_get_value(struct gpio_chip *chip, unsigned gpio) +{ +	return gpio_line_get(gpio); +} + +static void iop3xx_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value) +{ +	gpio_line_set(gpio, value); +} + +static struct gpio_chip iop3xx_chip = { +	.label			= "iop3xx", +	.direction_input	= iop3xx_gpio_direction_input, +	.get			= iop3xx_gpio_get_value, +	.direction_output	= iop3xx_gpio_direction_output, +	.set			= iop3xx_gpio_set_value, +	.base			= 0, +	.ngpio			= IOP3XX_N_GPIOS, +}; + +static int iop3xx_gpio_probe(struct platform_device *pdev) +{ +	struct resource *res; + +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	base = devm_ioremap_resource(&pdev->dev, res); +	if (IS_ERR(base)) +		return PTR_ERR(base); + +	return gpiochip_add(&iop3xx_chip); +} + +static struct platform_driver iop3xx_gpio_driver = { +	.driver = { +		.name = "gpio-iop", +		.owner = THIS_MODULE, +	}, +	.probe = iop3xx_gpio_probe, +}; + +static int __init iop3xx_gpio_init(void) +{ +	return platform_driver_register(&iop3xx_gpio_driver); +} +arch_initcall(iop3xx_gpio_init); diff --git a/drivers/gpio/gpio-janz-ttl.c b/drivers/gpio/gpio-janz-ttl.c index 2ecd3a09c74..42852eaaf02 100644 --- a/drivers/gpio/gpio-janz-ttl.c +++ b/drivers/gpio/gpio-janz-ttl.c @@ -152,34 +152,21 @@ static int ttl_probe(struct platform_device *pdev)  	pdata = dev_get_platdata(&pdev->dev);  	if (!pdata) {  		dev_err(dev, "no platform data\n"); -		ret = -ENXIO; -		goto out_return; +		return -ENXIO;  	} -	mod = kzalloc(sizeof(*mod), GFP_KERNEL); -	if (!mod) { -		dev_err(dev, "unable to allocate private data\n"); -		ret = -ENOMEM; -		goto out_return; -	} +	mod = devm_kzalloc(dev, sizeof(*mod), GFP_KERNEL); +	if (!mod) +		return -ENOMEM;  	platform_set_drvdata(pdev, mod);  	spin_lock_init(&mod->lock);  	/* get access to the MODULbus registers for this module */  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		dev_err(dev, "MODULbus registers not found\n"); -		ret = -ENODEV; -		goto out_free_mod; -	} - -	mod->regs = ioremap(res->start, resource_size(res)); -	if (!mod->regs) { -		dev_err(dev, "MODULbus registers not ioremap\n"); -		ret = -ENOMEM; -		goto out_free_mod; -	} +	mod->regs = devm_ioremap_resource(dev, res); +	if (IS_ERR(mod->regs)) +		return PTR_ERR(mod->regs);  	ttl_setup_device(mod); @@ -198,17 +185,10 @@ static int ttl_probe(struct platform_device *pdev)  	ret = gpiochip_add(gpio);  	if (ret) {  		dev_err(dev, "unable to add GPIO chip\n"); -		goto out_iounmap_regs; +		return ret;  	}  	return 0; - -out_iounmap_regs: -	iounmap(mod->regs); -out_free_mod: -	kfree(mod); -out_return: -	return ret;  }  static int ttl_remove(struct platform_device *pdev) @@ -223,8 +203,6 @@ static int ttl_remove(struct platform_device *pdev)  		return ret;  	} -	iounmap(mod->regs); -	kfree(mod);  	return 0;  } diff --git a/drivers/gpio/gpio-kempld.c b/drivers/gpio/gpio-kempld.c index efdc3924d7d..1e5e51987d3 100644 --- a/drivers/gpio/gpio-kempld.c +++ b/drivers/gpio/gpio-kempld.c @@ -24,7 +24,7 @@  #include <linux/mfd/kempld.h>  #define KEMPLD_GPIO_MAX_NUM		16 -#define KEMPLD_GPIO_MASK(x)		(1 << ((x) % 8)) +#define KEMPLD_GPIO_MASK(x)		(BIT((x) % 8))  #define KEMPLD_GPIO_DIR_NUM(x)		(0x40 + (x) / 8)  #define KEMPLD_GPIO_LVL_NUM(x)		(0x42 + (x) / 8)  #define KEMPLD_GPIO_EVT_LVL_EDGE	0x46 @@ -167,7 +167,7 @@ static int kempld_gpio_probe(struct platform_device *pdev)  	chip->label = "gpio-kempld";  	chip->owner = THIS_MODULE;  	chip->dev = dev; -	chip->can_sleep = 1; +	chip->can_sleep = true;  	if (pdata && pdata->gpio_base)  		chip->base = pdata->gpio_base;  	else @@ -216,4 +216,4 @@ module_platform_driver(kempld_gpio_driver);  MODULE_DESCRIPTION("KEM PLD GPIO Driver");  MODULE_AUTHOR("Michael Brunner <michael.brunner@kontron.com>");  MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:gpio-kempld"); +MODULE_ALIAS("platform:kempld-gpio"); diff --git a/drivers/gpio/gpio-ks8695.c b/drivers/gpio/gpio-ks8695.c index a3ac66ea364..464a83de0d6 100644 --- a/drivers/gpio/gpio-ks8695.c +++ b/drivers/gpio/gpio-ks8695.c @@ -228,7 +228,7 @@ static struct gpio_chip ks8695_gpio_chip = {  	.to_irq			= ks8695_gpio_to_irq,  	.base			= 0,  	.ngpio			= 16, -	.can_sleep		= 0, +	.can_sleep		= false,  };  /* Register the GPIOs */ diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c deleted file mode 100644 index bfa1af1b519..00000000000 --- a/drivers/gpio/gpio-langwell.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Moorestown platform Langwell chip GPIO driver - * - * Copyright (c) 2008, 2009, 2013, Intel Corporation. - * - * 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, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* Supports: - * Moorestown platform Langwell chip. - * Medfield platform Penwell chip. - */ - -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/platform_device.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/stddef.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/irq.h> -#include <linux/io.h> -#include <linux/gpio.h> -#include <linux/slab.h> -#include <linux/pm_runtime.h> -#include <linux/irqdomain.h> - -/* - * Langwell chip has 64 pins and thus there are 2 32bit registers to control - * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit - * registers to control them, so we only define the order here instead of a - * structure, to get a bit offset for a pin (use GPDR as an example): - * - * nreg = ngpio / 32; - * reg = offset / 32; - * bit = offset % 32; - * reg_addr = reg_base + GPDR * nreg * 4 + reg * 4; - * - * so the bit of reg_addr is to control pin offset's GPDR feature -*/ - -enum GPIO_REG { -	GPLR = 0,	/* pin level read-only */ -	GPDR,		/* pin direction */ -	GPSR,		/* pin set */ -	GPCR,		/* pin clear */ -	GRER,		/* rising edge detect */ -	GFER,		/* falling edge detect */ -	GEDR,		/* edge detect result */ -	GAFR,		/* alt function */ -}; - -struct lnw_gpio { -	struct gpio_chip		chip; -	void __iomem			*reg_base; -	spinlock_t			lock; -	struct pci_dev			*pdev; -	struct irq_domain		*domain; -}; - -#define to_lnw_priv(chip)	container_of(chip, struct lnw_gpio, chip) - -static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset, -			      enum GPIO_REG reg_type) -{ -	struct lnw_gpio *lnw = to_lnw_priv(chip); -	unsigned nreg = chip->ngpio / 32; -	u8 reg = offset / 32; - -	return lnw->reg_base + reg_type * nreg * 4 + reg * 4; -} - -static void __iomem *gpio_reg_2bit(struct gpio_chip *chip, unsigned offset, -				   enum GPIO_REG reg_type) -{ -	struct lnw_gpio *lnw = to_lnw_priv(chip); -	unsigned nreg = chip->ngpio / 32; -	u8 reg = offset / 16; - -	return lnw->reg_base + reg_type * nreg * 4 + reg * 4; -} - -static int lnw_gpio_request(struct gpio_chip *chip, unsigned offset) -{ -	void __iomem *gafr = gpio_reg_2bit(chip, offset, GAFR); -	u32 value = readl(gafr); -	int shift = (offset % 16) << 1, af = (value >> shift) & 3; - -	if (af) { -		value &= ~(3 << shift); -		writel(value, gafr); -	} -	return 0; -} - -static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset) -{ -	void __iomem *gplr = gpio_reg(chip, offset, GPLR); - -	return readl(gplr) & BIT(offset % 32); -} - -static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ -	void __iomem *gpsr, *gpcr; - -	if (value) { -		gpsr = gpio_reg(chip, offset, GPSR); -		writel(BIT(offset % 32), gpsr); -	} else { -		gpcr = gpio_reg(chip, offset, GPCR); -		writel(BIT(offset % 32), gpcr); -	} -} - -static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ -	struct lnw_gpio *lnw = to_lnw_priv(chip); -	void __iomem *gpdr = gpio_reg(chip, offset, GPDR); -	u32 value; -	unsigned long flags; - -	if (lnw->pdev) -		pm_runtime_get(&lnw->pdev->dev); - -	spin_lock_irqsave(&lnw->lock, flags); -	value = readl(gpdr); -	value &= ~BIT(offset % 32); -	writel(value, gpdr); -	spin_unlock_irqrestore(&lnw->lock, flags); - -	if (lnw->pdev) -		pm_runtime_put(&lnw->pdev->dev); - -	return 0; -} - -static int lnw_gpio_direction_output(struct gpio_chip *chip, -			unsigned offset, int value) -{ -	struct lnw_gpio *lnw = to_lnw_priv(chip); -	void __iomem *gpdr = gpio_reg(chip, offset, GPDR); -	unsigned long flags; - -	lnw_gpio_set(chip, offset, value); - -	if (lnw->pdev) -		pm_runtime_get(&lnw->pdev->dev); - -	spin_lock_irqsave(&lnw->lock, flags); -	value = readl(gpdr); -	value |= BIT(offset % 32); -	writel(value, gpdr); -	spin_unlock_irqrestore(&lnw->lock, flags); - -	if (lnw->pdev) -		pm_runtime_put(&lnw->pdev->dev); - -	return 0; -} - -static int lnw_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ -	struct lnw_gpio *lnw = to_lnw_priv(chip); -	return irq_create_mapping(lnw->domain, offset); -} - -static int lnw_irq_type(struct irq_data *d, unsigned type) -{ -	struct lnw_gpio *lnw = irq_data_get_irq_chip_data(d); -	u32 gpio = irqd_to_hwirq(d); -	unsigned long flags; -	u32 value; -	void __iomem *grer = gpio_reg(&lnw->chip, gpio, GRER); -	void __iomem *gfer = gpio_reg(&lnw->chip, gpio, GFER); - -	if (gpio >= lnw->chip.ngpio) -		return -EINVAL; - -	if (lnw->pdev) -		pm_runtime_get(&lnw->pdev->dev); - -	spin_lock_irqsave(&lnw->lock, flags); -	if (type & IRQ_TYPE_EDGE_RISING) -		value = readl(grer) | BIT(gpio % 32); -	else -		value = readl(grer) & (~BIT(gpio % 32)); -	writel(value, grer); - -	if (type & IRQ_TYPE_EDGE_FALLING) -		value = readl(gfer) | BIT(gpio % 32); -	else -		value = readl(gfer) & (~BIT(gpio % 32)); -	writel(value, gfer); -	spin_unlock_irqrestore(&lnw->lock, flags); - -	if (lnw->pdev) -		pm_runtime_put(&lnw->pdev->dev); - -	return 0; -} - -static void lnw_irq_unmask(struct irq_data *d) -{ -} - -static void lnw_irq_mask(struct irq_data *d) -{ -} - -static struct irq_chip lnw_irqchip = { -	.name		= "LNW-GPIO", -	.irq_mask	= lnw_irq_mask, -	.irq_unmask	= lnw_irq_unmask, -	.irq_set_type	= lnw_irq_type, -}; - -static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = {   /* pin number */ -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), .driver_data = 64 }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f), .driver_data = 96 }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a), .driver_data = 96 }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08eb), .driver_data = 96 }, -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08f7), .driver_data = 96 }, -	{ 0, } -}; -MODULE_DEVICE_TABLE(pci, lnw_gpio_ids); - -static void lnw_irq_handler(unsigned irq, struct irq_desc *desc) -{ -	struct irq_data *data = irq_desc_get_irq_data(desc); -	struct lnw_gpio *lnw = irq_data_get_irq_handler_data(data); -	struct irq_chip *chip = irq_data_get_irq_chip(data); -	u32 base, gpio, mask; -	unsigned long pending; -	void __iomem *gedr; - -	/* check GPIO controller to check which pin triggered the interrupt */ -	for (base = 0; base < lnw->chip.ngpio; base += 32) { -		gedr = gpio_reg(&lnw->chip, base, GEDR); -		while ((pending = readl(gedr))) { -			gpio = __ffs(pending); -			mask = BIT(gpio); -			/* Clear before handling so we can't lose an edge */ -			writel(mask, gedr); -			generic_handle_irq(irq_find_mapping(lnw->domain, -							    base + gpio)); -		} -	} - -	chip->irq_eoi(data); -} - -static void lnw_irq_init_hw(struct lnw_gpio *lnw) -{ -	void __iomem *reg; -	unsigned base; - -	for (base = 0; base < lnw->chip.ngpio; base += 32) { -		/* Clear the rising-edge detect register */ -		reg = gpio_reg(&lnw->chip, base, GRER); -		writel(0, reg); -		/* Clear the falling-edge detect register */ -		reg = gpio_reg(&lnw->chip, base, GFER); -		writel(0, reg); -		/* Clear the edge detect status register */ -		reg = gpio_reg(&lnw->chip, base, GEDR); -		writel(~0, reg); -	} -} - -static int lnw_gpio_irq_map(struct irq_domain *d, unsigned int virq, -			    irq_hw_number_t hw) -{ -	struct lnw_gpio *lnw = d->host_data; - -	irq_set_chip_and_handler_name(virq, &lnw_irqchip, handle_simple_irq, -				      "demux"); -	irq_set_chip_data(virq, lnw); -	irq_set_irq_type(virq, IRQ_TYPE_NONE); - -	return 0; -} - -static const struct irq_domain_ops lnw_gpio_irq_ops = { -	.map = lnw_gpio_irq_map, -	.xlate = irq_domain_xlate_twocell, -}; - -static int lnw_gpio_runtime_idle(struct device *dev) -{ -	pm_schedule_suspend(dev, 500); -	return -EBUSY; -} - -static const struct dev_pm_ops lnw_gpio_pm_ops = { -	SET_RUNTIME_PM_OPS(NULL, NULL, lnw_gpio_runtime_idle) -}; - -static int lnw_gpio_probe(struct pci_dev *pdev, -			  const struct pci_device_id *id) -{ -	void __iomem *base; -	struct lnw_gpio *lnw; -	u32 gpio_base; -	u32 irq_base; -	int retval; -	int ngpio = id->driver_data; - -	retval = pcim_enable_device(pdev); -	if (retval) -		return retval; - -	retval = pcim_iomap_regions(pdev, 1 << 0 | 1 << 1, pci_name(pdev)); -	if (retval) { -		dev_err(&pdev->dev, "I/O memory mapping error\n"); -		return retval; -	} - -	base = pcim_iomap_table(pdev)[1]; - -	irq_base = readl(base); -	gpio_base = readl(sizeof(u32) + base); - -	/* release the IO mapping, since we already get the info from bar1 */ -	pcim_iounmap_regions(pdev, 1 << 1); - -	lnw = devm_kzalloc(&pdev->dev, sizeof(*lnw), GFP_KERNEL); -	if (!lnw) { -		dev_err(&pdev->dev, "can't allocate chip data\n"); -		return -ENOMEM; -	} - -	lnw->reg_base = pcim_iomap_table(pdev)[0]; -	lnw->chip.label = dev_name(&pdev->dev); -	lnw->chip.request = lnw_gpio_request; -	lnw->chip.direction_input = lnw_gpio_direction_input; -	lnw->chip.direction_output = lnw_gpio_direction_output; -	lnw->chip.get = lnw_gpio_get; -	lnw->chip.set = lnw_gpio_set; -	lnw->chip.to_irq = lnw_gpio_to_irq; -	lnw->chip.base = gpio_base; -	lnw->chip.ngpio = ngpio; -	lnw->chip.can_sleep = 0; -	lnw->pdev = pdev; - -	spin_lock_init(&lnw->lock); - -	lnw->domain = irq_domain_add_simple(pdev->dev.of_node, ngpio, irq_base, -					    &lnw_gpio_irq_ops, lnw); -	if (!lnw->domain) -		return -ENOMEM; - -	pci_set_drvdata(pdev, lnw); -	retval = gpiochip_add(&lnw->chip); -	if (retval) { -		dev_err(&pdev->dev, "gpiochip_add error %d\n", retval); -		return retval; -	} - -	lnw_irq_init_hw(lnw); - -	irq_set_handler_data(pdev->irq, lnw); -	irq_set_chained_handler(pdev->irq, lnw_irq_handler); - -	pm_runtime_put_noidle(&pdev->dev); -	pm_runtime_allow(&pdev->dev); - -	return 0; -} - -static struct pci_driver lnw_gpio_driver = { -	.name		= "langwell_gpio", -	.id_table	= lnw_gpio_ids, -	.probe		= lnw_gpio_probe, -	.driver		= { -		.pm	= &lnw_gpio_pm_ops, -	}, -}; - -static int __init lnw_gpio_init(void) -{ -	return pci_register_driver(&lnw_gpio_driver); -} - -device_initcall(lnw_gpio_init); diff --git a/drivers/gpio/gpio-lp3943.c b/drivers/gpio/gpio-lp3943.c new file mode 100644 index 00000000000..a0341c92bcb --- /dev/null +++ b/drivers/gpio/gpio-lp3943.c @@ -0,0 +1,242 @@ +/* + * TI/National Semiconductor LP3943 GPIO driver + * + * Copyright 2013 Texas Instruments + * + * Author: Milo Kim <milo.kim@ti.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2. + */ + +#include <linux/bitops.h> +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/i2c.h> +#include <linux/mfd/lp3943.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +enum lp3943_gpios { +	LP3943_GPIO1, +	LP3943_GPIO2, +	LP3943_GPIO3, +	LP3943_GPIO4, +	LP3943_GPIO5, +	LP3943_GPIO6, +	LP3943_GPIO7, +	LP3943_GPIO8, +	LP3943_GPIO9, +	LP3943_GPIO10, +	LP3943_GPIO11, +	LP3943_GPIO12, +	LP3943_GPIO13, +	LP3943_GPIO14, +	LP3943_GPIO15, +	LP3943_GPIO16, +	LP3943_MAX_GPIO, +}; + +struct lp3943_gpio { +	struct gpio_chip chip; +	struct lp3943 *lp3943; +	u16 input_mask;		/* 1 = GPIO is input direction, 0 = output */ +}; + +static inline struct lp3943_gpio *to_lp3943_gpio(struct gpio_chip *_chip) +{ +	return container_of(_chip, struct lp3943_gpio, chip); +} + +static int lp3943_gpio_request(struct gpio_chip *chip, unsigned offset) +{ +	struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip); +	struct lp3943 *lp3943 = lp3943_gpio->lp3943; + +	/* Return an error if the pin is already assigned */ +	if (test_and_set_bit(offset, &lp3943->pin_used)) +		return -EBUSY; + +	return 0; +} + +static void lp3943_gpio_free(struct gpio_chip *chip, unsigned offset) +{ +	struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip); +	struct lp3943 *lp3943 = lp3943_gpio->lp3943; + +	clear_bit(offset, &lp3943->pin_used); +} + +static int lp3943_gpio_set_mode(struct lp3943_gpio *lp3943_gpio, u8 offset, +				u8 val) +{ +	struct lp3943 *lp3943 = lp3943_gpio->lp3943; +	const struct lp3943_reg_cfg *mux = lp3943->mux_cfg; + +	return lp3943_update_bits(lp3943, mux[offset].reg, mux[offset].mask, +				  val << mux[offset].shift); +} + +static int lp3943_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ +	struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip); + +	lp3943_gpio->input_mask |= BIT(offset); + +	return lp3943_gpio_set_mode(lp3943_gpio, offset, LP3943_GPIO_IN); +} + +static int lp3943_get_gpio_in_status(struct lp3943_gpio *lp3943_gpio, +				     struct gpio_chip *chip, unsigned offset) +{ +	u8 addr, read; +	int err; + +	switch (offset) { +	case LP3943_GPIO1 ... LP3943_GPIO8: +		addr = LP3943_REG_GPIO_A; +		break; +	case LP3943_GPIO9 ... LP3943_GPIO16: +		addr = LP3943_REG_GPIO_B; +		offset = offset - 8; +		break; +	default: +		return -EINVAL; +	} + +	err = lp3943_read_byte(lp3943_gpio->lp3943, addr, &read); +	if (err) +		return err; + +	return !!(read & BIT(offset)); +} + +static int lp3943_get_gpio_out_status(struct lp3943_gpio *lp3943_gpio, +				      struct gpio_chip *chip, unsigned offset) +{ +	struct lp3943 *lp3943 = lp3943_gpio->lp3943; +	const struct lp3943_reg_cfg *mux = lp3943->mux_cfg; +	u8 read; +	int err; + +	err = lp3943_read_byte(lp3943, mux[offset].reg, &read); +	if (err) +		return err; + +	read = (read & mux[offset].mask) >> mux[offset].shift; + +	if (read == LP3943_GPIO_OUT_HIGH) +		return 1; +	else if (read == LP3943_GPIO_OUT_LOW) +		return 0; +	else +		return -EINVAL; +} + +static int lp3943_gpio_get(struct gpio_chip *chip, unsigned offset) +{ +	struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip); + +	/* +	 * Limitation: +	 *   LP3943 doesn't have the GPIO direction register. It provides +	 *   only input and output status registers. +	 *   So, direction info is required to handle the 'get' operation. +	 *   This variable is updated whenever the direction is changed and +	 *   it is used here. +	 */ + +	if (lp3943_gpio->input_mask & BIT(offset)) +		return lp3943_get_gpio_in_status(lp3943_gpio, chip, offset); +	else +		return lp3943_get_gpio_out_status(lp3943_gpio, chip, offset); +} + +static void lp3943_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ +	struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip); +	u8 data; + +	if (value) +		data = LP3943_GPIO_OUT_HIGH; +	else +		data = LP3943_GPIO_OUT_LOW; + +	lp3943_gpio_set_mode(lp3943_gpio, offset, data); +} + +static int lp3943_gpio_direction_output(struct gpio_chip *chip, unsigned offset, +					int value) +{ +	struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip); + +	lp3943_gpio_set(chip, offset, value); +	lp3943_gpio->input_mask &= ~BIT(offset); + +	return 0; +} + +static const struct gpio_chip lp3943_gpio_chip = { +	.label			= "lp3943", +	.owner			= THIS_MODULE, +	.request		= lp3943_gpio_request, +	.free			= lp3943_gpio_free, +	.direction_input	= lp3943_gpio_direction_input, +	.get			= lp3943_gpio_get, +	.direction_output	= lp3943_gpio_direction_output, +	.set			= lp3943_gpio_set, +	.base			= -1, +	.ngpio			= LP3943_MAX_GPIO, +	.can_sleep		= 1, +}; + +static int lp3943_gpio_probe(struct platform_device *pdev) +{ +	struct lp3943 *lp3943 = dev_get_drvdata(pdev->dev.parent); +	struct lp3943_gpio *lp3943_gpio; + +	lp3943_gpio = devm_kzalloc(&pdev->dev, sizeof(*lp3943_gpio), +				GFP_KERNEL); +	if (!lp3943_gpio) +		return -ENOMEM; + +	lp3943_gpio->lp3943 = lp3943; +	lp3943_gpio->chip = lp3943_gpio_chip; +	lp3943_gpio->chip.dev = &pdev->dev; + +	platform_set_drvdata(pdev, lp3943_gpio); + +	return gpiochip_add(&lp3943_gpio->chip); +} + +static int lp3943_gpio_remove(struct platform_device *pdev) +{ +	struct lp3943_gpio *lp3943_gpio = platform_get_drvdata(pdev); + +	return gpiochip_remove(&lp3943_gpio->chip); +} + +static const struct of_device_id lp3943_gpio_of_match[] = { +	{ .compatible = "ti,lp3943-gpio", }, +	{ } +}; +MODULE_DEVICE_TABLE(of, lp3943_gpio_of_match); + +static struct platform_driver lp3943_gpio_driver = { +	.probe = lp3943_gpio_probe, +	.remove = lp3943_gpio_remove, +	.driver = { +		.name = "lp3943-gpio", +		.owner = THIS_MODULE, +		.of_match_table = lp3943_gpio_of_match, +	}, +}; +module_platform_driver(lp3943_gpio_driver); + +MODULE_DESCRIPTION("LP3943 GPIO driver"); +MODULE_ALIAS("platform:lp3943-gpio"); +MODULE_AUTHOR("Milo Kim"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index 90a80eb688a..225344d6640 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -21,13 +21,14 @@  #include <linux/io.h>  #include <linux/errno.h>  #include <linux/gpio.h> +#include <linux/of.h>  #include <linux/of_gpio.h>  #include <linux/platform_device.h>  #include <linux/module.h> +#include <linux/platform_data/gpio-lpc32xx.h>  #include <mach/hardware.h>  #include <mach/platform.h> -#include <mach/gpio-lpc32xx.h>  #include <mach/irqs.h>  #define LPC32XX_GPIO_P3_INP_STATE		_GPREG(0x000) @@ -447,7 +448,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {  			.base			= LPC32XX_GPIO_P0_GRP,  			.ngpio			= LPC32XX_GPIO_P0_MAX,  			.names			= gpio_p0_names, -			.can_sleep		= 0, +			.can_sleep		= false,  		},  		.gpio_grp = &gpio_grp_regs_p0,  	}, @@ -463,7 +464,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {  			.base			= LPC32XX_GPIO_P1_GRP,  			.ngpio			= LPC32XX_GPIO_P1_MAX,  			.names			= gpio_p1_names, -			.can_sleep		= 0, +			.can_sleep		= false,  		},  		.gpio_grp = &gpio_grp_regs_p1,  	}, @@ -478,7 +479,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {  			.base			= LPC32XX_GPIO_P2_GRP,  			.ngpio			= LPC32XX_GPIO_P2_MAX,  			.names			= gpio_p2_names, -			.can_sleep		= 0, +			.can_sleep		= false,  		},  		.gpio_grp = &gpio_grp_regs_p2,  	}, @@ -494,7 +495,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {  			.base			= LPC32XX_GPIO_P3_GRP,  			.ngpio			= LPC32XX_GPIO_P3_MAX,  			.names			= gpio_p3_names, -			.can_sleep		= 0, +			.can_sleep		= false,  		},  		.gpio_grp = &gpio_grp_regs_p3,  	}, @@ -508,7 +509,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {  			.base			= LPC32XX_GPI_P3_GRP,  			.ngpio			= LPC32XX_GPI_P3_MAX,  			.names			= gpi_p3_names, -			.can_sleep		= 0, +			.can_sleep		= false,  		},  		.gpio_grp = &gpio_grp_regs_p3,  	}, @@ -522,7 +523,7 @@ static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {  			.base			= LPC32XX_GPO_P3_GRP,  			.ngpio			= LPC32XX_GPO_P3_MAX,  			.names			= gpo_p3_names, -			.can_sleep		= 0, +			.can_sleep		= false,  		},  		.gpio_grp = &gpio_grp_regs_p3,  	}, diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c index 2d9ca6055e5..2bea89b7250 100644 --- a/drivers/gpio/gpio-lynxpoint.c +++ b/drivers/gpio/gpio-lynxpoint.c @@ -188,7 +188,7 @@ static int lp_irq_type(struct irq_data *d, unsigned type)  static int lp_gpio_get(struct gpio_chip *chip, unsigned offset)  {  	unsigned long reg = lp_gpio_reg(chip, offset, LP_CONFIG1); -	return inl(reg) & IN_LVL_BIT; +	return !!(inl(reg) & IN_LVL_BIT);  }  static void lp_gpio_set(struct gpio_chip *chip, unsigned offset, int value) @@ -242,26 +242,28 @@ static int lp_gpio_to_irq(struct gpio_chip *chip, unsigned offset)  	return irq_create_mapping(lg->domain, offset);  } -static void lp_gpio_irq_handler(unsigned irq, struct irq_desc *desc) +static void lp_gpio_irq_handler(unsigned hwirq, struct irq_desc *desc)  {  	struct irq_data *data = irq_desc_get_irq_data(desc);  	struct lp_gpio *lg = irq_data_get_irq_handler_data(data);  	struct irq_chip *chip = irq_data_get_irq_chip(data);  	u32 base, pin, mask; -	unsigned long reg, pending; -	unsigned virq; +	unsigned long reg, ena, pending;  	/* check from GPIO controller which pin triggered the interrupt */  	for (base = 0; base < lg->chip.ngpio; base += 32) {  		reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT); +		ena = lp_gpio_reg(&lg->chip, base, LP_INT_ENABLE); + +		while ((pending = (inl(reg) & inl(ena)))) { +			unsigned irq; -		while ((pending = inl(reg))) {  			pin = __ffs(pending);  			mask = BIT(pin);  			/* Clear before handling so we don't lose an edge */  			outl(mask, reg); -			virq = irq_find_mapping(lg->domain, base + pin); -			generic_handle_irq(virq); +			irq = irq_find_mapping(lg->domain, base + pin); +			generic_handle_irq(irq);  		}  	}  	chip->irq_eoi(data); @@ -299,6 +301,26 @@ static void lp_irq_disable(struct irq_data *d)  	spin_unlock_irqrestore(&lg->lock, flags);  } +static int lp_irq_reqres(struct irq_data *d) +{ +	struct lp_gpio *lg = irq_data_get_irq_chip_data(d); + +	if (gpio_lock_as_irq(&lg->chip, irqd_to_hwirq(d))) { +		dev_err(lg->chip.dev, +			"unable to lock HW IRQ %lu for IRQ\n", +			irqd_to_hwirq(d)); +		return -EINVAL; +	} +	return 0; +} + +static void lp_irq_relres(struct irq_data *d) +{ +	struct lp_gpio *lg = irq_data_get_irq_chip_data(d); + +	gpio_unlock_as_irq(&lg->chip, irqd_to_hwirq(d)); +} +  static struct irq_chip lp_irqchip = {  	.name = "LP-GPIO",  	.irq_mask = lp_irq_mask, @@ -306,6 +328,8 @@ static struct irq_chip lp_irqchip = {  	.irq_enable = lp_irq_enable,  	.irq_disable = lp_irq_disable,  	.irq_set_type = lp_irq_type, +	.irq_request_resources = lp_irq_reqres, +	.irq_release_resources = lp_irq_relres,  	.flags = IRQCHIP_SKIP_SET_WAKE,  }; @@ -324,15 +348,14 @@ static void lp_gpio_irq_init_hw(struct lp_gpio *lg)  	}  } -static int lp_gpio_irq_map(struct irq_domain *d, unsigned int virq, -			    irq_hw_number_t hw) +static int lp_gpio_irq_map(struct irq_domain *d, unsigned int irq, +			    irq_hw_number_t hwirq)  {  	struct lp_gpio *lg = d->host_data; -	irq_set_chip_and_handler_name(virq, &lp_irqchip, handle_simple_irq, -				      "demux"); -	irq_set_chip_data(virq, lg); -	irq_set_irq_type(virq, IRQ_TYPE_NONE); +	irq_set_chip_and_handler(irq, &lp_irqchip, handle_simple_irq); +	irq_set_chip_data(irq, lg); +	irq_set_irq_type(irq, IRQ_TYPE_NONE);  	return 0;  } @@ -352,10 +375,8 @@ static int lp_gpio_probe(struct platform_device *pdev)  	int ret = -ENODEV;  	lg = devm_kzalloc(dev, sizeof(struct lp_gpio), GFP_KERNEL); -	if (!lg) { -		dev_err(dev, "can't allocate lp_gpio chip data\n"); +	if (!lg)  		return -ENOMEM; -	}  	lg->pdev = pdev;  	platform_set_drvdata(pdev, lg); @@ -390,7 +411,7 @@ static int lp_gpio_probe(struct platform_device *pdev)  	gc->set = lp_gpio_set;  	gc->base = -1;  	gc->ngpio = LP_NUM_GPIO; -	gc->can_sleep = 0; +	gc->can_sleep = false;  	gc->dev = dev;  	/* set up interrupts  */ @@ -436,6 +457,7 @@ static const struct dev_pm_ops lp_gpio_pm_ops = {  static const struct acpi_device_id lynxpoint_gpio_acpi_match[] = {  	{ "INT33C7", 0 }, +	{ "INT3437", 0 },  	{ }  };  MODULE_DEVICE_TABLE(acpi, lynxpoint_gpio_acpi_match); @@ -467,4 +489,15 @@ static int __init lp_gpio_init(void)  	return platform_driver_register(&lp_gpio_driver);  } +static void __exit lp_gpio_exit(void) +{ +	platform_driver_unregister(&lp_gpio_driver); +} +  subsys_initcall(lp_gpio_init); +module_exit(lp_gpio_exit); + +MODULE_AUTHOR("Mathias Nyman (Intel)"); +MODULE_DESCRIPTION("GPIO interface for Intel Lynxpoint"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:lp_gpio"); diff --git a/drivers/gpio/gpio-max730x.c b/drivers/gpio/gpio-max730x.c index f4f4ed19bdc..0814584fcdc 100644 --- a/drivers/gpio/gpio-max730x.c +++ b/drivers/gpio/gpio-max730x.c @@ -188,7 +188,7 @@ int __max730x_probe(struct max7301 *ts)  	ts->chip.set = max7301_set;  	ts->chip.ngpio = PIN_NUMBER; -	ts->chip.can_sleep = 1; +	ts->chip.can_sleep = true;  	ts->chip.dev = dev;  	ts->chip.owner = THIS_MODULE; @@ -220,7 +220,6 @@ int __max730x_probe(struct max7301 *ts)  	return ret;  exit_destroy: -	dev_set_drvdata(dev, NULL);  	mutex_destroy(&ts->lock);  	return ret;  } @@ -234,16 +233,13 @@ int __max730x_remove(struct device *dev)  	if (ts == NULL)  		return -ENODEV; -	dev_set_drvdata(dev, NULL); -  	/* Power down the chip and disable IRQ output */  	ts->write(dev, 0x04, 0x00);  	ret = gpiochip_remove(&ts->chip); -	if (!ret) { +	if (!ret)  		mutex_destroy(&ts->lock); -		kfree(ts); -	} else +	else  		dev_err(dev, "Failed to remove GPIO controller: %d\n", ret);  	return ret; diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c index 91ad74dea8c..7c36f2b0983 100644 --- a/drivers/gpio/gpio-max732x.c +++ b/drivers/gpio/gpio-max732x.c @@ -564,7 +564,7 @@ static int max732x_setup_gpio(struct max732x_chip *chip,  		gc->set = max732x_gpio_set_value;  	}  	gc->get = max732x_gpio_get_value; -	gc->can_sleep = 1; +	gc->can_sleep = true;  	gc->base = gpio_start;  	gc->ngpio = port; @@ -622,6 +622,13 @@ static int max732x_probe(struct i2c_client *client,  		goto out_failed;  	} +	if (nr_port > 8 && !chip->client_dummy) { +		dev_err(&client->dev, +			"Failed to allocate second group I2C device\n"); +		ret = -ENODEV; +		goto out_failed; +	} +  	mutex_init(&chip->lock);  	max732x_readb(chip, is_group_a(chip, 0), &chip->reg_out[0]); @@ -647,6 +654,8 @@ static int max732x_probe(struct i2c_client *client,  	return 0;  out_failed: +	if (chip->client_dummy) +		i2c_unregister_device(chip->client_dummy);  	max732x_irq_teardown(chip);  	return ret;  } diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c index 3fd2caa4a2e..553a80a5eaf 100644 --- a/drivers/gpio/gpio-mc33880.c +++ b/drivers/gpio/gpio-mc33880.c @@ -115,7 +115,7 @@ static int mc33880_probe(struct spi_device *spi)  	mc->chip.set = mc33880_set;  	mc->chip.base = pdata->base;  	mc->chip.ngpio = PIN_NUMBER; -	mc->chip.can_sleep = 1; +	mc->chip.can_sleep = true;  	mc->chip.dev = &spi->dev;  	mc->chip.owner = THIS_MODULE; @@ -142,7 +142,6 @@ static int mc33880_probe(struct spi_device *spi)  	return ret;  exit_destroy: -	spi_set_drvdata(spi, NULL);  	mutex_destroy(&mc->lock);  	return ret;  } @@ -156,8 +155,6 @@ static int mc33880_remove(struct spi_device *spi)  	if (mc == NULL)  		return -ENODEV; -	spi_set_drvdata(spi, NULL); -  	ret = gpiochip_remove(&mc->chip);  	if (!ret)  		mutex_destroy(&mc->lock); diff --git a/drivers/gpio/gpio-mc9s08dz60.c b/drivers/gpio/gpio-mc9s08dz60.c index 0ab700046a2..dce35ff00db 100644 --- a/drivers/gpio/gpio-mc9s08dz60.c +++ b/drivers/gpio/gpio-mc9s08dz60.c @@ -102,7 +102,7 @@ static int mc9s08dz60_probe(struct i2c_client *client,  	mc9s->chip.dev = &client->dev;  	mc9s->chip.owner = THIS_MODULE;  	mc9s->chip.ngpio = GPIO_NUM; -	mc9s->chip.can_sleep = 1; +	mc9s->chip.can_sleep = true;  	mc9s->chip.get = mc9s08dz60_get_value;  	mc9s->chip.set = mc9s08dz60_set_value;  	mc9s->chip.direction_output = mc9s08dz60_direction_output; diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index 2deb0c5e54a..57adbc90fda 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -1,5 +1,13 @@  /* - * MCP23S08 SPI/GPIO gpio expander driver + * MCP23S08 SPI/I2C GPIO gpio expander driver + * + * The inputs and outputs of the mcp23s08, mcp23s17, mcp23008 and mcp23017 are + * supported. + * For the I2C versions of the chips (mcp23008 and mcp23017) generation of + * interrupts is also supported. + * The hardware of the SPI versions of the chips (mcp23s08 and mcp23s17) is + * also capable of generating interrupts, but the linux driver does not + * support that yet.   */  #include <linux/kernel.h> @@ -12,7 +20,8 @@  #include <linux/spi/mcp23s08.h>  #include <linux/slab.h>  #include <asm/byteorder.h> -#include <linux/of.h> +#include <linux/interrupt.h> +#include <linux/of_irq.h>  #include <linux/of_device.h>  /** @@ -34,6 +43,7 @@  #define MCP_DEFVAL	0x03  #define MCP_INTCON	0x04  #define MCP_IOCON	0x05 +#	define IOCON_MIRROR	(1 << 6)  #	define IOCON_SEQOP	(1 << 5)  #	define IOCON_HAEN	(1 << 3)  #	define IOCON_ODR	(1 << 2) @@ -57,8 +67,14 @@ struct mcp23s08 {  	u8			addr;  	u16			cache[11]; +	u16			irq_rise; +	u16			irq_fall; +	int			irq; +	bool			irq_controller;  	/* lock protects the cached values */  	struct mutex		lock; +	struct mutex		irq_lock; +	struct irq_domain	*irq_domain;  	struct gpio_chip	chip; @@ -77,6 +93,11 @@ struct mcp23s08_driver_data {  	struct mcp23s08		chip[];  }; +/* This lock class tells lockdep that GPIO irqs are in a different + * category than their parents, so it won't report false recursion. + */ +static struct lock_class_key gpio_lock_class; +  /*----------------------------------------------------------------------*/  #if IS_ENABLED(CONFIG_I2C) @@ -152,7 +173,7 @@ static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)  	tx[0] = mcp->addr | 0x01;  	tx[1] = reg; -	status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx); +	status = spi_write_then_read(mcp->data, tx, sizeof(tx), rx, sizeof(rx));  	return (status < 0) ? status : rx[0];  } @@ -163,7 +184,7 @@ static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)  	tx[0] = mcp->addr;  	tx[1] = reg;  	tx[2] = val; -	return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0); +	return spi_write_then_read(mcp->data, tx, sizeof(tx), NULL, 0);  }  static int @@ -172,13 +193,13 @@ mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)  	u8	tx[2], *tmp;  	int	status; -	if ((n + reg) > sizeof mcp->cache) +	if ((n + reg) > sizeof(mcp->cache))  		return -EINVAL;  	tx[0] = mcp->addr | 0x01;  	tx[1] = reg;  	tmp = (u8 *)vals; -	status = spi_write_then_read(mcp->data, tx, sizeof tx, tmp, n); +	status = spi_write_then_read(mcp->data, tx, sizeof(tx), tmp, n);  	if (status >= 0) {  		while (n--)  			vals[n] = tmp[n]; /* expand to 16bit */ @@ -193,7 +214,7 @@ static int mcp23s17_read(struct mcp23s08 *mcp, unsigned reg)  	tx[0] = mcp->addr | 0x01;  	tx[1] = reg << 1; -	status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx); +	status = spi_write_then_read(mcp->data, tx, sizeof(tx), rx, sizeof(rx));  	return (status < 0) ? status : (rx[0] | (rx[1] << 8));  } @@ -205,7 +226,7 @@ static int mcp23s17_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)  	tx[1] = reg << 1;  	tx[2] = val;  	tx[3] = val >> 8; -	return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0); +	return spi_write_then_read(mcp->data, tx, sizeof(tx), NULL, 0);  }  static int @@ -214,12 +235,12 @@ mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)  	u8	tx[2];  	int	status; -	if ((n + reg) > sizeof mcp->cache) +	if ((n + reg) > sizeof(mcp->cache))  		return -EINVAL;  	tx[0] = mcp->addr | 0x01;  	tx[1] = reg << 1; -	status = spi_write_then_read(mcp->data, tx, sizeof tx, +	status = spi_write_then_read(mcp->data, tx, sizeof(tx),  				     (u8 *)vals, n * 2);  	if (status >= 0) {  		while (n--) @@ -316,6 +337,195 @@ mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value)  }  /*----------------------------------------------------------------------*/ +static irqreturn_t mcp23s08_irq(int irq, void *data) +{ +	struct mcp23s08 *mcp = data; +	int intcap, intf, i; +	unsigned int child_irq; + +	mutex_lock(&mcp->lock); +	intf = mcp->ops->read(mcp, MCP_INTF); +	if (intf < 0) { +		mutex_unlock(&mcp->lock); +		return IRQ_HANDLED; +	} + +	mcp->cache[MCP_INTF] = intf; + +	intcap = mcp->ops->read(mcp, MCP_INTCAP); +	if (intcap < 0) { +		mutex_unlock(&mcp->lock); +		return IRQ_HANDLED; +	} + +	mcp->cache[MCP_INTCAP] = intcap; +	mutex_unlock(&mcp->lock); + + +	for (i = 0; i < mcp->chip.ngpio; i++) { +		if ((BIT(i) & mcp->cache[MCP_INTF]) && +		    ((BIT(i) & intcap & mcp->irq_rise) || +		     (mcp->irq_fall & ~intcap & BIT(i)))) { +			child_irq = irq_find_mapping(mcp->irq_domain, i); +			handle_nested_irq(child_irq); +		} +	} + +	return IRQ_HANDLED; +} + +static int mcp23s08_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ +	struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip); + +	return irq_find_mapping(mcp->irq_domain, offset); +} + +static void mcp23s08_irq_mask(struct irq_data *data) +{ +	struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); +	unsigned int pos = data->hwirq; + +	mcp->cache[MCP_GPINTEN] &= ~BIT(pos); +} + +static void mcp23s08_irq_unmask(struct irq_data *data) +{ +	struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); +	unsigned int pos = data->hwirq; + +	mcp->cache[MCP_GPINTEN] |= BIT(pos); +} + +static int mcp23s08_irq_set_type(struct irq_data *data, unsigned int type) +{ +	struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); +	unsigned int pos = data->hwirq; +	int status = 0; + +	if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { +		mcp->cache[MCP_INTCON] &= ~BIT(pos); +		mcp->irq_rise |= BIT(pos); +		mcp->irq_fall |= BIT(pos); +	} else if (type & IRQ_TYPE_EDGE_RISING) { +		mcp->cache[MCP_INTCON] &= ~BIT(pos); +		mcp->irq_rise |= BIT(pos); +		mcp->irq_fall &= ~BIT(pos); +	} else if (type & IRQ_TYPE_EDGE_FALLING) { +		mcp->cache[MCP_INTCON] &= ~BIT(pos); +		mcp->irq_rise &= ~BIT(pos); +		mcp->irq_fall |= BIT(pos); +	} else +		return -EINVAL; + +	return status; +} + +static void mcp23s08_irq_bus_lock(struct irq_data *data) +{ +	struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + +	mutex_lock(&mcp->irq_lock); +} + +static void mcp23s08_irq_bus_unlock(struct irq_data *data) +{ +	struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + +	mutex_lock(&mcp->lock); +	mcp->ops->write(mcp, MCP_GPINTEN, mcp->cache[MCP_GPINTEN]); +	mcp->ops->write(mcp, MCP_DEFVAL, mcp->cache[MCP_DEFVAL]); +	mcp->ops->write(mcp, MCP_INTCON, mcp->cache[MCP_INTCON]); +	mutex_unlock(&mcp->lock); +	mutex_unlock(&mcp->irq_lock); +} + +static int mcp23s08_irq_reqres(struct irq_data *data) +{ +	struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + +	if (gpio_lock_as_irq(&mcp->chip, data->hwirq)) { +		dev_err(mcp->chip.dev, +			"unable to lock HW IRQ %lu for IRQ usage\n", +			data->hwirq); +		return -EINVAL; +	} + +	return 0; +} + +static void mcp23s08_irq_relres(struct irq_data *data) +{ +	struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data); + +	gpio_unlock_as_irq(&mcp->chip, data->hwirq); +} + +static struct irq_chip mcp23s08_irq_chip = { +	.name = "gpio-mcp23xxx", +	.irq_mask = mcp23s08_irq_mask, +	.irq_unmask = mcp23s08_irq_unmask, +	.irq_set_type = mcp23s08_irq_set_type, +	.irq_bus_lock = mcp23s08_irq_bus_lock, +	.irq_bus_sync_unlock = mcp23s08_irq_bus_unlock, +	.irq_request_resources = mcp23s08_irq_reqres, +	.irq_release_resources = mcp23s08_irq_relres, +}; + +static int mcp23s08_irq_setup(struct mcp23s08 *mcp) +{ +	struct gpio_chip *chip = &mcp->chip; +	int err, irq, j; + +	mutex_init(&mcp->irq_lock); + +	mcp->irq_domain = irq_domain_add_linear(chip->of_node, chip->ngpio, +						&irq_domain_simple_ops, mcp); +	if (!mcp->irq_domain) +		return -ENODEV; + +	err = devm_request_threaded_irq(chip->dev, mcp->irq, NULL, mcp23s08_irq, +					IRQF_TRIGGER_LOW | IRQF_ONESHOT, +					dev_name(chip->dev), mcp); +	if (err != 0) { +		dev_err(chip->dev, "unable to request IRQ#%d: %d\n", +			mcp->irq, err); +		return err; +	} + +	chip->to_irq = mcp23s08_gpio_to_irq; + +	for (j = 0; j < mcp->chip.ngpio; j++) { +		irq = irq_create_mapping(mcp->irq_domain, j); +		irq_set_lockdep_class(irq, &gpio_lock_class); +		irq_set_chip_data(irq, mcp); +		irq_set_chip(irq, &mcp23s08_irq_chip); +		irq_set_nested_thread(irq, true); +#ifdef CONFIG_ARM +		set_irq_flags(irq, IRQF_VALID); +#else +		irq_set_noprobe(irq); +#endif +	} +	return 0; +} + +static void mcp23s08_irq_teardown(struct mcp23s08 *mcp) +{ +	unsigned int irq, i; + +	free_irq(mcp->irq, mcp); + +	for (i = 0; i < mcp->chip.ngpio; i++) { +		irq = irq_find_mapping(mcp->irq_domain, i); +		if (irq > 0) +			irq_dispose_mapping(irq); +	} + +	irq_domain_remove(mcp->irq_domain); +} + +/*----------------------------------------------------------------------*/  #ifdef CONFIG_DEBUG_FS @@ -357,7 +567,7 @@ static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip)  			(mcp->cache[MCP_GPIO] & mask) ? "hi" : "lo",  			(mcp->cache[MCP_GPPU] & mask) ? "up" : "  ");  		/* NOTE:  ignoring the irq-related registers */ -		seq_printf(s, "\n"); +		seq_puts(s, "\n");  	}  done:  	mutex_unlock(&mcp->lock); @@ -370,10 +580,11 @@ done:  /*----------------------------------------------------------------------*/  static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, -			      void *data, unsigned addr, -			      unsigned type, unsigned base, unsigned pullups) +			      void *data, unsigned addr, unsigned type, +			      unsigned base, unsigned pullups)  {  	int status; +	bool mirror = false;  	mutex_init(&mcp->lock); @@ -425,20 +636,32 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,  	}  	mcp->chip.base = base; -	mcp->chip.can_sleep = 1; +	mcp->chip.can_sleep = true;  	mcp->chip.dev = dev;  	mcp->chip.owner = THIS_MODULE;  	/* verify MCP_IOCON.SEQOP = 0, so sequential reads work,  	 * and MCP_IOCON.HAEN = 1, so we work with all chips.  	 */ +  	status = mcp->ops->read(mcp, MCP_IOCON);  	if (status < 0)  		goto fail; -	if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN)) { + +	mcp->irq_controller = of_property_read_bool(mcp->chip.of_node, +						"interrupt-controller"); +	if (mcp->irq && mcp->irq_controller && (type == MCP_TYPE_017)) +		mirror = of_property_read_bool(mcp->chip.of_node, +						"microchip,irq-mirror"); + +	if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror) {  		/* mcp23s17 has IOCON twice, make sure they are in sync */  		status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8));  		status |= IOCON_HAEN | (IOCON_HAEN << 8); +		status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8)); +		if (mirror) +			status |= IOCON_MIRROR | (IOCON_MIRROR << 8); +  		status = mcp->ops->write(mcp, MCP_IOCON, status);  		if (status < 0)  			goto fail; @@ -470,6 +693,16 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,  	}  	status = gpiochip_add(&mcp->chip); +	if (status < 0) +		goto fail; + +	if (mcp->irq && mcp->irq_controller) { +		status = mcp23s08_irq_setup(mcp); +		if (status) { +			mcp23s08_irq_teardown(mcp); +			goto fail; +		} +	}  fail:  	if (status < 0)  		dev_dbg(dev, "can't setup chip %d, --> %d\n", @@ -481,7 +714,7 @@ fail:  #ifdef CONFIG_OF  #ifdef CONFIG_SPI_MASTER -static struct of_device_id mcp23s08_spi_of_match[] = { +static const struct of_device_id mcp23s08_spi_of_match[] = {  	{  		.compatible = "microchip,mcp23s08",  		.data = (void *) MCP_TYPE_S08, @@ -505,7 +738,7 @@ MODULE_DEVICE_TABLE(of, mcp23s08_spi_of_match);  #endif  #if IS_ENABLED(CONFIG_I2C) -static struct of_device_id mcp23s08_i2c_of_match[] = { +static const struct of_device_id mcp23s08_i2c_of_match[] = {  	{  		.compatible = "microchip,mcp23008",  		.data = (void *) MCP_TYPE_008, @@ -546,6 +779,7 @@ static int mcp230xx_probe(struct i2c_client *client,  	if (match || !pdata) {  		base = -1;  		pullups = 0; +		client->irq = irq_of_parse_and_map(client->dev.of_node, 0);  	} else {  		if (!gpio_is_valid(pdata->base)) {  			dev_dbg(&client->dev, "invalid platform data\n"); @@ -555,10 +789,11 @@ static int mcp230xx_probe(struct i2c_client *client,  		pullups = pdata->chip[0].pullups;  	} -	mcp = kzalloc(sizeof *mcp, GFP_KERNEL); +	mcp = kzalloc(sizeof(*mcp), GFP_KERNEL);  	if (!mcp)  		return -ENOMEM; +	mcp->irq = client->irq;  	status = mcp23s08_probe_one(mcp, &client->dev, client, client->addr,  				    id->driver_data, base, pullups);  	if (status) @@ -579,6 +814,9 @@ static int mcp230xx_remove(struct i2c_client *client)  	struct mcp23s08 *mcp = i2c_get_clientdata(client);  	int status; +	if (client->irq && mcp->irq_controller) +		mcp23s08_irq_teardown(mcp); +  	status = gpiochip_remove(&mcp->chip);  	if (status == 0)  		kfree(mcp); @@ -629,7 +867,7 @@ static int mcp23s08_probe(struct spi_device *spi)  {  	struct mcp23s08_platform_data	*pdata;  	unsigned			addr; -	unsigned			chips = 0; +	int				chips = 0;  	struct mcp23s08_driver_data	*data;  	int				status, type;  	unsigned			base = -1, @@ -640,7 +878,7 @@ static int mcp23s08_probe(struct spi_device *spi)  	match = of_match_device(of_match_ptr(mcp23s08_spi_of_match), &spi->dev);  	if (match) { -		type = (int)match->data; +		type = (int)(uintptr_t)match->data;  		status = of_property_read_u32(spi->dev.of_node,  			    "microchip,spi-present-mask", &spi_present_mask);  		if (status) { @@ -657,8 +895,11 @@ static int mcp23s08_probe(struct spi_device *spi)  			return -ENODEV;  		} -		for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) +		for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {  			pullups[addr] = 0; +			if (spi_present_mask & (1 << addr)) +				chips++; +		}  	} else {  		type = spi_get_device_id(spi)->driver_data;  		pdata = dev_get_platdata(&spi->dev); @@ -681,13 +922,13 @@ static int mcp23s08_probe(struct spi_device *spi)  			pullups[addr] = pdata->chip[addr].pullups;  		} -		if (!chips) -			return -ENODEV; -  		base = pdata->base;  	} -	data = kzalloc(sizeof *data + chips * sizeof(struct mcp23s08), +	if (!chips) +		return -ENODEV; + +	data = kzalloc(sizeof(*data) + chips * sizeof(struct mcp23s08),  			GFP_KERNEL);  	if (!data)  		return -ENOMEM; diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index 6da6d7667c6..d51329d23d3 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -242,7 +242,7 @@ static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port)  	gpio->dbg_show = NULL;  	gpio->base = -1;  	gpio->ngpio = num_port; -	gpio->can_sleep = 0; +	gpio->can_sleep = false;  	gpio->to_irq = ioh_gpio_to_irq;  } @@ -596,7 +596,7 @@ static int ioh_gpio_resume(struct pci_dev *pdev)  #define ioh_gpio_resume NULL  #endif -static DEFINE_PCI_DEVICE_TABLE(ioh_gpio_pcidev_id) = { +static const struct pci_device_id ioh_gpio_pcidev_id[] = {  	{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) },  	{ 0, }  }; diff --git a/drivers/gpio/gpio-moxart.c b/drivers/gpio/gpio-moxart.c new file mode 100644 index 00000000000..4661e181be0 --- /dev/null +++ b/drivers/gpio/gpio-moxart.c @@ -0,0 +1,154 @@ +/* + * MOXA ART SoCs GPIO driver. + * + * Copyright (C) 2013 Jonas Jensen + * + * Jonas Jensen <jonas.jensen@gmail.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2.  This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/err.h> +#include <linux/init.h> +#include <linux/irq.h> +#include <linux/io.h> +#include <linux/gpio.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/of_gpio.h> +#include <linux/pinctrl/consumer.h> +#include <linux/delay.h> +#include <linux/timer.h> +#include <linux/bitops.h> + +#define GPIO_DATA_OUT		0x00 +#define GPIO_DATA_IN		0x04 +#define GPIO_PIN_DIRECTION	0x08 + +struct moxart_gpio_chip { +	struct gpio_chip gpio; +	void __iomem *base; +}; + +static inline struct moxart_gpio_chip *to_moxart_gpio(struct gpio_chip *chip) +{ +	return container_of(chip, struct moxart_gpio_chip, gpio); +} + +static int moxart_gpio_request(struct gpio_chip *chip, unsigned offset) +{ +	return pinctrl_request_gpio(offset); +} + +static void moxart_gpio_free(struct gpio_chip *chip, unsigned offset) +{ +	pinctrl_free_gpio(offset); +} + +static void moxart_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ +	struct moxart_gpio_chip *gc = to_moxart_gpio(chip); +	void __iomem *ioaddr = gc->base + GPIO_DATA_OUT; +	u32 reg = readl(ioaddr); + +	if (value) +		reg = reg | BIT(offset); +	else +		reg = reg & ~BIT(offset); + +	writel(reg, ioaddr); +} + +static int moxart_gpio_get(struct gpio_chip *chip, unsigned offset) +{ +	struct moxart_gpio_chip *gc = to_moxart_gpio(chip); +	u32 ret = readl(gc->base + GPIO_PIN_DIRECTION); + +	if (ret & BIT(offset)) +		return !!(readl(gc->base + GPIO_DATA_OUT) & BIT(offset)); +	else +		return !!(readl(gc->base + GPIO_DATA_IN) & BIT(offset)); +} + +static int moxart_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ +	struct moxart_gpio_chip *gc = to_moxart_gpio(chip); +	void __iomem *ioaddr = gc->base + GPIO_PIN_DIRECTION; + +	writel(readl(ioaddr) & ~BIT(offset), ioaddr); +	return 0; +} + +static int moxart_gpio_direction_output(struct gpio_chip *chip, +					unsigned offset, int value) +{ +	struct moxart_gpio_chip *gc = to_moxart_gpio(chip); +	void __iomem *ioaddr = gc->base + GPIO_PIN_DIRECTION; + +	moxart_gpio_set(chip, offset, value); +	writel(readl(ioaddr) | BIT(offset), ioaddr); +	return 0; +} + +static struct gpio_chip moxart_template_chip = { +	.label			= "moxart-gpio", +	.request		= moxart_gpio_request, +	.free			= moxart_gpio_free, +	.direction_input	= moxart_gpio_direction_input, +	.direction_output	= moxart_gpio_direction_output, +	.set			= moxart_gpio_set, +	.get			= moxart_gpio_get, +	.ngpio			= 32, +	.owner			= THIS_MODULE, +}; + +static int moxart_gpio_probe(struct platform_device *pdev) +{ +	struct device *dev = &pdev->dev; +	struct resource *res; +	struct moxart_gpio_chip *mgc; +	int ret; + +	mgc = devm_kzalloc(dev, sizeof(*mgc), GFP_KERNEL); +	if (!mgc) +		return -ENOMEM; +	mgc->gpio = moxart_template_chip; + +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	mgc->base = devm_ioremap_resource(dev, res); +	if (IS_ERR(mgc->base)) +		return PTR_ERR(mgc->base); + +	mgc->gpio.dev = dev; + +	ret = gpiochip_add(&mgc->gpio); +	if (ret) { +		dev_err(dev, "%s: gpiochip_add failed\n", +			dev->of_node->full_name); +		return ret; +	} + +	return 0; +} + +static const struct of_device_id moxart_gpio_match[] = { +	{ .compatible = "moxa,moxart-gpio" }, +	{ } +}; + +static struct platform_driver moxart_gpio_driver = { +	.driver	= { +		.name		= "moxart-gpio", +		.owner		= THIS_MODULE, +		.of_match_table	= moxart_gpio_match, +	}, +	.probe	= moxart_gpio_probe, +}; +module_platform_driver(moxart_gpio_driver); + +MODULE_DESCRIPTION("MOXART GPIO chip driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jonas Jensen <jonas.jensen@gmail.com>"); diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index a0b33a216d4..d7d6d72eba3 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -14,6 +14,7 @@  #include <linux/io.h>  #include <linux/of.h>  #include <linux/of_gpio.h> +#include <linux/of_irq.h>  #include <linux/gpio.h>  #include <linux/slab.h>  #include <linux/irq.h> @@ -69,10 +70,14 @@ static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio)  	u32 val;  	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);  	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); +	u32 out_mask, out_shadow; -	val = in_be32(mm->regs + GPIO_DAT) & ~in_be32(mm->regs + GPIO_DIR); +	out_mask = in_be32(mm->regs + GPIO_DIR); -	return (val | mpc8xxx_gc->data) & mpc8xxx_gpio2mask(gpio); +	val = in_be32(mm->regs + GPIO_DAT) & ~out_mask; +	out_shadow = mpc8xxx_gc->data & out_mask; + +	return (val | out_shadow) & mpc8xxx_gpio2mask(gpio);  }  static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio) @@ -282,16 +287,16 @@ static struct irq_chip mpc8xxx_irq_chip = {  	.irq_set_type	= mpc8xxx_irq_set_type,  }; -static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int virq, -				irq_hw_number_t hw) +static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int irq, +				irq_hw_number_t hwirq)  {  	struct mpc8xxx_gpio_chip *mpc8xxx_gc = h->host_data;  	if (mpc8xxx_gc->of_dev_id_data)  		mpc8xxx_irq_chip.irq_set_type = mpc8xxx_gc->of_dev_id_data; -	irq_set_chip_data(virq, h->host_data); -	irq_set_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq); +	irq_set_chip_data(irq, h->host_data); +	irq_set_chip_and_handler(irq, &mpc8xxx_irq_chip, handle_level_irq);  	return 0;  } diff --git a/drivers/gpio/gpio-msic.c b/drivers/gpio/gpio-msic.c index d75eaa3a1dc..8f70ded82a2 100644 --- a/drivers/gpio/gpio-msic.c +++ b/drivers/gpio/gpio-msic.c @@ -292,7 +292,7 @@ static int platform_msic_gpio_probe(struct platform_device *pdev)  	mg->chip.to_irq = msic_gpio_to_irq;  	mg->chip.base = pdata->gpio_base;  	mg->chip.ngpio = MSIC_NUM_GPIO; -	mg->chip.can_sleep = 1; +	mg->chip.can_sleep = true;  	mg->chip.dev = dev;  	mutex_init(&mg->buslock); @@ -305,10 +305,9 @@ static int platform_msic_gpio_probe(struct platform_device *pdev)  	for (i = 0; i < mg->chip.ngpio; i++) {  		irq_set_chip_data(i + mg->irq_base, mg); -		irq_set_chip_and_handler_name(i + mg->irq_base, -					      &msic_irqchip, -					      handle_simple_irq, -					      "demux"); +		irq_set_chip_and_handler(i + mg->irq_base, +					 &msic_irqchip, +					 handle_simple_irq);  	}  	irq_set_chained_handler(mg->irq, msic_gpio_irq_handler);  	irq_set_handler_data(mg->irq, mg); diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c index f7a0cc4da95..a3351acd496 100644 --- a/drivers/gpio/gpio-msm-v2.c +++ b/drivers/gpio/gpio-msm-v2.c @@ -102,7 +102,7 @@ struct msm_gpio_dev {  	DECLARE_BITMAP(wake_irqs, MAX_NR_GPIO);  	DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);  	struct irq_domain *domain; -	unsigned int summary_irq; +	int summary_irq;  	void __iomem *msm_tlmm_base;  }; @@ -252,7 +252,7 @@ static void msm_gpio_irq_mask(struct irq_data *d)  	spin_lock_irqsave(&tlmm_lock, irq_flags);  	writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio)); -	clear_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio)); +	clear_gpio_bits(BIT(INTR_RAW_STATUS_EN) | BIT(INTR_ENABLE), GPIO_INTR_CFG(gpio));  	__clear_bit(gpio, msm_gpio.enabled_irqs);  	spin_unlock_irqrestore(&tlmm_lock, irq_flags);  } @@ -264,7 +264,7 @@ static void msm_gpio_irq_unmask(struct irq_data *d)  	spin_lock_irqsave(&tlmm_lock, irq_flags);  	__set_bit(gpio, msm_gpio.enabled_irqs); -	set_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio)); +	set_gpio_bits(BIT(INTR_RAW_STATUS_EN) | BIT(INTR_ENABLE), GPIO_INTR_CFG(gpio));  	writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio));  	spin_unlock_irqrestore(&tlmm_lock, irq_flags);  } @@ -430,10 +430,11 @@ static int msm_gpio_probe(struct platform_device *pdev)  	return 0;  } -static struct of_device_id msm_gpio_of_match[] = { +static const struct of_device_id msm_gpio_of_match[] = {  	{ .compatible = "qcom,msm-gpio", },  	{ },  }; +MODULE_DEVICE_TABLE(of, msm_gpio_of_match);  static int msm_gpio_remove(struct platform_device *dev)  { diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 3c3321f9405..418e3865036 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -44,6 +44,7 @@  #include <linux/of_device.h>  #include <linux/clk.h>  #include <linux/pinctrl/consumer.h> +#include <linux/irqchip/chained_irq.h>  /*   * GPIO unit register offsets. @@ -79,7 +80,7 @@ struct mvebu_gpio_chip {  	spinlock_t	   lock;  	void __iomem	  *membase;  	void __iomem	  *percpu_membase; -	unsigned int       irqbase; +	int		   irqbase;  	struct irq_domain *domain;  	int                soc_variant;  }; @@ -438,12 +439,15 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)  static void mvebu_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  {  	struct mvebu_gpio_chip *mvchip = irq_get_handler_data(irq); +	struct irq_chip *chip = irq_desc_get_chip(desc);  	u32 cause, type;  	int i;  	if (mvchip == NULL)  		return; +	chained_irq_enter(chip, desc); +  	cause = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) &  		readl_relaxed(mvebu_gpioreg_level_mask(mvchip));  	cause |= readl_relaxed(mvebu_gpioreg_edge_cause(mvchip)) & @@ -466,8 +470,11 @@ static void mvebu_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  			polarity ^= 1 << i;  			writel_relaxed(polarity, mvebu_gpioreg_in_pol(mvchip));  		} +  		generic_handle_irq(irq);  	} + +	chained_irq_exit(chip, desc);  }  #ifdef CONFIG_DEBUG_FS @@ -528,7 +535,7 @@ static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)  #define mvebu_gpio_dbg_show NULL  #endif -static struct of_device_id mvebu_gpio_of_match[] = { +static const struct of_device_id mvebu_gpio_of_match[] = {  	{  		.compatible = "marvell,orion-gpio",  		.data       = (void *) MVEBU_GPIO_SOC_VARIANT_ORION, @@ -567,10 +574,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)  		soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION;  	mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), GFP_KERNEL); -	if (!mvchip) { -		dev_err(&pdev->dev, "Cannot allocate memory\n"); +	if (!mvchip)  		return -ENOMEM; -	}  	if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) {  		dev_err(&pdev->dev, "Missing ngpios OF property\n"); @@ -600,7 +605,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)  	mvchip->chip.to_irq = mvebu_gpio_to_irq;  	mvchip->chip.base = id * MVEBU_MAX_GPIO_PER_BANK;  	mvchip->chip.ngpio = ngpios; -	mvchip->chip.can_sleep = 0; +	mvchip->chip.can_sleep = false;  	mvchip->chip.of_node = np;  	mvchip->chip.dbg_show = mvebu_gpio_dbg_show; @@ -676,7 +681,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)  	mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1);  	if (mvchip->irqbase < 0) {  		dev_err(&pdev->dev, "no irqs\n"); -		return -ENOMEM; +		return mvchip->irqbase;  	}  	gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase, @@ -731,9 +736,4 @@ static struct platform_driver mvebu_gpio_driver = {  	},  	.probe		= mvebu_gpio_probe,  }; - -static int __init mvebu_gpio_init(void) -{ -	return platform_driver_register(&mvebu_gpio_driver); -} -postcore_initcall(mvebu_gpio_init); +module_platform_driver(mvebu_gpio_driver); diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 3307f6db3a9..db83b3c0a44 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -422,7 +422,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)  	port->irq_high = platform_get_irq(pdev, 1);  	port->irq = platform_get_irq(pdev, 0);  	if (port->irq < 0) -		return -EINVAL; +		return port->irq;  	/* disable the interrupt and clear the status */  	writel(0, port->base + GPIO_IMR); diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index f8e6af20dfb..8ffdd7d2bad 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -214,7 +214,8 @@ static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)  	ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR;  	ct->regs.mask = PINCTRL_IRQEN(port); -	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0); +	irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK, +			       IRQ_NOREQUEST, 0);  }  static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset) @@ -254,7 +255,6 @@ static int mxs_gpio_probe(struct platform_device *pdev)  	struct device_node *parent;  	static void __iomem *base;  	struct mxs_gpio_port *port; -	struct resource *iores = NULL;  	int irq_base;  	int err; @@ -262,16 +262,10 @@ static int mxs_gpio_probe(struct platform_device *pdev)  	if (!port)  		return -ENOMEM; -	if (np) { -		port->id = of_alias_get_id(np, "gpio"); -		if (port->id < 0) -			return port->id; -		port->devid = (enum mxs_gpio_id) of_id->data; -	} else { -		port->id = pdev->id; -		port->devid = pdev->id_entry->driver_data; -	} - +	port->id = of_alias_get_id(np, "gpio"); +	if (port->id < 0) +		return port->id; +	port->devid = (enum mxs_gpio_id) of_id->data;  	port->irq = platform_get_irq(pdev, 0);  	if (port->irq < 0)  		return port->irq; @@ -281,18 +275,11 @@ static int mxs_gpio_probe(struct platform_device *pdev)  	 * share the same one  	 */  	if (!base) { -		if (np) { -			parent = of_get_parent(np); -			base = of_iomap(parent, 0); -			of_node_put(parent); -			if (!base) -				return -EADDRNOTAVAIL; -		} else { -			iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); -			base = devm_ioremap_resource(&pdev->dev, iores); -			if (IS_ERR(base)) -				return PTR_ERR(base); -		} +		parent = of_get_parent(np); +		base = of_iomap(parent, 0); +		of_node_put(parent); +		if (!base) +			return -EADDRNOTAVAIL;  	}  	port->base = base; diff --git a/drivers/gpio/gpio-octeon.c b/drivers/gpio/gpio-octeon.c index 71a4a318315..dbb08546b9e 100644 --- a/drivers/gpio/gpio-octeon.c +++ b/drivers/gpio/gpio-octeon.c @@ -111,7 +111,7 @@ static int octeon_gpio_probe(struct platform_device *pdev)  	chip->dev = &pdev->dev;  	chip->owner = THIS_MODULE;  	chip->base = 0; -	chip->can_sleep = 0; +	chip->can_sleep = false;  	chip->ngpio = 20;  	chip->direction_input = octeon_gpio_dir_in;  	chip->get = octeon_gpio_get; diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 0ff43552d47..00f29aa1fb9 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -24,9 +24,9 @@  #include <linux/pm.h>  #include <linux/of.h>  #include <linux/of_device.h> -#include <linux/irqdomain.h>  #include <linux/irqchip/chained_irq.h>  #include <linux/gpio.h> +#include <linux/bitops.h>  #include <linux/platform_data/gpio-omap.h>  #define OFF_MODE	1 @@ -52,7 +52,6 @@ struct gpio_bank {  	struct list_head node;  	void __iomem *base;  	u16 irq; -	struct irq_domain *domain;  	u32 non_wakeup_gpios;  	u32 enabled_non_wakeup_gpios;  	struct gpio_regs context; @@ -63,6 +62,7 @@ struct gpio_bank {  	struct gpio_chip chip;  	struct clk *dbck;  	u32 mod_usage; +	u32 irq_usage;  	u32 dbck_enable_mask;  	bool dbck_enabled;  	struct device *dev; @@ -83,19 +83,21 @@ struct gpio_bank {  };  #define GPIO_INDEX(bank, gpio) (gpio % bank->width) -#define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio)) +#define GPIO_BIT(bank, gpio) (BIT(GPIO_INDEX(bank, gpio)))  #define GPIO_MOD_CTRL_BIT	BIT(0) +#define BANK_USED(bank) (bank->mod_usage || bank->irq_usage) +#define LINE_USED(line, offset) (line & (BIT(offset))) +  static int irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq)  {  	return bank->chip.base + gpio_irq;  } -static int omap_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +static inline struct gpio_bank *_irq_data_get_bank(struct irq_data *d)  { -	struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip); - -	return irq_find_mapping(bank->domain, offset); +	struct gpio_chip *chip = irq_data_get_irq_chip_data(d); +	return container_of(chip, struct gpio_bank, chip);  }  static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) @@ -104,12 +106,12 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)  	u32 l;  	reg += bank->regs->direction; -	l = __raw_readl(reg); +	l = readl_relaxed(reg);  	if (is_input) -		l |= 1 << gpio; +		l |= BIT(gpio);  	else -		l &= ~(1 << gpio); -	__raw_writel(l, reg); +		l &= ~(BIT(gpio)); +	writel_relaxed(l, reg);  	bank->context.oe = l;  } @@ -128,7 +130,7 @@ static void _set_gpio_dataout_reg(struct gpio_bank *bank, int gpio, int enable)  		bank->context.dataout &= ~l;  	} -	__raw_writel(l, reg); +	writel_relaxed(l, reg);  }  /* set data out value using mask register */ @@ -138,12 +140,12 @@ static void _set_gpio_dataout_mask(struct gpio_bank *bank, int gpio, int enable)  	u32 gpio_bit = GPIO_BIT(bank, gpio);  	u32 l; -	l = __raw_readl(reg); +	l = readl_relaxed(reg);  	if (enable)  		l |= gpio_bit;  	else  		l &= ~gpio_bit; -	__raw_writel(l, reg); +	writel_relaxed(l, reg);  	bank->context.dataout = l;  } @@ -151,35 +153,35 @@ static int _get_gpio_datain(struct gpio_bank *bank, int offset)  {  	void __iomem *reg = bank->base + bank->regs->datain; -	return (__raw_readl(reg) & (1 << offset)) != 0; +	return (readl_relaxed(reg) & (BIT(offset))) != 0;  }  static int _get_gpio_dataout(struct gpio_bank *bank, int offset)  {  	void __iomem *reg = bank->base + bank->regs->dataout; -	return (__raw_readl(reg) & (1 << offset)) != 0; +	return (readl_relaxed(reg) & (BIT(offset))) != 0;  }  static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)  { -	int l = __raw_readl(base + reg); +	int l = readl_relaxed(base + reg);  	if (set)  		l |= mask;  	else  		l &= ~mask; -	__raw_writel(l, base + reg); +	writel_relaxed(l, base + reg);  }  static inline void _gpio_dbck_enable(struct gpio_bank *bank)  {  	if (bank->dbck_enable_mask && !bank->dbck_enabled) { -		clk_enable(bank->dbck); +		clk_prepare_enable(bank->dbck);  		bank->dbck_enabled = true; -		__raw_writel(bank->dbck_enable_mask, +		writel_relaxed(bank->dbck_enable_mask,  			     bank->base + bank->regs->debounce_en);  	}  } @@ -192,9 +194,9 @@ static inline void _gpio_dbck_disable(struct gpio_bank *bank)  		 * enabled but the clock is not, GPIO module seems to be unable  		 * to detect events and generate interrupts at least on OMAP3.  		 */ -		__raw_writel(0, bank->base + bank->regs->debounce_en); +		writel_relaxed(0, bank->base + bank->regs->debounce_en); -		clk_disable(bank->dbck); +		clk_disable_unprepare(bank->dbck);  		bank->dbck_enabled = false;  	}  } @@ -227,12 +229,12 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,  	l = GPIO_BIT(bank, gpio); -	clk_enable(bank->dbck); +	clk_prepare_enable(bank->dbck);  	reg = bank->base + bank->regs->debounce; -	__raw_writel(debounce, reg); +	writel_relaxed(debounce, reg);  	reg = bank->base + bank->regs->debounce_en; -	val = __raw_readl(reg); +	val = readl_relaxed(reg);  	if (debounce)  		val |= l; @@ -240,8 +242,8 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,  		val &= ~l;  	bank->dbck_enable_mask = val; -	__raw_writel(val, reg); -	clk_disable(bank->dbck); +	writel_relaxed(val, reg); +	clk_disable_unprepare(bank->dbck);  	/*  	 * Enable debounce clock per module.  	 * This call is mandatory because in omap_gpio_request() when @@ -279,14 +281,14 @@ static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio)  	bank->dbck_enable_mask &= ~gpio_bit;  	bank->context.debounce_en &= ~gpio_bit; -	__raw_writel(bank->context.debounce_en, +        writel_relaxed(bank->context.debounce_en,  		     bank->base + bank->regs->debounce_en);  	if (!bank->dbck_enable_mask) {  		bank->context.debounce = 0; -		__raw_writel(bank->context.debounce, bank->base + +		writel_relaxed(bank->context.debounce, bank->base +  			     bank->regs->debounce); -		clk_disable(bank->dbck); +		clk_disable_unprepare(bank->dbck);  		bank->dbck_enabled = false;  	}  } @@ -295,7 +297,7 @@ static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,  						unsigned trigger)  {  	void __iomem *base = bank->base; -	u32 gpio_bit = 1 << gpio; +	u32 gpio_bit = BIT(gpio);  	_gpio_rmw(base, bank->regs->leveldetect0, gpio_bit,  		  trigger & IRQ_TYPE_LEVEL_LOW); @@ -307,18 +309,18 @@ static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,  		  trigger & IRQ_TYPE_EDGE_FALLING);  	bank->context.leveldetect0 = -			__raw_readl(bank->base + bank->regs->leveldetect0); +			readl_relaxed(bank->base + bank->regs->leveldetect0);  	bank->context.leveldetect1 = -			__raw_readl(bank->base + bank->regs->leveldetect1); +			readl_relaxed(bank->base + bank->regs->leveldetect1);  	bank->context.risingdetect = -			__raw_readl(bank->base + bank->regs->risingdetect); +			readl_relaxed(bank->base + bank->regs->risingdetect);  	bank->context.fallingdetect = -			__raw_readl(bank->base + bank->regs->fallingdetect); +			readl_relaxed(bank->base + bank->regs->fallingdetect);  	if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {  		_gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0);  		bank->context.wake_en = -			__raw_readl(bank->base + bank->regs->wkup_en); +			readl_relaxed(bank->base + bank->regs->wkup_en);  	}  	/* This part needs to be executed always for OMAP{34xx, 44xx} */ @@ -343,8 +345,8 @@ static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,  exit:  	bank->level_mask = -		__raw_readl(bank->base + bank->regs->leveldetect0) | -		__raw_readl(bank->base + bank->regs->leveldetect1); +		readl_relaxed(bank->base + bank->regs->leveldetect0) | +		readl_relaxed(bank->base + bank->regs->leveldetect1);  }  #ifdef CONFIG_ARCH_OMAP1 @@ -362,13 +364,13 @@ static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)  	reg += bank->regs->irqctrl; -	l = __raw_readl(reg); +	l = readl_relaxed(reg);  	if ((l >> gpio) & 1) -		l &= ~(1 << gpio); +		l &= ~(BIT(gpio));  	else -		l |= 1 << gpio; +		l |= BIT(gpio); -	__raw_writel(l, reg); +	writel_relaxed(l, reg);  }  #else  static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) {} @@ -386,17 +388,17 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,  	} else if (bank->regs->irqctrl) {  		reg += bank->regs->irqctrl; -		l = __raw_readl(reg); +		l = readl_relaxed(reg);  		if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) -			bank->toggle_mask |= 1 << gpio; +			bank->toggle_mask |= BIT(gpio);  		if (trigger & IRQ_TYPE_EDGE_RISING) -			l |= 1 << gpio; +			l |= BIT(gpio);  		else if (trigger & IRQ_TYPE_EDGE_FALLING) -			l &= ~(1 << gpio); +			l &= ~(BIT(gpio));  		else  			return -EINVAL; -		__raw_writel(l, reg); +		writel_relaxed(l, reg);  	} else if (bank->regs->edgectrl1) {  		if (gpio & 0x08)  			reg += bank->regs->edgectrl2; @@ -404,31 +406,85 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,  			reg += bank->regs->edgectrl1;  		gpio &= 0x07; -		l = __raw_readl(reg); +		l = readl_relaxed(reg);  		l &= ~(3 << (gpio << 1));  		if (trigger & IRQ_TYPE_EDGE_RISING)  			l |= 2 << (gpio << 1);  		if (trigger & IRQ_TYPE_EDGE_FALLING) -			l |= 1 << (gpio << 1); +			l |= BIT(gpio << 1);  		/* Enable wake-up during idle for dynamic tick */ -		_gpio_rmw(base, bank->regs->wkup_en, 1 << gpio, trigger); +		_gpio_rmw(base, bank->regs->wkup_en, BIT(gpio), trigger);  		bank->context.wake_en = -			__raw_readl(bank->base + bank->regs->wkup_en); -		__raw_writel(l, reg); +			readl_relaxed(bank->base + bank->regs->wkup_en); +		writel_relaxed(l, reg);  	}  	return 0;  } +static void _enable_gpio_module(struct gpio_bank *bank, unsigned offset) +{ +	if (bank->regs->pinctrl) { +		void __iomem *reg = bank->base + bank->regs->pinctrl; + +		/* Claim the pin for MPU */ +		writel_relaxed(readl_relaxed(reg) | (BIT(offset)), reg); +	} + +	if (bank->regs->ctrl && !BANK_USED(bank)) { +		void __iomem *reg = bank->base + bank->regs->ctrl; +		u32 ctrl; + +		ctrl = readl_relaxed(reg); +		/* Module is enabled, clocks are not gated */ +		ctrl &= ~GPIO_MOD_CTRL_BIT; +		writel_relaxed(ctrl, reg); +		bank->context.ctrl = ctrl; +	} +} + +static void _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 */ +		_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; + +		ctrl = readl_relaxed(reg); +		/* Module is disabled, clocks are gated */ +		ctrl |= GPIO_MOD_CTRL_BIT; +		writel_relaxed(ctrl, reg); +		bank->context.ctrl = ctrl; +	} +} + +static int gpio_is_input(struct gpio_bank *bank, int mask) +{ +	void __iomem *reg = bank->base + bank->regs->direction; + +	return readl_relaxed(reg) & mask; +} +  static int gpio_irq_type(struct irq_data *d, unsigned type)  { -	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); +	struct gpio_bank *bank = _irq_data_get_bank(d);  	unsigned gpio = 0;  	int retval;  	unsigned long flags; +	unsigned offset; -	if (WARN_ON(!bank->mod_usage)) -		return -EINVAL; +	if (!BANK_USED(bank)) +		pm_runtime_get_sync(bank->dev);  #ifdef CONFIG_ARCH_OMAP1  	if (d->irq > IH_MPUIO_BASE) @@ -446,7 +502,17 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)  		return -EINVAL;  	spin_lock_irqsave(&bank->lock, flags); -	retval = _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), type); +	offset = GPIO_INDEX(bank, gpio); +	retval = _set_gpio_triggering(bank, offset, type); +	if (!LINE_USED(bank->mod_usage, offset)) { +		_enable_gpio_module(bank, offset); +		_set_gpio_direction(bank, offset, 1); +	} else if (!gpio_is_input(bank, BIT(offset))) { +		spin_unlock_irqrestore(&bank->lock, flags); +		return -EINVAL; +	} + +	bank->irq_usage |= BIT(GPIO_INDEX(bank, gpio));  	spin_unlock_irqrestore(&bank->lock, flags);  	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) @@ -462,16 +528,16 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)  	void __iomem *reg = bank->base;  	reg += bank->regs->irqstatus; -	__raw_writel(gpio_mask, reg); +	writel_relaxed(gpio_mask, reg);  	/* Workaround for clearing DSP GPIO interrupts to allow retention */  	if (bank->regs->irqstatus2) {  		reg = bank->base + bank->regs->irqstatus2; -		__raw_writel(gpio_mask, reg); +		writel_relaxed(gpio_mask, reg);  	}  	/* Flush posted write for the irq status to avoid spurious interrupts */ -	__raw_readl(reg); +	readl_relaxed(reg);  }  static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio) @@ -483,10 +549,10 @@ static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)  {  	void __iomem *reg = bank->base;  	u32 l; -	u32 mask = (1 << bank->width) - 1; +	u32 mask = (BIT(bank->width)) - 1;  	reg += bank->regs->irqenable; -	l = __raw_readl(reg); +	l = readl_relaxed(reg);  	if (bank->regs->irqenable_inv)  		l = ~l;  	l &= mask; @@ -504,7 +570,7 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)  		bank->context.irqenable1 |= gpio_mask;  	} else {  		reg += bank->regs->irqenable; -		l = __raw_readl(reg); +		l = readl_relaxed(reg);  		if (bank->regs->irqenable_inv)  			l &= ~gpio_mask;  		else @@ -512,7 +578,7 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)  		bank->context.irqenable1 = l;  	} -	__raw_writel(l, reg); +	writel_relaxed(l, reg);  }  static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) @@ -526,7 +592,7 @@ static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)  		bank->context.irqenable1 &= ~gpio_mask;  	} else {  		reg += bank->regs->irqenable; -		l = __raw_readl(reg); +		l = readl_relaxed(reg);  		if (bank->regs->irqenable_inv)  			l |= gpio_mask;  		else @@ -534,7 +600,7 @@ static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)  		bank->context.irqenable1 = l;  	} -	__raw_writel(l, reg); +	writel_relaxed(l, reg);  }  static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable) @@ -570,7 +636,7 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)  	else  		bank->context.wake_en &= ~gpio_bit; -	__raw_writel(bank->context.wake_en, bank->base + bank->regs->wkup_en); +	writel_relaxed(bank->context.wake_en, bank->base + bank->regs->wkup_en);  	spin_unlock_irqrestore(&bank->lock, flags);  	return 0; @@ -588,7 +654,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)  /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */  static int gpio_wake_enable(struct irq_data *d, unsigned int enable)  { -	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); +	struct gpio_bank *bank = _irq_data_get_bank(d);  	unsigned int gpio = irq_to_gpio(bank, d->hwirq);  	return _set_gpio_wakeup(bank, gpio, enable); @@ -603,35 +669,19 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)  	 * If this is the first gpio_request for the bank,  	 * enable the bank module.  	 */ -	if (!bank->mod_usage) +	if (!BANK_USED(bank))  		pm_runtime_get_sync(bank->dev);  	spin_lock_irqsave(&bank->lock, flags);  	/* Set trigger to none. You need to enable the desired trigger with -	 * request_irq() or set_irq_type(). +	 * request_irq() or set_irq_type(). Only do this if the IRQ line has +	 * not already been requested.  	 */ -	_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE); - -	if (bank->regs->pinctrl) { -		void __iomem *reg = bank->base + bank->regs->pinctrl; - -		/* Claim the pin for MPU */ -		__raw_writel(__raw_readl(reg) | (1 << offset), reg); +	if (!LINE_USED(bank->irq_usage, offset)) { +		_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE); +		_enable_gpio_module(bank, offset);  	} - -	if (bank->regs->ctrl && !bank->mod_usage) { -		void __iomem *reg = bank->base + bank->regs->ctrl; -		u32 ctrl; - -		ctrl = __raw_readl(reg); -		/* Module is enabled, clocks are not gated */ -		ctrl &= ~GPIO_MOD_CTRL_BIT; -		__raw_writel(ctrl, reg); -		bank->context.ctrl = ctrl; -	} - -	bank->mod_usage |= 1 << offset; - +	bank->mod_usage |= BIT(offset);  	spin_unlock_irqrestore(&bank->lock, flags);  	return 0; @@ -640,31 +690,11 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)  static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)  {  	struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip); -	void __iomem *base = bank->base;  	unsigned long flags;  	spin_lock_irqsave(&bank->lock, flags); - -	if (bank->regs->wkup_en) { -		/* Disable wake-up during idle for dynamic tick */ -		_gpio_rmw(base, bank->regs->wkup_en, 1 << offset, 0); -		bank->context.wake_en = -			__raw_readl(bank->base + bank->regs->wkup_en); -	} - -	bank->mod_usage &= ~(1 << offset); - -	if (bank->regs->ctrl && !bank->mod_usage) { -		void __iomem *reg = bank->base + bank->regs->ctrl; -		u32 ctrl; - -		ctrl = __raw_readl(reg); -		/* Module is disabled, clocks are gated */ -		ctrl |= GPIO_MOD_CTRL_BIT; -		__raw_writel(ctrl, reg); -		bank->context.ctrl = ctrl; -	} - +	bank->mod_usage &= ~(BIT(offset)); +	_disable_gpio_module(bank, offset);  	_reset_gpio(bank, bank->chip.base + offset);  	spin_unlock_irqrestore(&bank->lock, flags); @@ -672,7 +702,7 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)  	 * If this is the last gpio to be freed in the bank,  	 * disable the bank module.  	 */ -	if (!bank->mod_usage) +	if (!BANK_USED(bank))  		pm_runtime_put(bank->dev);  } @@ -692,11 +722,12 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  	unsigned int bit;  	struct gpio_bank *bank;  	int unmasked = 0; -	struct irq_chip *chip = irq_desc_get_chip(desc); +	struct irq_chip *irqchip = irq_desc_get_chip(desc); +	struct gpio_chip *chip = irq_get_handler_data(irq); -	chained_irq_enter(chip, desc); +	chained_irq_enter(irqchip, desc); -	bank = irq_get_handler_data(irq); +	bank = container_of(chip, struct gpio_bank, chip);  	isr_reg = bank->base + bank->regs->irqstatus;  	pm_runtime_get_sync(bank->dev); @@ -708,7 +739,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  		u32 enabled;  		enabled = _get_gpio_irqbank_mask(bank); -		isr_saved = isr = __raw_readl(isr_reg) & enabled; +		isr_saved = isr = readl_relaxed(isr_reg) & enabled;  		if (bank->level_mask)  			level_mask = bank->level_mask & enabled; @@ -724,7 +755,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  		configured, we could unmask GPIO bank interrupt immediately */  		if (!level_mask && !unmasked) {  			unmasked = 1; -			chained_irq_exit(chip, desc); +			chained_irq_exit(irqchip, desc);  		}  		if (!isr) @@ -732,7 +763,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  		while (isr) {  			bit = __ffs(isr); -			isr &= ~(1 << bit); +			isr &= ~(BIT(bit));  			/*  			 * Some chips can't respond to both rising and falling @@ -741,10 +772,11 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  			 * to respond to the IRQ for the opposite direction.  			 * This will be indicated in the bank toggle_mask.  			 */ -			if (bank->toggle_mask & (1 << bit)) +			if (bank->toggle_mask & (BIT(bit)))  				_toggle_gpio_edge_triggering(bank, bit); -			generic_handle_irq(irq_find_mapping(bank->domain, bit)); +			generic_handle_irq(irq_find_mapping(bank->chip.irqdomain, +							    bit));  		}  	}  	/* if bank has any level sensitive GPIO pin interrupt @@ -753,24 +785,35 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  	interrupt */  exit:  	if (!unmasked) -		chained_irq_exit(chip, desc); +		chained_irq_exit(irqchip, desc);  	pm_runtime_put(bank->dev);  }  static void gpio_irq_shutdown(struct irq_data *d)  { -	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); +	struct gpio_bank *bank = _irq_data_get_bank(d);  	unsigned int gpio = irq_to_gpio(bank, d->hwirq);  	unsigned long flags; +	unsigned offset = GPIO_INDEX(bank, gpio);  	spin_lock_irqsave(&bank->lock, flags); +	gpio_unlock_as_irq(&bank->chip, offset); +	bank->irq_usage &= ~(BIT(offset)); +	_disable_gpio_module(bank, offset);  	_reset_gpio(bank, gpio);  	spin_unlock_irqrestore(&bank->lock, flags); + +	/* +	 * If this is the last IRQ to be freed in the bank, +	 * disable the bank module. +	 */ +	if (!BANK_USED(bank)) +		pm_runtime_put(bank->dev);  }  static void gpio_ack_irq(struct irq_data *d)  { -	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); +	struct gpio_bank *bank = _irq_data_get_bank(d);  	unsigned int gpio = irq_to_gpio(bank, d->hwirq);  	_clear_gpio_irqstatus(bank, gpio); @@ -778,7 +821,7 @@ static void gpio_ack_irq(struct irq_data *d)  static void gpio_mask_irq(struct irq_data *d)  { -	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); +	struct gpio_bank *bank = _irq_data_get_bank(d);  	unsigned int gpio = irq_to_gpio(bank, d->hwirq);  	unsigned long flags; @@ -790,7 +833,7 @@ static void gpio_mask_irq(struct irq_data *d)  static void gpio_unmask_irq(struct irq_data *d)  { -	struct gpio_bank *bank = irq_data_get_irq_chip_data(d); +	struct gpio_bank *bank = _irq_data_get_bank(d);  	unsigned int gpio = irq_to_gpio(bank, d->hwirq);  	unsigned int irq_mask = GPIO_BIT(bank, gpio);  	u32 trigger = irqd_get_trigger_type(d); @@ -832,7 +875,7 @@ static int omap_mpuio_suspend_noirq(struct device *dev)  	unsigned long		flags;  	spin_lock_irqsave(&bank->lock, flags); -	__raw_writel(0xffff & ~bank->context.wake_en, mask_reg); +	writel_relaxed(0xffff & ~bank->context.wake_en, mask_reg);  	spin_unlock_irqrestore(&bank->lock, flags);  	return 0; @@ -847,7 +890,7 @@ static int omap_mpuio_resume_noirq(struct device *dev)  	unsigned long		flags;  	spin_lock_irqsave(&bank->lock, flags); -	__raw_writel(bank->context.wake_en, mask_reg); +	writel_relaxed(bank->context.wake_en, mask_reg);  	spin_unlock_irqrestore(&bank->lock, flags);  	return 0; @@ -885,23 +928,31 @@ static inline void mpuio_init(struct gpio_bank *bank)  /*---------------------------------------------------------------------*/ -static int gpio_input(struct gpio_chip *chip, unsigned offset) +static int gpio_get_direction(struct gpio_chip *chip, unsigned offset)  {  	struct gpio_bank *bank;  	unsigned long flags; +	void __iomem *reg; +	int dir;  	bank = container_of(chip, struct gpio_bank, chip); +	reg = bank->base + bank->regs->direction;  	spin_lock_irqsave(&bank->lock, flags); -	_set_gpio_direction(bank, offset, 1); +	dir = !!(readl_relaxed(reg) & BIT(offset));  	spin_unlock_irqrestore(&bank->lock, flags); -	return 0; +	return dir;  } -static int gpio_is_input(struct gpio_bank *bank, int mask) +static int gpio_input(struct gpio_chip *chip, unsigned offset)  { -	void __iomem *reg = bank->base + bank->regs->direction; +	struct gpio_bank *bank; +	unsigned long flags; -	return __raw_readl(reg) & mask; +	bank = container_of(chip, struct gpio_bank, chip); +	spin_lock_irqsave(&bank->lock, flags); +	_set_gpio_direction(bank, offset, 1); +	spin_unlock_irqrestore(&bank->lock, flags); +	return 0;  }  static int gpio_get(struct gpio_chip *chip, unsigned offset) @@ -910,7 +961,7 @@ static int gpio_get(struct gpio_chip *chip, unsigned offset)  	u32 mask;  	bank = container_of(chip, struct gpio_bank, chip); -	mask = (1 << offset); +	mask = (BIT(offset));  	if (gpio_is_input(bank, mask))  		return _get_gpio_datain(bank, offset); @@ -967,7 +1018,7 @@ static void __init omap_gpio_show_rev(struct gpio_bank *bank)  	if (called || bank->regs->revision == USHRT_MAX)  		return; -	rev = __raw_readw(bank->base + bank->regs->revision); +	rev = readw_relaxed(bank->base + bank->regs->revision);  	pr_info("OMAP GPIO hardware version %d.%d\n",  		(rev >> 4) & 0x0f, rev & 0x0f); @@ -988,20 +1039,20 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)  		l = 0xffff;  	if (bank->is_mpuio) { -		__raw_writel(l, bank->base + bank->regs->irqenable); +		writel_relaxed(l, bank->base + bank->regs->irqenable);  		return;  	}  	_gpio_rmw(base, bank->regs->irqenable, l, bank->regs->irqenable_inv);  	_gpio_rmw(base, bank->regs->irqstatus, l, !bank->regs->irqenable_inv);  	if (bank->regs->debounce_en) -		__raw_writel(0, base + bank->regs->debounce_en); +		writel_relaxed(0, base + bank->regs->debounce_en);  	/* Save OE default value (0xffffffff) in the context */ -	bank->context.oe = __raw_readl(bank->base + bank->regs->direction); +	bank->context.oe = readl_relaxed(bank->base + bank->regs->direction);  	 /* Initialize interface clk ungated, module enabled */  	if (bank->regs->ctrl) -		__raw_writel(0, base + bank->regs->ctrl); +		writel_relaxed(0, base + bank->regs->ctrl);  	bank->dbck = clk_get(bank->dev, "dbclk");  	if (IS_ERR(bank->dbck)) @@ -1037,10 +1088,12 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,  			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);  } -static void omap_gpio_chip_init(struct gpio_bank *bank) +static int omap_gpio_chip_init(struct gpio_bank *bank)  {  	int j;  	static int gpio; +	int irq_base = 0; +	int ret;  	/*  	 * REVISIT eventually switch from OMAP-specific gpio structs @@ -1048,12 +1101,12 @@ static void omap_gpio_chip_init(struct gpio_bank *bank)  	 */  	bank->chip.request = omap_gpio_request;  	bank->chip.free = omap_gpio_free; +	bank->chip.get_direction = gpio_get_direction;  	bank->chip.direction_input = gpio_input;  	bank->chip.get = gpio_get;  	bank->chip.direction_output = gpio_output;  	bank->chip.set_debounce = gpio_debounce;  	bank->chip.set = gpio_set; -	bank->chip.to_irq = omap_gpio_to_irq;  	if (bank->is_mpuio) {  		bank->chip.label = "mpuio";  		if (bank->regs->wkup_en) @@ -1066,22 +1119,48 @@ static void omap_gpio_chip_init(struct gpio_bank *bank)  	}  	bank->chip.ngpio = bank->width; -	gpiochip_add(&bank->chip); +	ret = gpiochip_add(&bank->chip); +	if (ret) { +		dev_err(bank->dev, "Could not register gpio chip %d\n", ret); +		return ret; +	} + +#ifdef CONFIG_ARCH_OMAP1 +	/* +	 * REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop +	 * irq_alloc_descs() since a base IRQ offset will no longer be needed. +	 */ +	irq_base = irq_alloc_descs(-1, 0, bank->width, 0); +	if (irq_base < 0) { +		dev_err(bank->dev, "Couldn't allocate IRQ numbers\n"); +		return -ENODEV; +	} +#endif + +	ret = gpiochip_irqchip_add(&bank->chip, &gpio_irq_chip, +				   irq_base, gpio_irq_handler, +				   IRQ_TYPE_NONE); + +	if (ret) { +		dev_err(bank->dev, "Couldn't add irqchip to gpiochip %d\n", ret); +		ret = gpiochip_remove(&bank->chip); +		return -ENODEV; +	} + +	gpiochip_set_chained_irqchip(&bank->chip, &gpio_irq_chip, +				     bank->irq, gpio_irq_handler);  	for (j = 0; j < bank->width; j++) { -		int irq = irq_create_mapping(bank->domain, j); +		int irq = irq_find_mapping(bank->chip.irqdomain, j);  		irq_set_lockdep_class(irq, &gpio_lock_class); -		irq_set_chip_data(irq, bank);  		if (bank->is_mpuio) {  			omap_mpuio_alloc_gc(bank, irq, bank->width); -		} else { -			irq_set_chip_and_handler(irq, &gpio_irq_chip, -						 handle_simple_irq); -			set_irq_flags(irq, IRQF_VALID); +			irq_set_chip_and_handler(irq, NULL, NULL); +			set_irq_flags(irq, 0);  		}  	} -	irq_set_chained_handler(bank->irq, gpio_irq_handler); -	irq_set_handler_data(bank->irq, bank); + +	return 0;  }  static const struct of_device_id omap_gpio_match[]; @@ -1094,9 +1173,7 @@ static int omap_gpio_probe(struct platform_device *pdev)  	const struct omap_gpio_platform_data *pdata;  	struct resource *res;  	struct gpio_bank *bank; -#ifdef CONFIG_ARCH_OMAP1 -	int irq_base; -#endif +	int ret;  	match = of_match_device(of_match_ptr(omap_gpio_match), dev); @@ -1118,6 +1195,7 @@ static int omap_gpio_probe(struct platform_device *pdev)  	bank->irq = res->start;  	bank->dev = dev; +	bank->chip.dev = dev;  	bank->dbck_flag = pdata->dbck_flag;  	bank->stride = pdata->bank_stride;  	bank->width = pdata->bank_width; @@ -1138,29 +1216,6 @@ static int omap_gpio_probe(struct platform_device *pdev)  				pdata->get_context_loss_count;  	} -#ifdef CONFIG_ARCH_OMAP1 -	/* -	 * REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop -	 * irq_alloc_descs() and irq_domain_add_legacy() and just use a -	 * linear IRQ domain mapping for all OMAP platforms. -	 */ -	irq_base = irq_alloc_descs(-1, 0, bank->width, 0); -	if (irq_base < 0) { -		dev_err(dev, "Couldn't allocate IRQ numbers\n"); -		return -ENODEV; -	} - -	bank->domain = irq_domain_add_legacy(node, bank->width, irq_base, -					     0, &irq_domain_simple_ops, NULL); -#else -	bank->domain = irq_domain_add_linear(node, bank->width, -					     &irq_domain_simple_ops, NULL); -#endif -	if (!bank->domain) { -		dev_err(dev, "Couldn't register an IRQ domain\n"); -		return -ENODEV; -	} -  	if (bank->regs->set_dataout && bank->regs->clr_dataout)  		bank->set_dataout = _set_gpio_dataout_reg;  	else @@ -1170,24 +1225,10 @@ static int omap_gpio_probe(struct platform_device *pdev)  	/* Static mapping, never released */  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (unlikely(!res)) { -		dev_err(dev, "Invalid mem resource\n"); -		irq_domain_remove(bank->domain); -		return -ENODEV; -	} - -	if (!devm_request_mem_region(dev, res->start, resource_size(res), -				     pdev->name)) { -		dev_err(dev, "Region already claimed\n"); -		irq_domain_remove(bank->domain); -		return -EBUSY; -	} - -	bank->base = devm_ioremap(dev, res->start, resource_size(res)); -	if (!bank->base) { -		dev_err(dev, "Could not ioremap\n"); -		irq_domain_remove(bank->domain); -		return -ENOMEM; +	bank->base = devm_ioremap_resource(dev, res); +	if (IS_ERR(bank->base)) { +		irq_domain_remove(bank->chip.irqdomain); +		return PTR_ERR(bank->base);  	}  	platform_set_drvdata(pdev, bank); @@ -1200,7 +1241,11 @@ static int omap_gpio_probe(struct platform_device *pdev)  		mpuio_init(bank);  	omap_gpio_mod_init(bank); -	omap_gpio_chip_init(bank); + +	ret = omap_gpio_chip_init(bank); +	if (ret) +		return ret; +  	omap_gpio_show_rev(bank);  	pm_runtime_put(bank->dev); @@ -1238,11 +1283,11 @@ static int omap_gpio_runtime_suspend(struct device *dev)  	 */  	wake_low = bank->context.leveldetect0 & bank->context.wake_en;  	if (wake_low) -		__raw_writel(wake_low | bank->context.fallingdetect, +		writel_relaxed(wake_low | bank->context.fallingdetect,  			     bank->base + bank->regs->fallingdetect);  	wake_hi = bank->context.leveldetect1 & bank->context.wake_en;  	if (wake_hi) -		__raw_writel(wake_hi | bank->context.risingdetect, +		writel_relaxed(wake_hi | bank->context.risingdetect,  			     bank->base + bank->regs->risingdetect);  	if (!bank->enabled_non_wakeup_gpios) @@ -1257,7 +1302,7 @@ static int omap_gpio_runtime_suspend(struct device *dev)  	 * non-wakeup GPIOs.  Otherwise spurious IRQs will be  	 * generated.  See OMAP2420 Errata item 1.101.  	 */ -	bank->saved_datain = __raw_readl(bank->base + +	bank->saved_datain = readl_relaxed(bank->base +  						bank->regs->datain);  	l1 = bank->context.fallingdetect;  	l2 = bank->context.risingdetect; @@ -1265,8 +1310,8 @@ static int omap_gpio_runtime_suspend(struct device *dev)  	l1 &= ~bank->enabled_non_wakeup_gpios;  	l2 &= ~bank->enabled_non_wakeup_gpios; -	__raw_writel(l1, bank->base + bank->regs->fallingdetect); -	__raw_writel(l2, bank->base + bank->regs->risingdetect); +	writel_relaxed(l1, bank->base + bank->regs->fallingdetect); +	writel_relaxed(l2, bank->base + bank->regs->risingdetect);  	bank->workaround_enabled = true; @@ -1314,9 +1359,9 @@ static int omap_gpio_runtime_resume(struct device *dev)  	 * generate a PRCM wakeup.  Here we restore the  	 * pre-runtime_suspend() values for edge triggering.  	 */ -	__raw_writel(bank->context.fallingdetect, +	writel_relaxed(bank->context.fallingdetect,  		     bank->base + bank->regs->fallingdetect); -	__raw_writel(bank->context.risingdetect, +	writel_relaxed(bank->context.risingdetect,  		     bank->base + bank->regs->risingdetect);  	if (bank->loses_context) { @@ -1338,7 +1383,7 @@ static int omap_gpio_runtime_resume(struct device *dev)  		return 0;  	} -	l = __raw_readl(bank->base + bank->regs->datain); +	l = readl_relaxed(bank->base + bank->regs->datain);  	/*  	 * Check if any of the non-wakeup interrupt GPIOs have changed @@ -1368,24 +1413,24 @@ static int omap_gpio_runtime_resume(struct device *dev)  	if (gen) {  		u32 old0, old1; -		old0 = __raw_readl(bank->base + bank->regs->leveldetect0); -		old1 = __raw_readl(bank->base + bank->regs->leveldetect1); +		old0 = readl_relaxed(bank->base + bank->regs->leveldetect0); +		old1 = readl_relaxed(bank->base + bank->regs->leveldetect1);  		if (!bank->regs->irqstatus_raw0) { -			__raw_writel(old0 | gen, bank->base + +			writel_relaxed(old0 | gen, bank->base +  						bank->regs->leveldetect0); -			__raw_writel(old1 | gen, bank->base + +			writel_relaxed(old1 | gen, bank->base +  						bank->regs->leveldetect1);  		}  		if (bank->regs->irqstatus_raw0) { -			__raw_writel(old0 | l, bank->base + +			writel_relaxed(old0 | l, bank->base +  						bank->regs->leveldetect0); -			__raw_writel(old1 | l, bank->base + +			writel_relaxed(old1 | l, bank->base +  						bank->regs->leveldetect1);  		} -		__raw_writel(old0, bank->base + bank->regs->leveldetect0); -		__raw_writel(old1, bank->base + bank->regs->leveldetect1); +		writel_relaxed(old0, bank->base + bank->regs->leveldetect0); +		writel_relaxed(old1, bank->base + bank->regs->leveldetect1);  	}  	bank->workaround_enabled = false; @@ -1400,7 +1445,7 @@ void omap2_gpio_prepare_for_idle(int pwr_mode)  	struct gpio_bank *bank;  	list_for_each_entry(bank, &omap_gpio_list, node) { -		if (!bank->mod_usage || !bank->loses_context) +		if (!BANK_USED(bank) || !bank->loses_context)  			continue;  		bank->power_mode = pwr_mode; @@ -1414,7 +1459,7 @@ void omap2_gpio_resume_after_idle(void)  	struct gpio_bank *bank;  	list_for_each_entry(bank, &omap_gpio_list, node) { -		if (!bank->mod_usage || !bank->loses_context) +		if (!BANK_USED(bank) || !bank->loses_context)  			continue;  		pm_runtime_get_sync(bank->dev); @@ -1427,55 +1472,55 @@ static void omap_gpio_init_context(struct gpio_bank *p)  	struct omap_gpio_reg_offs *regs = p->regs;  	void __iomem *base = p->base; -	p->context.ctrl		= __raw_readl(base + regs->ctrl); -	p->context.oe		= __raw_readl(base + regs->direction); -	p->context.wake_en	= __raw_readl(base + regs->wkup_en); -	p->context.leveldetect0	= __raw_readl(base + regs->leveldetect0); -	p->context.leveldetect1	= __raw_readl(base + regs->leveldetect1); -	p->context.risingdetect	= __raw_readl(base + regs->risingdetect); -	p->context.fallingdetect = __raw_readl(base + regs->fallingdetect); -	p->context.irqenable1	= __raw_readl(base + regs->irqenable); -	p->context.irqenable2	= __raw_readl(base + regs->irqenable2); +	p->context.ctrl		= readl_relaxed(base + regs->ctrl); +	p->context.oe		= readl_relaxed(base + regs->direction); +	p->context.wake_en	= readl_relaxed(base + regs->wkup_en); +	p->context.leveldetect0	= readl_relaxed(base + regs->leveldetect0); +	p->context.leveldetect1	= readl_relaxed(base + regs->leveldetect1); +	p->context.risingdetect	= readl_relaxed(base + regs->risingdetect); +	p->context.fallingdetect = readl_relaxed(base + regs->fallingdetect); +	p->context.irqenable1	= readl_relaxed(base + regs->irqenable); +	p->context.irqenable2	= readl_relaxed(base + regs->irqenable2);  	if (regs->set_dataout && p->regs->clr_dataout) -		p->context.dataout = __raw_readl(base + regs->set_dataout); +		p->context.dataout = readl_relaxed(base + regs->set_dataout);  	else -		p->context.dataout = __raw_readl(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)  { -	__raw_writel(bank->context.wake_en, +	writel_relaxed(bank->context.wake_en,  				bank->base + bank->regs->wkup_en); -	__raw_writel(bank->context.ctrl, bank->base + bank->regs->ctrl); -	__raw_writel(bank->context.leveldetect0, +	writel_relaxed(bank->context.ctrl, bank->base + bank->regs->ctrl); +	writel_relaxed(bank->context.leveldetect0,  				bank->base + bank->regs->leveldetect0); -	__raw_writel(bank->context.leveldetect1, +	writel_relaxed(bank->context.leveldetect1,  				bank->base + bank->regs->leveldetect1); -	__raw_writel(bank->context.risingdetect, +	writel_relaxed(bank->context.risingdetect,  				bank->base + bank->regs->risingdetect); -	__raw_writel(bank->context.fallingdetect, +	writel_relaxed(bank->context.fallingdetect,  				bank->base + bank->regs->fallingdetect);  	if (bank->regs->set_dataout && bank->regs->clr_dataout) -		__raw_writel(bank->context.dataout, +		writel_relaxed(bank->context.dataout,  				bank->base + bank->regs->set_dataout);  	else -		__raw_writel(bank->context.dataout, +		writel_relaxed(bank->context.dataout,  				bank->base + bank->regs->dataout); -	__raw_writel(bank->context.oe, bank->base + bank->regs->direction); +	writel_relaxed(bank->context.oe, bank->base + bank->regs->direction);  	if (bank->dbck_enable_mask) { -		__raw_writel(bank->context.debounce, bank->base + +		writel_relaxed(bank->context.debounce, bank->base +  					bank->regs->debounce); -		__raw_writel(bank->context.debounce_en, +		writel_relaxed(bank->context.debounce_en,  					bank->base + bank->regs->debounce_en);  	} -	__raw_writel(bank->context.irqenable1, +	writel_relaxed(bank->context.irqenable1,  				bank->base + bank->regs->irqenable); -	__raw_writel(bank->context.irqenable2, +	writel_relaxed(bank->context.irqenable2,  				bank->base + bank->regs->irqenable2);  }  #endif /* CONFIG_PM_RUNTIME */ diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c index 8588af0f766..86bdbe36206 100644 --- a/drivers/gpio/gpio-palmas.c +++ b/drivers/gpio/gpio-palmas.c @@ -31,6 +31,10 @@ struct palmas_gpio {  	struct palmas *palmas;  }; +struct palmas_device_data { +	int ngpio; +}; +  static inline struct palmas_gpio *to_palmas_gpio(struct gpio_chip *chip)  {  	return container_of(chip, struct palmas_gpio, gpio_chip); @@ -42,23 +46,26 @@ static int palmas_gpio_get(struct gpio_chip *gc, unsigned offset)  	struct palmas *palmas = pg->palmas;  	unsigned int val;  	int ret; +	unsigned int reg; +	int gpio16 = (offset/8); + +	offset %= 8; +	reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR; -	ret = palmas_read(palmas, PALMAS_GPIO_BASE, PALMAS_GPIO_DATA_DIR, &val); +	ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);  	if (ret < 0) { -		dev_err(gc->dev, "GPIO_DATA_DIR read failed, err = %d\n", ret); +		dev_err(gc->dev, "Reg 0x%02x read failed, %d\n", reg, ret);  		return ret;  	} -	if (val & (1 << offset)) { -		ret = palmas_read(palmas, PALMAS_GPIO_BASE, -				  PALMAS_GPIO_DATA_OUT, &val); -	} else { -		ret = palmas_read(palmas, PALMAS_GPIO_BASE, -				  PALMAS_GPIO_DATA_IN, &val); -	} +	if (val & BIT(offset)) +		reg = (gpio16) ? PALMAS_GPIO_DATA_OUT2 : PALMAS_GPIO_DATA_OUT; +	else +		reg = (gpio16) ? PALMAS_GPIO_DATA_IN2 : PALMAS_GPIO_DATA_IN; + +	ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);  	if (ret < 0) { -		dev_err(gc->dev, "GPIO_DATA_IN/OUT read failed, err = %d\n", -			ret); +		dev_err(gc->dev, "Reg 0x%02x read failed, %d\n", reg, ret);  		return ret;  	}  	return !!(val & BIT(offset)); @@ -70,17 +77,20 @@ static void palmas_gpio_set(struct gpio_chip *gc, unsigned offset,  	struct palmas_gpio *pg = to_palmas_gpio(gc);  	struct palmas *palmas = pg->palmas;  	int ret; +	unsigned int reg; +	int gpio16 = (offset/8); -	if (value) -		ret = palmas_write(palmas, PALMAS_GPIO_BASE, -				PALMAS_GPIO_SET_DATA_OUT, BIT(offset)); +	offset %= 8; +	if (gpio16) +		reg = (value) ? +			PALMAS_GPIO_SET_DATA_OUT2 : PALMAS_GPIO_CLEAR_DATA_OUT2;  	else -		ret = palmas_write(palmas, PALMAS_GPIO_BASE, -				PALMAS_GPIO_CLEAR_DATA_OUT, BIT(offset)); +		reg = (value) ? +			PALMAS_GPIO_SET_DATA_OUT : PALMAS_GPIO_CLEAR_DATA_OUT; + +	ret = palmas_write(palmas, PALMAS_GPIO_BASE, reg, BIT(offset));  	if (ret < 0) -		dev_err(gc->dev, "%s write failed, err = %d\n", -			(value) ? "GPIO_SET_DATA_OUT" : "GPIO_CLEAR_DATA_OUT", -			ret); +		dev_err(gc->dev, "Reg 0x%02x write failed, %d\n", reg, ret);  }  static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset, @@ -89,14 +99,19 @@ static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset,  	struct palmas_gpio *pg = to_palmas_gpio(gc);  	struct palmas *palmas = pg->palmas;  	int ret; +	unsigned int reg; +	int gpio16 = (offset/8); + +	offset %= 8; +	reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;  	/* Set the initial value */  	palmas_gpio_set(gc, offset, value); -	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, -		PALMAS_GPIO_DATA_DIR, BIT(offset), BIT(offset)); +	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, +				BIT(offset), BIT(offset));  	if (ret < 0) -		dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret); +		dev_err(gc->dev, "Reg 0x%02x update failed, %d\n", reg, ret);  	return ret;  } @@ -105,11 +120,15 @@ static int palmas_gpio_input(struct gpio_chip *gc, unsigned offset)  	struct palmas_gpio *pg = to_palmas_gpio(gc);  	struct palmas *palmas = pg->palmas;  	int ret; +	unsigned int reg; +	int gpio16 = (offset/8); + +	offset %= 8; +	reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR; -	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, -		PALMAS_GPIO_DATA_DIR, BIT(offset), 0); +	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, BIT(offset), 0);  	if (ret < 0) -		dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret); +		dev_err(gc->dev, "Reg 0x%02x update failed, %d\n", reg, ret);  	return ret;  } @@ -121,25 +140,47 @@ static int palmas_gpio_to_irq(struct gpio_chip *gc, unsigned offset)  	return palmas_irq_get_virq(palmas, PALMAS_GPIO_0_IRQ + offset);  } +static const struct palmas_device_data palmas_dev_data = { +	.ngpio = 8, +}; + +static const struct palmas_device_data tps80036_dev_data = { +	.ngpio = 16, +}; + +static const struct of_device_id of_palmas_gpio_match[] = { +	{ .compatible = "ti,palmas-gpio", .data = &palmas_dev_data,}, +	{ .compatible = "ti,tps65913-gpio", .data = &palmas_dev_data,}, +	{ .compatible = "ti,tps65914-gpio", .data = &palmas_dev_data,}, +	{ .compatible = "ti,tps80036-gpio", .data = &tps80036_dev_data,}, +	{ }, +}; +MODULE_DEVICE_TABLE(of, of_palmas_gpio_match); +  static int palmas_gpio_probe(struct platform_device *pdev)  {  	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);  	struct palmas_platform_data *palmas_pdata;  	struct palmas_gpio *palmas_gpio;  	int ret; +	const struct of_device_id *match; +	const struct palmas_device_data *dev_data; + +	match = of_match_device(of_palmas_gpio_match, &pdev->dev); +	dev_data = match->data; +	if (!dev_data) +		dev_data = &palmas_dev_data;  	palmas_gpio = devm_kzalloc(&pdev->dev,  				sizeof(*palmas_gpio), GFP_KERNEL); -	if (!palmas_gpio) { -		dev_err(&pdev->dev, "Could not allocate palmas_gpio\n"); +	if (!palmas_gpio)  		return -ENOMEM; -	}  	palmas_gpio->palmas = palmas;  	palmas_gpio->gpio_chip.owner = THIS_MODULE;  	palmas_gpio->gpio_chip.label = dev_name(&pdev->dev); -	palmas_gpio->gpio_chip.ngpio = 8; -	palmas_gpio->gpio_chip.can_sleep = 1; +	palmas_gpio->gpio_chip.ngpio = dev_data->ngpio; +	palmas_gpio->gpio_chip.can_sleep = true;  	palmas_gpio->gpio_chip.direction_input = palmas_gpio_input;  	palmas_gpio->gpio_chip.direction_output = palmas_gpio_output;  	palmas_gpio->gpio_chip.to_irq = palmas_gpio_to_irq; @@ -172,15 +213,6 @@ static int palmas_gpio_remove(struct platform_device *pdev)  	return gpiochip_remove(&palmas_gpio->gpio_chip);  } -static struct of_device_id of_palmas_gpio_match[] = { -	{ .compatible = "ti,palmas-gpio"}, -	{ .compatible = "ti,tps65913-gpio"}, -	{ .compatible = "ti,tps65914-gpio"}, -	{ .compatible = "ti,tps80036-gpio"}, -	{ }, -}; -MODULE_DEVICE_TABLE(of, of_palmas_gpio_match); -  static struct platform_driver palmas_gpio_driver = {  	.driver.name	= "palmas-gpio",  	.driver.owner	= THIS_MODULE, diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index cdd1aa12b89..e721a37c347 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -1,5 +1,5 @@  /* - *  PCA953x 4/8/16 bit I/O ports + *  PCA953x 4/8/16/24/40 bit I/O ports   *   *  Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>   *  Copyright (C) 2007 Marvell International Ltd. @@ -15,8 +15,6 @@  #include <linux/init.h>  #include <linux/gpio.h>  #include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/irqdomain.h>  #include <linux/i2c.h>  #include <linux/platform_data/pca953x.h>  #include <linux/slab.h> @@ -59,6 +57,7 @@ static const struct i2c_device_id pca953x_id[] = {  	{ "pca9557", 8  | PCA953X_TYPE, },  	{ "pca9574", 8  | PCA957X_TYPE | PCA_INT, },  	{ "pca9575", 16 | PCA957X_TYPE | PCA_INT, }, +	{ "pca9698", 40 | PCA953X_TYPE, },  	{ "max7310", 8  | PCA953X_TYPE, },  	{ "max7312", 16 | PCA953X_TYPE | PCA_INT, }, @@ -68,6 +67,7 @@ static const struct i2c_device_id pca953x_id[] = {  	{ "tca6408", 8  | PCA953X_TYPE | PCA_INT, },  	{ "tca6416", 16 | PCA953X_TYPE | PCA_INT, },  	{ "tca6424", 24 | PCA953X_TYPE | PCA_INT, }, +	{ "xra1202", 8  | PCA953X_TYPE },  	{ }  };  MODULE_DEVICE_TABLE(i2c, pca953x_id); @@ -89,7 +89,6 @@ struct pca953x_chip {  	u8 irq_stat[MAX_BANK];  	u8 irq_trig_raise[MAX_BANK];  	u8 irq_trig_fall[MAX_BANK]; -	struct irq_domain *domain;  #endif  	struct i2c_client *client; @@ -98,6 +97,11 @@ struct pca953x_chip {  	int	chip_type;  }; +static inline struct pca953x_chip *to_pca(struct gpio_chip *gc) +{ +	return container_of(gc, struct pca953x_chip, gpio_chip); +} +  static int pca953x_read_single(struct pca953x_chip *chip, int reg, u32 *val,  				int off)  { @@ -200,12 +204,10 @@ static int pca953x_read_regs(struct pca953x_chip *chip, int reg, u8 *val)  static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)  { -	struct pca953x_chip *chip; +	struct pca953x_chip *chip = to_pca(gc);  	u8 reg_val;  	int ret, offset = 0; -	chip = container_of(gc, struct pca953x_chip, gpio_chip); -  	mutex_lock(&chip->i2c_lock);  	reg_val = chip->reg_direction[off / BANK_SZ] | (1u << (off % BANK_SZ)); @@ -231,12 +233,10 @@ exit:  static int pca953x_gpio_direction_output(struct gpio_chip *gc,  		unsigned off, int val)  { -	struct pca953x_chip *chip; +	struct pca953x_chip *chip = to_pca(gc);  	u8 reg_val;  	int ret, offset = 0; -	chip = container_of(gc, struct pca953x_chip, gpio_chip); -  	mutex_lock(&chip->i2c_lock);  	/* set output level */  	if (val) @@ -283,12 +283,10 @@ exit:  static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)  { -	struct pca953x_chip *chip; +	struct pca953x_chip *chip = to_pca(gc);  	u32 reg_val;  	int ret, offset = 0; -	chip = container_of(gc, struct pca953x_chip, gpio_chip); -  	mutex_lock(&chip->i2c_lock);  	switch (chip->chip_type) {  	case PCA953X_TYPE: @@ -313,12 +311,10 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)  static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)  { -	struct pca953x_chip *chip; +	struct pca953x_chip *chip = to_pca(gc);  	u8 reg_val;  	int ret, offset = 0; -	chip = container_of(gc, struct pca953x_chip, gpio_chip); -  	mutex_lock(&chip->i2c_lock);  	if (val)  		reg_val = chip->reg_output[off / BANK_SZ] @@ -354,7 +350,7 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)  	gc->direction_output = pca953x_gpio_direction_output;  	gc->get = pca953x_gpio_get_value;  	gc->set = pca953x_gpio_set_value; -	gc->can_sleep = 1; +	gc->can_sleep = true;  	gc->base = chip->gpio_start;  	gc->ngpio = gpios; @@ -365,38 +361,34 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)  }  #ifdef CONFIG_GPIO_PCA953X_IRQ -static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off) -{ -	struct pca953x_chip *chip; - -	chip = container_of(gc, struct pca953x_chip, gpio_chip); -	return irq_create_mapping(chip->domain, off); -} -  static void pca953x_irq_mask(struct irq_data *d)  { -	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); +	struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +	struct pca953x_chip *chip = to_pca(gc);  	chip->irq_mask[d->hwirq / BANK_SZ] &= ~(1 << (d->hwirq % BANK_SZ));  }  static void pca953x_irq_unmask(struct irq_data *d)  { -	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); +	struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +	struct pca953x_chip *chip = to_pca(gc);  	chip->irq_mask[d->hwirq / BANK_SZ] |= 1 << (d->hwirq % BANK_SZ);  }  static void pca953x_irq_bus_lock(struct irq_data *d)  { -	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); +	struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +	struct pca953x_chip *chip = to_pca(gc);  	mutex_lock(&chip->irq_lock);  }  static void pca953x_irq_bus_sync_unlock(struct irq_data *d)  { -	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); +	struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +	struct pca953x_chip *chip = to_pca(gc);  	u8 new_irqs;  	int level, i; @@ -418,7 +410,8 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)  static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)  { -	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); +	struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +	struct pca953x_chip *chip = to_pca(gc);  	int bank_nb = d->hwirq / BANK_SZ;  	u8 mask = 1 << (d->hwirq % BANK_SZ); @@ -501,44 +494,25 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)  	struct pca953x_chip *chip = devid;  	u8 pending[MAX_BANK];  	u8 level; +	unsigned nhandled = 0;  	int i;  	if (!pca953x_irq_pending(chip, pending)) -		return IRQ_HANDLED; +		return IRQ_NONE;  	for (i = 0; i < NBANK(chip); i++) {  		while (pending[i]) {  			level = __ffs(pending[i]); -			handle_nested_irq(irq_find_mapping(chip->domain, +			handle_nested_irq(irq_find_mapping(chip->gpio_chip.irqdomain,  							level + (BANK_SZ * i)));  			pending[i] &= ~(1 << level); +			nhandled++;  		}  	} -	return IRQ_HANDLED; -} - -static int pca953x_gpio_irq_map(struct irq_domain *d, unsigned int irq, -		       irq_hw_number_t hwirq) -{ -	irq_clear_status_flags(irq, IRQ_NOREQUEST); -	irq_set_chip_data(irq, d->host_data); -	irq_set_chip(irq, &pca953x_irq_chip); -	irq_set_nested_thread(irq, true); -#ifdef CONFIG_ARM -	set_irq_flags(irq, IRQF_VALID); -#else -	irq_set_noprobe(irq); -#endif - -	return 0; +	return (nhandled > 0) ? IRQ_HANDLED : IRQ_NONE;  } -static const struct irq_domain_ops pca953x_irq_simple_ops = { -	.map = pca953x_gpio_irq_map, -	.xlate = irq_domain_xlate_twocell, -}; -  static int pca953x_irq_setup(struct pca953x_chip *chip,  			     const struct i2c_device_id *id,  			     int irq_base) @@ -570,19 +544,12 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,  			chip->irq_stat[i] &= chip->reg_direction[i];  		mutex_init(&chip->irq_lock); -		chip->domain = irq_domain_add_simple(client->dev.of_node, -						chip->gpio_chip.ngpio, -						irq_base, -						&pca953x_irq_simple_ops, -						chip); -		if (!chip->domain) -			return -ENODEV; -  		ret = devm_request_threaded_irq(&client->dev,  					client->irq,  					   NULL,  					   pca953x_irq_handler, -					   IRQF_TRIGGER_LOW | IRQF_ONESHOT, +					   IRQF_TRIGGER_LOW | IRQF_ONESHOT | +						   IRQF_SHARED,  					   dev_name(&client->dev), chip);  		if (ret) {  			dev_err(&client->dev, "failed to request irq %d\n", @@ -590,7 +557,16 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,  			return ret;  		} -		chip->gpio_chip.to_irq = pca953x_gpio_to_irq; +		ret =  gpiochip_irqchip_add(&chip->gpio_chip, +					    &pca953x_irq_chip, +					    irq_base, +					    handle_simple_irq, +					    IRQ_TYPE_NONE); +		if (ret) { +			dev_err(&client->dev, +				"could not connect irqchip to gpiochip\n"); +			return ret; +		}  	}  	return 0; @@ -625,11 +601,12 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert)  	const __be32 *val;  	int size; +	*gpio_base = -1; +  	node = client->dev.of_node;  	if (node == NULL)  		return; -	*gpio_base = -1;  	val = of_get_property(node, "linux,gpio-base", &size);  	WARN(val, "%s: device-tree property 'linux,gpio-base' is deprecated!", __func__);  	if (val) { @@ -683,17 +660,6 @@ static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)  	int ret;  	u8 val[MAX_BANK]; -	/* Let every port in proper state, that could save power */ -	memset(val, 0, NBANK(chip)); -	pca953x_write_regs(chip, PCA957X_PUPD, val); -	memset(val, 0xFF, NBANK(chip)); -	pca953x_write_regs(chip, PCA957X_CFG, val); -	memset(val, 0, NBANK(chip)); -	pca953x_write_regs(chip, PCA957X_OUT, val); - -	ret = pca953x_read_regs(chip, PCA957X_IN, val); -	if (ret) -		goto out;  	ret = pca953x_read_regs(chip, PCA957X_OUT, chip->reg_output);  	if (ret)  		goto out; @@ -764,11 +730,11 @@ static int pca953x_probe(struct i2c_client *client,  	if (ret)  		return ret; -	ret = pca953x_irq_setup(chip, id, irq_base); +	ret = gpiochip_add(&chip->gpio_chip);  	if (ret)  		return ret; -	ret = gpiochip_add(&chip->gpio_chip); +	ret = pca953x_irq_setup(chip, id, irq_base);  	if (ret)  		return ret; @@ -823,6 +789,7 @@ static const struct of_device_id pca953x_dt_ids[] = {  	{ .compatible = "nxp,pca9557", },  	{ .compatible = "nxp,pca9574", },  	{ .compatible = "nxp,pca9575", }, +	{ .compatible = "nxp,pca9698", },  	{ .compatible = "maxim,max7310", },  	{ .compatible = "maxim,max7312", }, @@ -833,6 +800,8 @@ static const struct of_device_id pca953x_dt_ids[] = {  	{ .compatible = "ti,tca6408", },  	{ .compatible = "ti,tca6416", },  	{ .compatible = "ti,tca6424", }, + +	{ .compatible = "exar,xra1202", },  	{ }  }; diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index 9e61bb0719d..27b46751ea7 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c @@ -26,9 +26,10 @@  #include <linux/irqdomain.h>  #include <linux/kernel.h>  #include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h>  #include <linux/slab.h>  #include <linux/spinlock.h> -#include <linux/workqueue.h>  static const struct i2c_device_id pcf857x_id[] = { @@ -50,6 +51,27 @@ static const struct i2c_device_id pcf857x_id[] = {  };  MODULE_DEVICE_TABLE(i2c, pcf857x_id); +#ifdef CONFIG_OF +static const struct of_device_id pcf857x_of_table[] = { +	{ .compatible = "nxp,pcf8574" }, +	{ .compatible = "nxp,pcf8574a" }, +	{ .compatible = "nxp,pca8574" }, +	{ .compatible = "nxp,pca9670" }, +	{ .compatible = "nxp,pca9672" }, +	{ .compatible = "nxp,pca9674" }, +	{ .compatible = "nxp,pcf8575" }, +	{ .compatible = "nxp,pca8575" }, +	{ .compatible = "nxp,pca9671" }, +	{ .compatible = "nxp,pca9673" }, +	{ .compatible = "nxp,pca9675" }, +	{ .compatible = "maxim,max7328" }, +	{ .compatible = "maxim,max7329" }, +	{ .compatible = "ti,tca9554" }, +	{ } +}; +MODULE_DEVICE_TABLE(of, pcf857x_of_table); +#endif +  /*   * The pcf857x, pca857x, and pca967x chips only expose one read and one   * write register.  Writing a "one" bit (to match the reset state) lets @@ -66,12 +88,11 @@ struct pcf857x {  	struct gpio_chip	chip;  	struct i2c_client	*client;  	struct mutex		lock;		/* protect 'out' */ -	struct work_struct	work;		/* irq demux work */  	struct irq_domain	*irq_domain;	/* for irq demux  */  	spinlock_t		slock;		/* protect irq demux */  	unsigned		out;		/* software latch */  	unsigned		status;		/* current status */ -	int			irq;		/* real irq number */ +	unsigned		irq_mapped;	/* mapped gpio irqs */  	int (*write)(struct i2c_client *client, unsigned data);  	int (*read)(struct i2c_client *client); @@ -164,48 +185,54 @@ static void pcf857x_set(struct gpio_chip *chip, unsigned offset, int value)  static int pcf857x_to_irq(struct gpio_chip *chip, unsigned offset)  {  	struct pcf857x *gpio = container_of(chip, struct pcf857x, chip); +	int ret; -	return irq_create_mapping(gpio->irq_domain, offset); +	ret = irq_create_mapping(gpio->irq_domain, offset); +	if (ret > 0) +		gpio->irq_mapped |= (1 << offset); + +	return ret;  } -static void pcf857x_irq_demux_work(struct work_struct *work) +static irqreturn_t pcf857x_irq(int irq, void *data)  { -	struct pcf857x *gpio = container_of(work, -					       struct pcf857x, -					       work); +	struct pcf857x  *gpio = data;  	unsigned long change, i, status, flags;  	status = gpio->read(gpio->client);  	spin_lock_irqsave(&gpio->slock, flags); -	change = gpio->status ^ status; +	/* +	 * call the interrupt handler iff gpio is used as +	 * interrupt source, just to avoid bad irqs +	 */ + +	change = ((gpio->status ^ status) & gpio->irq_mapped);  	for_each_set_bit(i, &change, gpio->chip.ngpio)  		generic_handle_irq(irq_find_mapping(gpio->irq_domain, i));  	gpio->status = status;  	spin_unlock_irqrestore(&gpio->slock, flags); -} - -static irqreturn_t pcf857x_irq_demux(int irq, void *data) -{ -	struct pcf857x	*gpio = data; - -	/* -	 * pcf857x can't read/write data here, -	 * since i2c data access might go to sleep. -	 */ -	schedule_work(&gpio->work);  	return IRQ_HANDLED;  } -static int pcf857x_irq_domain_map(struct irq_domain *domain, unsigned int virq, +static int pcf857x_irq_domain_map(struct irq_domain *domain, unsigned int irq,  				 irq_hw_number_t hw)  { -	irq_set_chip_and_handler(virq, +	struct pcf857x *gpio = domain->host_data; + +	irq_set_chip_and_handler(irq,  				 &dummy_irq_chip,  				 handle_level_irq); +#ifdef CONFIG_ARM +	set_irq_flags(irq, IRQF_VALID); +#else +	irq_set_noprobe(irq); +#endif +	gpio->irq_mapped |= (1 << hw); +  	return 0;  } @@ -218,8 +245,6 @@ static void pcf857x_irq_domain_cleanup(struct pcf857x *gpio)  	if (gpio->irq_domain)  		irq_domain_remove(gpio->irq_domain); -	if (gpio->irq) -		free_irq(gpio->irq, gpio);  }  static int pcf857x_irq_domain_init(struct pcf857x *gpio, @@ -230,20 +255,21 @@ static int pcf857x_irq_domain_init(struct pcf857x *gpio,  	gpio->irq_domain = irq_domain_add_linear(client->dev.of_node,  						 gpio->chip.ngpio,  						 &pcf857x_irq_domain_ops, -						 NULL); +						 gpio);  	if (!gpio->irq_domain)  		goto fail;  	/* enable real irq */ -	status = request_irq(client->irq, pcf857x_irq_demux, 0, -			     dev_name(&client->dev), gpio); +	status = devm_request_threaded_irq(&client->dev, client->irq, +				NULL, pcf857x_irq, IRQF_ONESHOT | +				IRQF_TRIGGER_FALLING | IRQF_SHARED, +				dev_name(&client->dev), gpio); +  	if (status)  		goto fail;  	/* enable gpio_to_irq() */ -	INIT_WORK(&gpio->work, pcf857x_irq_demux_work);  	gpio->chip.to_irq	= pcf857x_to_irq; -	gpio->irq		= client->irq;  	return 0; @@ -257,14 +283,18 @@ fail:  static int pcf857x_probe(struct i2c_client *client,  			 const struct i2c_device_id *id)  { -	struct pcf857x_platform_data	*pdata; +	struct pcf857x_platform_data	*pdata = dev_get_platdata(&client->dev); +	struct device_node		*np = client->dev.of_node;  	struct pcf857x			*gpio; +	unsigned int			n_latch = 0;  	int				status; -	pdata = dev_get_platdata(&client->dev); -	if (!pdata) { +	if (IS_ENABLED(CONFIG_OF) && np) +		of_property_read_u32(np, "lines-initial-states", &n_latch); +	else if (pdata) +		n_latch = pdata->n_latch; +	else  		dev_dbg(&client->dev, "no platform data\n"); -	}  	/* Allocate, initialize, and register this gpio_chip. */  	gpio = devm_kzalloc(&client->dev, sizeof(*gpio), GFP_KERNEL); @@ -275,7 +305,7 @@ static int pcf857x_probe(struct i2c_client *client,  	spin_lock_init(&gpio->slock);  	gpio->chip.base			= pdata ? pdata->gpio_base : -1; -	gpio->chip.can_sleep		= 1; +	gpio->chip.can_sleep		= true;  	gpio->chip.dev			= &client->dev;  	gpio->chip.owner		= THIS_MODULE;  	gpio->chip.get			= pcf857x_get; @@ -289,7 +319,7 @@ static int pcf857x_probe(struct i2c_client *client,  		status = pcf857x_irq_domain_init(gpio, client);  		if (status < 0) {  			dev_err(&client->dev, "irq_domain init failed\n"); -			goto fail; +			goto fail_irq_domain;  		}  	} @@ -357,11 +387,11 @@ static int pcf857x_probe(struct i2c_client *client,  	 * may cause transient glitching since it can't know the last value  	 * written (some pins may need to be driven low).  	 * -	 * Using pdata->n_latch avoids that trouble.  When left initialized -	 * to zero, our software copy of the "latch" then matches the chip's -	 * all-ones reset state.  Otherwise it flags pins to be driven low. +	 * Using n_latch avoids that trouble.  When left initialized to zero, +	 * our software copy of the "latch" then matches the chip's all-ones +	 * reset state.  Otherwise it flags pins to be driven low.  	 */ -	gpio->out = pdata ? ~pdata->n_latch : ~0; +	gpio->out = ~n_latch;  	gpio->status = gpio->out;  	status = gpiochip_add(&gpio->chip); @@ -384,12 +414,13 @@ static int pcf857x_probe(struct i2c_client *client,  	return 0;  fail: -	dev_dbg(&client->dev, "probe error %d for '%s'\n", -			status, client->name); -  	if (client->irq)  		pcf857x_irq_domain_cleanup(gpio); +fail_irq_domain: +	dev_dbg(&client->dev, "probe error %d for '%s'\n", +		status, client->name); +  	return status;  } @@ -423,6 +454,7 @@ static struct i2c_driver pcf857x_driver = {  	.driver = {  		.name	= "pcf857x",  		.owner	= THIS_MODULE, +		.of_match_table = of_match_ptr(pcf857x_of_table),  	},  	.probe	= pcf857x_probe,  	.remove	= pcf857x_remove, diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index 0fec097e838..d6eac9b17db 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -20,6 +20,7 @@  #include <linux/gpio.h>  #include <linux/interrupt.h>  #include <linux/irq.h> +#include <linux/slab.h>  #define PCH_EDGE_FALLING	0  #define PCH_EDGE_RISING		BIT(0) @@ -138,9 +139,6 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,  	unsigned long flags;  	spin_lock_irqsave(&chip->spinlock, flags); -	pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1); -	pm |= (1 << nr); -	iowrite32(pm, &chip->reg->pm);  	reg_val = ioread32(&chip->reg->po);  	if (val) @@ -148,6 +146,11 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,  	else  		reg_val &= ~(1 << nr);  	iowrite32(reg_val, &chip->reg->po); + +	pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1); +	pm |= (1 << nr); +	iowrite32(pm, &chip->reg->pm); +  	spin_unlock_irqrestore(&chip->spinlock, flags);  	return 0; @@ -224,7 +227,7 @@ static void pch_gpio_setup(struct pch_gpio *chip)  	gpio->dbg_show = NULL;  	gpio->base = -1;  	gpio->ngpio = gpio_pins[chip->ioh]; -	gpio->can_sleep = 0; +	gpio->can_sleep = false;  	gpio->to_irq = pch_gpio_to_irq;  } @@ -518,7 +521,7 @@ static int pch_gpio_resume(struct pci_dev *pdev)  #endif  #define PCI_VENDOR_ID_ROHM             0x10DB -static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = { +static const struct pci_device_id pch_gpio_pcidev_id[] = {  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },  	{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },  	{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8043) }, diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 4274e2e70ef..84b49cfb81a 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -15,10 +15,8 @@  #include <linux/io.h>  #include <linux/ioport.h>  #include <linux/irq.h> -#include <linux/irqdomain.h>  #include <linux/irqchip/chained_irq.h>  #include <linux/bitops.h> -#include <linux/workqueue.h>  #include <linux/gpio.h>  #include <linux/device.h>  #include <linux/amba/bus.h> @@ -53,7 +51,6 @@ struct pl061_gpio {  	spinlock_t		lock;  	void __iomem		*base; -	struct irq_domain	*domain;  	struct gpio_chip	gc;  #ifdef CONFIG_PM @@ -90,7 +87,7 @@ static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)  	spin_lock_irqsave(&chip->lock, flags);  	gpiodir = readb(chip->base + GPIODIR); -	gpiodir &= ~(1 << offset); +	gpiodir &= ~(BIT(offset));  	writeb(gpiodir, chip->base + GPIODIR);  	spin_unlock_irqrestore(&chip->lock, flags); @@ -108,16 +105,16 @@ static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,  		return -EINVAL;  	spin_lock_irqsave(&chip->lock, flags); -	writeb(!!value << offset, chip->base + (1 << (offset + 2))); +	writeb(!!value << offset, chip->base + (BIT(offset + 2)));  	gpiodir = readb(chip->base + GPIODIR); -	gpiodir |= 1 << offset; +	gpiodir |= BIT(offset);  	writeb(gpiodir, chip->base + GPIODIR);  	/*  	 * gpio value is set again, because pl061 doesn't allow to set value of  	 * a gpio pin before configuring it in OUT mode.  	 */ -	writeb(!!value << offset, chip->base + (1 << (offset + 2))); +	writeb(!!value << offset, chip->base + (BIT(offset + 2)));  	spin_unlock_irqrestore(&chip->lock, flags);  	return 0; @@ -127,29 +124,24 @@ static int pl061_get_value(struct gpio_chip *gc, unsigned offset)  {  	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); -	return !!readb(chip->base + (1 << (offset + 2))); +	return !!readb(chip->base + (BIT(offset + 2)));  }  static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value)  {  	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); -	writeb(!!value << offset, chip->base + (1 << (offset + 2))); -} - -static int pl061_to_irq(struct gpio_chip *gc, unsigned offset) -{ -	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); - -	return irq_create_mapping(chip->domain, offset); +	writeb(!!value << offset, chip->base + (BIT(offset + 2)));  }  static int pl061_irq_type(struct irq_data *d, unsigned trigger)  { -	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); +	struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);  	int offset = irqd_to_hwirq(d);  	unsigned long flags;  	u8 gpiois, gpioibe, gpioiev; +	u8 bit = BIT(offset);  	if (offset < 0 || offset >= PL061_GPIO_NR)  		return -EINVAL; @@ -157,30 +149,31 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)  	spin_lock_irqsave(&chip->lock, flags);  	gpioiev = readb(chip->base + GPIOIEV); -  	gpiois = readb(chip->base + GPIOIS); +	gpioibe = readb(chip->base + GPIOIBE); +  	if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { -		gpiois |= 1 << offset; +		gpiois |= bit;  		if (trigger & IRQ_TYPE_LEVEL_HIGH) -			gpioiev |= 1 << offset; +			gpioiev |= bit;  		else -			gpioiev &= ~(1 << offset); +			gpioiev &= ~bit;  	} else -		gpiois &= ~(1 << offset); -	writeb(gpiois, chip->base + GPIOIS); +		gpiois &= ~bit; -	gpioibe = readb(chip->base + GPIOIBE);  	if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) -		gpioibe |= 1 << offset; +		/* Setting this makes GPIOEV be ignored */ +		gpioibe |= bit;  	else { -		gpioibe &= ~(1 << offset); +		gpioibe &= ~bit;  		if (trigger & IRQ_TYPE_EDGE_RISING) -			gpioiev |= 1 << offset; +			gpioiev |= bit;  		else if (trigger & IRQ_TYPE_EDGE_FALLING) -			gpioiev &= ~(1 << offset); +			gpioiev &= ~bit;  	} -	writeb(gpioibe, chip->base + GPIOIBE); +	writeb(gpiois, chip->base + GPIOIS); +	writeb(gpioibe, chip->base + GPIOIBE);  	writeb(gpioiev, chip->base + GPIOIEV);  	spin_unlock_irqrestore(&chip->lock, flags); @@ -192,7 +185,8 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)  {  	unsigned long pending;  	int offset; -	struct pl061_gpio *chip = irq_desc_get_handler_data(desc); +	struct gpio_chip *gc = irq_desc_get_handler_data(desc); +	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);  	struct irq_chip *irqchip = irq_desc_get_chip(desc);  	chained_irq_enter(irqchip, desc); @@ -201,7 +195,8 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)  	writeb(pending, chip->base + GPIOIC);  	if (pending) {  		for_each_set_bit(offset, &pending, PL061_GPIO_NR) -			generic_handle_irq(pl061_to_irq(&chip->gc, offset)); +			generic_handle_irq(irq_find_mapping(gc->irqdomain, +							    offset));  	}  	chained_irq_exit(irqchip, desc); @@ -209,8 +204,9 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)  static void pl061_irq_mask(struct irq_data *d)  { -	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); -	u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR); +	struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); +	u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);  	u8 gpioie;  	spin_lock(&chip->lock); @@ -221,8 +217,9 @@ static void pl061_irq_mask(struct irq_data *d)  static void pl061_irq_unmask(struct irq_data *d)  { -	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); -	u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR); +	struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc); +	u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);  	u8 gpioie;  	spin_lock(&chip->lock); @@ -232,30 +229,12 @@ static void pl061_irq_unmask(struct irq_data *d)  }  static struct irq_chip pl061_irqchip = { -	.name		= "pl061 gpio", +	.name		= "pl061",  	.irq_mask	= pl061_irq_mask,  	.irq_unmask	= pl061_irq_unmask,  	.irq_set_type	= pl061_irq_type,  }; -static int pl061_irq_map(struct irq_domain *d, unsigned int virq, -			 irq_hw_number_t hw) -{ -	struct pl061_gpio *chip = d->host_data; - -	irq_set_chip_and_handler_name(virq, &pl061_irqchip, handle_simple_irq, -				      "pl061"); -	irq_set_chip_data(virq, chip); -	irq_set_irq_type(virq, IRQ_TYPE_NONE); - -	return 0; -} - -static const struct irq_domain_ops pl061_domain_ops = { -	.map	= pl061_irq_map, -	.xlate	= irq_domain_xlate_twocell, -}; -  static int pl061_probe(struct amba_device *adev, const struct amba_id *id)  {  	struct device *dev = &adev->dev; @@ -270,26 +249,18 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)  	if (pdata) {  		chip->gc.base = pdata->gpio_base;  		irq_base = pdata->irq_base; -		if (irq_base <= 0) +		if (irq_base <= 0) { +			dev_err(&adev->dev, "invalid IRQ base in pdata\n");  			return -ENODEV; +		}  	} else {  		chip->gc.base = -1;  		irq_base = 0;  	} -	if (!devm_request_mem_region(dev, adev->res.start, -				     resource_size(&adev->res), "pl061")) -		return -EBUSY; - -	chip->base = devm_ioremap(dev, adev->res.start, -				  resource_size(&adev->res)); -	if (!chip->base) -		return -ENOMEM; - -	chip->domain = irq_domain_add_simple(adev->dev.of_node, PL061_GPIO_NR, -					     irq_base, &pl061_domain_ops, chip); -	if (!chip->domain) -		return -ENODEV; +	chip->base = devm_ioremap_resource(dev, &adev->res); +	if (IS_ERR(chip->base)) +		return PTR_ERR(chip->base);  	spin_lock_init(&chip->lock); @@ -299,7 +270,6 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)  	chip->gc.direction_output = pl061_direction_output;  	chip->gc.get = pl061_get_value;  	chip->gc.set = pl061_set_value; -	chip->gc.to_irq = pl061_to_irq;  	chip->gc.ngpio = PL061_GPIO_NR;  	chip->gc.label = dev_name(dev);  	chip->gc.dev = dev; @@ -314,23 +284,34 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)  	 */  	writeb(0, chip->base + GPIOIE); /* disable irqs */  	irq = adev->irq[0]; -	if (irq < 0) +	if (irq < 0) { +		dev_err(&adev->dev, "invalid IRQ\n");  		return -ENODEV; +	} -	irq_set_chained_handler(irq, pl061_irq_handler); -	irq_set_handler_data(irq, chip); +	ret = gpiochip_irqchip_add(&chip->gc, &pl061_irqchip, +				   irq_base, handle_simple_irq, +				   IRQ_TYPE_NONE); +	if (ret) { +		dev_info(&adev->dev, "could not add irqchip\n"); +		return ret; +	} +	gpiochip_set_chained_irqchip(&chip->gc, &pl061_irqchip, +				     irq, pl061_irq_handler);  	for (i = 0; i < PL061_GPIO_NR; i++) {  		if (pdata) { -			if (pdata->directions & (1 << i)) +			if (pdata->directions & (BIT(i)))  				pl061_direction_output(&chip->gc, i, -						pdata->values & (1 << i)); +						pdata->values & (BIT(i)));  			else  				pl061_direction_input(&chip->gc, i);  		}  	}  	amba_set_drvdata(adev, chip); +	dev_info(&adev->dev, "PL061 GPIO chip @%pa registered\n", +		 &adev->res.start);  	return 0;  } @@ -349,7 +330,7 @@ static int pl061_suspend(struct device *dev)  	chip->csave_regs.gpio_ie = readb(chip->base + GPIOIE);  	for (offset = 0; offset < PL061_GPIO_NR; offset++) { -		if (chip->csave_regs.gpio_dir & (1 << offset)) +		if (chip->csave_regs.gpio_dir & (BIT(offset)))  			chip->csave_regs.gpio_data |=  				pl061_get_value(&chip->gc, offset) << offset;  	} @@ -363,10 +344,10 @@ static int pl061_resume(struct device *dev)  	int offset;  	for (offset = 0; offset < PL061_GPIO_NR; offset++) { -		if (chip->csave_regs.gpio_dir & (1 << offset)) +		if (chip->csave_regs.gpio_dir & (BIT(offset)))  			pl061_direction_output(&chip->gc, offset,  					chip->csave_regs.gpio_data & -					(1 << offset)); +					(BIT(offset)));  		else  			pl061_direction_input(&chip->gc, offset);  	} diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index cc13d1b74fa..42e6e64f212 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -263,7 +263,8 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip,  static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)  { -	return readl_relaxed(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset); +	u32 gplr = readl_relaxed(gpio_chip_base(chip) + GPLR_OFFSET); +	return !!(gplr & (1 << offset));  }  static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) diff --git a/drivers/gpio/gpio-rc5t583.c b/drivers/gpio/gpio-rc5t583.c index e63d6a397e1..562b0c4d9cc 100644 --- a/drivers/gpio/gpio-rc5t583.c +++ b/drivers/gpio/gpio-rc5t583.c @@ -97,7 +97,7 @@ static int rc5t583_gpio_to_irq(struct gpio_chip *gc, unsigned offset)  {  	struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc); -	if ((offset >= 0) && (offset < 8)) +	if (offset < RC5T583_MAX_GPIO)  		return rc5t583_gpio->rc5t583->irq_base +  				RC5T583_IRQ_GPIO0 + offset;  	return -EINVAL; @@ -119,10 +119,8 @@ static int rc5t583_gpio_probe(struct platform_device *pdev)  	rc5t583_gpio = devm_kzalloc(&pdev->dev, sizeof(*rc5t583_gpio),  					GFP_KERNEL); -	if (!rc5t583_gpio) { -		dev_warn(&pdev->dev, "Mem allocation for rc5t583_gpio failed"); +	if (!rc5t583_gpio)  		return -ENOMEM; -	}  	rc5t583_gpio->gpio_chip.label = "gpio-rc5t583",  	rc5t583_gpio->gpio_chip.owner = THIS_MODULE, @@ -133,7 +131,7 @@ static int rc5t583_gpio_probe(struct platform_device *pdev)  	rc5t583_gpio->gpio_chip.get = rc5t583_gpio_get,  	rc5t583_gpio->gpio_chip.to_irq = rc5t583_gpio_to_irq,  	rc5t583_gpio->gpio_chip.ngpio = RC5T583_MAX_GPIO, -	rc5t583_gpio->gpio_chip.can_sleep = 1, +	rc5t583_gpio->gpio_chip.can_sleep = true,  	rc5t583_gpio->gpio_chip.dev = &pdev->dev;  	rc5t583_gpio->gpio_chip.base = -1;  	rc5t583_gpio->rc5t583 = rc5t583; diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index e3745eb0757..b6ae89ea881 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -22,9 +22,11 @@  #include <linux/irq.h>  #include <linux/irqdomain.h>  #include <linux/module.h> +#include <linux/of.h>  #include <linux/pinctrl/consumer.h>  #include <linux/platform_data/gpio-rcar.h>  #include <linux/platform_device.h> +#include <linux/pm_runtime.h>  #include <linux/spinlock.h>  #include <linux/slab.h> @@ -168,7 +170,8 @@ static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)  	u32 pending;  	unsigned int offset, irqs_handled = 0; -	while ((pending = gpio_rcar_read(p, INTDT))) { +	while ((pending = gpio_rcar_read(p, INTDT) & +			  gpio_rcar_read(p, INTMSK))) {  		offset = __ffs(pending);  		gpio_rcar_write(p, INTCLR, BIT(offset));  		generic_handle_irq(irq_find_mapping(p->irq_domain, offset)); @@ -266,24 +269,52 @@ static int gpio_rcar_to_irq(struct gpio_chip *chip, unsigned offset)  	return irq_create_mapping(gpio_to_priv(chip)->irq_domain, offset);  } -static int gpio_rcar_irq_domain_map(struct irq_domain *h, unsigned int virq, -				 irq_hw_number_t hw) +static int gpio_rcar_irq_domain_map(struct irq_domain *h, unsigned int irq, +				 irq_hw_number_t hwirq)  {  	struct gpio_rcar_priv *p = h->host_data; -	dev_dbg(&p->pdev->dev, "map hw irq = %d, virq = %d\n", (int)hw, virq); +	dev_dbg(&p->pdev->dev, "map hw irq = %d, irq = %d\n", (int)hwirq, irq); -	irq_set_chip_data(virq, h->host_data); -	irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq); -	set_irq_flags(virq, IRQF_VALID); /* kill me now */ +	irq_set_chip_data(irq, h->host_data); +	irq_set_chip_and_handler(irq, &p->irq_chip, handle_level_irq); +	set_irq_flags(irq, IRQF_VALID); /* kill me now */  	return 0;  }  static struct irq_domain_ops gpio_rcar_irq_domain_ops = {  	.map	= gpio_rcar_irq_domain_map, +	.xlate	= irq_domain_xlate_twocell,  }; -static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p) +struct gpio_rcar_info { +	bool has_both_edge_trigger; +}; + +static const struct of_device_id gpio_rcar_of_table[] = { +	{ +		.compatible = "renesas,gpio-r8a7790", +		.data = (void *)&(const struct gpio_rcar_info) { +			.has_both_edge_trigger = true, +		}, +	}, { +		.compatible = "renesas,gpio-r8a7791", +		.data = (void *)&(const struct gpio_rcar_info) { +			.has_both_edge_trigger = true, +		}, +	}, { +		.compatible = "renesas,gpio-rcar", +		.data = (void *)&(const struct gpio_rcar_info) { +			.has_both_edge_trigger = false, +		}, +	}, { +		/* Terminator */ +	}, +}; + +MODULE_DEVICE_TABLE(of, gpio_rcar_of_table); + +static int gpio_rcar_parse_pdata(struct gpio_rcar_priv *p)  {  	struct gpio_rcar_config *pdata = dev_get_platdata(&p->pdev->dev);  	struct device_node *np = p->pdev->dev.of_node; @@ -293,12 +324,21 @@ static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p)  	if (pdata) {  		p->config = *pdata;  	} else if (IS_ENABLED(CONFIG_OF) && np) { -		ret = of_parse_phandle_with_args(np, "gpio-ranges", -				"#gpio-range-cells", 0, &args); -		p->config.number_of_pins = ret == 0 && args.args_count == 3 -					 ? args.args[2] +		const struct of_device_id *match; +		const struct gpio_rcar_info *info; + +		match = of_match_node(gpio_rcar_of_table, np); +		if (!match) +			return -EINVAL; + +		info = match->data; + +		ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, +						       &args); +		p->config.number_of_pins = ret == 0 ? args.args[2]  					 : RCAR_MAX_GPIO_PER_BANK;  		p->config.gpio_base = -1; +		p->config.has_both_edge_trigger = info->has_both_edge_trigger;  	}  	if (p->config.number_of_pins == 0 || @@ -308,6 +348,8 @@ static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p)  			 p->config.number_of_pins, RCAR_MAX_GPIO_PER_BANK);  		p->config.number_of_pins = RCAR_MAX_GPIO_PER_BANK;  	} + +	return 0;  }  static int gpio_rcar_probe(struct platform_device *pdev) @@ -316,12 +358,12 @@ static int gpio_rcar_probe(struct platform_device *pdev)  	struct resource *io, *irq;  	struct gpio_chip *gpio_chip;  	struct irq_chip *irq_chip; -	const char *name = dev_name(&pdev->dev); +	struct device *dev = &pdev->dev; +	const char *name = dev_name(dev);  	int ret; -	p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); +	p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL);  	if (!p) { -		dev_err(&pdev->dev, "failed to allocate driver data\n");  		ret = -ENOMEM;  		goto err0;  	} @@ -330,23 +372,27 @@ static int gpio_rcar_probe(struct platform_device *pdev)  	spin_lock_init(&p->lock);  	/* Get device configuration from DT node or platform data. */ -	gpio_rcar_parse_pdata(p); +	ret = gpio_rcar_parse_pdata(p); +	if (ret < 0) +		return ret;  	platform_set_drvdata(pdev, p); +	pm_runtime_enable(dev); +	pm_runtime_get_sync(dev); +  	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);  	if (!io || !irq) { -		dev_err(&pdev->dev, "missing IRQ or IOMEM\n"); +		dev_err(dev, "missing IRQ or IOMEM\n");  		ret = -EINVAL;  		goto err0;  	} -	p->base = devm_ioremap_nocache(&pdev->dev, io->start, -				       resource_size(io)); +	p->base = devm_ioremap_nocache(dev, io->start, resource_size(io));  	if (!p->base) { -		dev_err(&pdev->dev, "failed to remap I/O memory\n"); +		dev_err(dev, "failed to remap I/O memory\n");  		ret = -ENXIO;  		goto err0;  	} @@ -360,7 +406,7 @@ static int gpio_rcar_probe(struct platform_device *pdev)  	gpio_chip->set = gpio_rcar_set;  	gpio_chip->to_irq = gpio_rcar_to_irq;  	gpio_chip->label = name; -	gpio_chip->dev = &pdev->dev; +	gpio_chip->dev = dev;  	gpio_chip->owner = THIS_MODULE;  	gpio_chip->base = p->config.gpio_base;  	gpio_chip->ngpio = p->config.number_of_pins; @@ -369,10 +415,9 @@ static int gpio_rcar_probe(struct platform_device *pdev)  	irq_chip->name = name;  	irq_chip->irq_mask = gpio_rcar_irq_disable;  	irq_chip->irq_unmask = gpio_rcar_irq_enable; -	irq_chip->irq_enable = gpio_rcar_irq_enable; -	irq_chip->irq_disable = gpio_rcar_irq_disable;  	irq_chip->irq_set_type = gpio_rcar_irq_set_type; -	irq_chip->flags	= IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED; +	irq_chip->flags	= IRQCHIP_SKIP_SET_WAKE | IRQCHIP_SET_TYPE_MASKED +			 | IRQCHIP_MASK_ON_SUSPEND;  	p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,  					      p->config.number_of_pins, @@ -380,30 +425,30 @@ static int gpio_rcar_probe(struct platform_device *pdev)  					      &gpio_rcar_irq_domain_ops, p);  	if (!p->irq_domain) {  		ret = -ENXIO; -		dev_err(&pdev->dev, "cannot initialize irq domain\n"); -		goto err1; +		dev_err(dev, "cannot initialize irq domain\n"); +		goto err0;  	} -	if (devm_request_irq(&pdev->dev, irq->start, -			     gpio_rcar_irq_handler, IRQF_SHARED, name, p)) { -		dev_err(&pdev->dev, "failed to request IRQ\n"); +	if (devm_request_irq(dev, irq->start, gpio_rcar_irq_handler, +			     IRQF_SHARED, name, p)) { +		dev_err(dev, "failed to request IRQ\n");  		ret = -ENOENT;  		goto err1;  	}  	ret = gpiochip_add(gpio_chip);  	if (ret) { -		dev_err(&pdev->dev, "failed to add GPIO controller\n"); +		dev_err(dev, "failed to add GPIO controller\n");  		goto err1;  	} -	dev_info(&pdev->dev, "driving %d GPIOs\n", p->config.number_of_pins); +	dev_info(dev, "driving %d GPIOs\n", p->config.number_of_pins);  	/* warn in case of mismatch if irq base is specified */  	if (p->config.irq_base) {  		ret = irq_find_mapping(p->irq_domain, 0);  		if (p->config.irq_base != ret) -			dev_warn(&pdev->dev, "irq base mismatch (%u/%u)\n", +			dev_warn(dev, "irq base mismatch (%u/%u)\n",  				 p->config.irq_base, ret);  	} @@ -411,7 +456,7 @@ static int gpio_rcar_probe(struct platform_device *pdev)  		ret = gpiochip_add_pin_range(gpio_chip, p->config.pctl_name, 0,  					     gpio_chip->base, gpio_chip->ngpio);  		if (ret < 0) -			dev_warn(&pdev->dev, "failed to add pin range\n"); +			dev_warn(dev, "failed to add pin range\n");  	}  	return 0; @@ -419,6 +464,8 @@ static int gpio_rcar_probe(struct platform_device *pdev)  err1:  	irq_domain_remove(p->irq_domain);  err0: +	pm_runtime_put(dev); +	pm_runtime_disable(dev);  	return ret;  } @@ -432,20 +479,11 @@ static int gpio_rcar_remove(struct platform_device *pdev)  		return ret;  	irq_domain_remove(p->irq_domain); +	pm_runtime_put(&pdev->dev); +	pm_runtime_disable(&pdev->dev);  	return 0;  } -#ifdef CONFIG_OF -static const struct of_device_id gpio_rcar_of_table[] = { -	{ -		.compatible = "renesas,gpio-rcar", -	}, -	{ }, -}; - -MODULE_DEVICE_TABLE(of, gpio_rcar_of_table); -#endif -  static struct platform_driver gpio_rcar_device_driver = {  	.probe		= gpio_rcar_probe,  	.remove		= gpio_rcar_remove, diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c index 88577c3272a..9fa7e53331c 100644 --- a/drivers/gpio/gpio-rdc321x.c +++ b/drivers/gpio/gpio-rdc321x.c @@ -141,17 +141,15 @@ static int rdc321x_gpio_probe(struct platform_device *pdev)  		return -ENODEV;  	} -	rdc321x_gpio_dev = kzalloc(sizeof(struct rdc321x_gpio), GFP_KERNEL); -	if (!rdc321x_gpio_dev) { -		dev_err(&pdev->dev, "failed to allocate private data\n"); +	rdc321x_gpio_dev = devm_kzalloc(&pdev->dev, sizeof(struct rdc321x_gpio), +					GFP_KERNEL); +	if (!rdc321x_gpio_dev)  		return -ENOMEM; -	}  	r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg1");  	if (!r) {  		dev_err(&pdev->dev, "failed to get gpio-reg1 resource\n"); -		err = -ENODEV; -		goto out_free; +		return -ENODEV;  	}  	spin_lock_init(&rdc321x_gpio_dev->lock); @@ -162,8 +160,7 @@ static int rdc321x_gpio_probe(struct platform_device *pdev)  	r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg2");  	if (!r) {  		dev_err(&pdev->dev, "failed to get gpio-reg2 resource\n"); -		err = -ENODEV; -		goto out_free; +		return -ENODEV;  	}  	rdc321x_gpio_dev->reg2_ctrl_base = r->start; @@ -187,21 +184,17 @@ static int rdc321x_gpio_probe(struct platform_device *pdev)  					rdc321x_gpio_dev->reg1_data_base,  					&rdc321x_gpio_dev->data_reg[0]);  	if (err) -		goto out_free; +		return err;  	err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,  					rdc321x_gpio_dev->reg2_data_base,  					&rdc321x_gpio_dev->data_reg[1]);  	if (err) -		goto out_free; +		return err;  	dev_info(&pdev->dev, "registering %d GPIOs\n",  					rdc321x_gpio_dev->chip.ngpio);  	return gpiochip_add(&rdc321x_gpio_dev->chip); - -out_free: -	kfree(rdc321x_gpio_dev); -	return err;  }  static int rdc321x_gpio_remove(struct platform_device *pdev) @@ -213,8 +206,6 @@ static int rdc321x_gpio_remove(struct platform_device *pdev)  	if (ret)  		dev_err(&pdev->dev, "failed to unregister chip\n"); -	kfree(rdc321x_gpio_dev); -  	return ret;  } diff --git a/drivers/gpio/gpio-sa1100.c b/drivers/gpio/gpio-sa1100.c index 8ea3b33d4b4..a90be34e4d5 100644 --- a/drivers/gpio/gpio-sa1100.c +++ b/drivers/gpio/gpio-sa1100.c @@ -10,7 +10,7 @@  #include <linux/gpio.h>  #include <linux/init.h>  #include <linux/module.h> - +#include <linux/io.h>  #include <mach/hardware.h>  #include <mach/irqs.h> diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 358a21c2d81..07105ee5c9a 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -30,10 +30,13 @@  #include <asm/irq.h> -#include <mach/hardware.h>  #include <mach/map.h>  #include <mach/regs-gpio.h> +#if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S3C64XX) +#include <mach/gpio-samsung.h> +#endif +  #include <plat/cpu.h>  #include <plat/gpio-core.h>  #include <plat/gpio-cfg.h> @@ -376,6 +379,7 @@ static int s5p64x0_gpio_setcfg_rbank(struct samsung_gpio_chip *chip,  	case 6:  		shift = ((off + 1) & 7) * 4;  		reg -= 4; +		break;  	default:  		shift = ((off + 1) & 7) * 4;  		break; @@ -1033,7 +1037,7 @@ static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)  }  #endif -#ifdef CONFIG_PLAT_S3C64XX +#ifdef CONFIG_ARCH_S3C64XX  static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)  {  	return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO; @@ -1053,7 +1057,7 @@ struct samsung_gpio_chip s3c24xx_gpios[] = {  			.base			= S3C2410_GPA(0),  			.owner			= THIS_MODULE,  			.label			= "GPIOA", -			.ngpio			= 24, +			.ngpio			= 27,  			.direction_input	= s3c24xx_gpiolib_banka_input,  			.direction_output	= s3c24xx_gpiolib_banka_output,  		}, @@ -1062,7 +1066,7 @@ struct samsung_gpio_chip s3c24xx_gpios[] = {  			.base	= S3C2410_GPB(0),  			.owner	= THIS_MODULE,  			.label	= "GPIOB", -			.ngpio	= 16, +			.ngpio	= 11,  		},  	}, {  		.chip	= { @@ -1107,7 +1111,7 @@ struct samsung_gpio_chip s3c24xx_gpios[] = {  			.base	= S3C2410_GPH(0),  			.owner	= THIS_MODULE,  			.label	= "GPIOH", -			.ngpio	= 11, +			.ngpio	= 15,  		},  	},  		/* GPIOS for the S3C2443 and later devices. */ @@ -1174,7 +1178,7 @@ struct samsung_gpio_chip s3c24xx_gpios[] = {   */  static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = { -#ifdef CONFIG_PLAT_S3C64XX +#ifdef CONFIG_ARCH_S3C64XX  	{  		.chip	= {  			.base	= S3C64XX_GPA(0), @@ -1227,7 +1231,7 @@ static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {  };  static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = { -#ifdef CONFIG_PLAT_S3C64XX +#ifdef CONFIG_ARCH_S3C64XX  	{  		.base	= S3C64XX_GPH_BASE + 0x4,  		.chip	= { @@ -1257,7 +1261,7 @@ static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {  };  static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = { -#ifdef CONFIG_PLAT_S3C64XX +#ifdef CONFIG_ARCH_S3C64XX  	{  		.base	= S3C64XX_GPF_BASE,  		.config	= &samsung_gpio_cfgs[6], @@ -2082,34 +2086,14 @@ static __init int samsung_gpiolib_init(void)  	int i, nr_chips;  	int group = 0; -#if defined(CONFIG_PINCTRL_EXYNOS) || defined(CONFIG_PINCTRL_EXYNOS5440)  	/* -	* This gpio driver includes support for device tree support and there -	* are platforms using it. In order to maintain compatibility with those -	* platforms, and to allow non-dt Exynos4210 platforms to use this -	* gpiolib support, a check is added to find out if there is a active -	* pin-controller driver support available. If it is available, this -	* gpiolib support is ignored and the gpiolib support available in -	* pin-controller driver is used. This is a temporary check and will go -	* away when all of the Exynos4210 platforms have switched to using -	* device tree and the pin-ctrl driver. -	*/ -	struct device_node *pctrl_np; -	static const struct of_device_id exynos_pinctrl_ids[] = { -		{ .compatible = "samsung,s3c2412-pinctrl", }, -		{ .compatible = "samsung,s3c2416-pinctrl", }, -		{ .compatible = "samsung,s3c2440-pinctrl", }, -		{ .compatible = "samsung,s3c2450-pinctrl", }, -		{ .compatible = "samsung,exynos4210-pinctrl", }, -		{ .compatible = "samsung,exynos4x12-pinctrl", }, -		{ .compatible = "samsung,exynos5250-pinctrl", }, -		{ .compatible = "samsung,exynos5440-pinctrl", }, -		{ } -	}; -	for_each_matching_node(pctrl_np, exynos_pinctrl_ids) -		if (pctrl_np && of_device_is_available(pctrl_np)) -			return -ENODEV; -#endif +	 * Currently there are two drivers that can provide GPIO support for +	 * Samsung SoCs. For device tree enabled platforms, the new +	 * pinctrl-samsung driver is used, providing both GPIO and pin control +	 * interfaces. For legacy (non-DT) platforms this driver is used. +	 */ +	if (of_have_populated_dt()) +		return -ENODEV;  	samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs)); diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c index 5af65719b95..a9b1cd16c84 100644 --- a/drivers/gpio/gpio-sch.c +++ b/drivers/gpio/gpio-sch.c @@ -97,8 +97,6 @@ static int sch_gpio_core_direction_out(struct gpio_chip *gc,  	u8 curr_dirs;  	unsigned short offset, bit; -	sch_gpio_core_set(gc, gpio_num, val); -  	spin_lock(&gpio_lock);  	offset = CGIO + gpio_num / 8; @@ -109,6 +107,17 @@ static int sch_gpio_core_direction_out(struct gpio_chip *gc,  		outb(curr_dirs & ~(1 << bit), gpio_ba + offset);  	spin_unlock(&gpio_lock); + +	/* +	 * according to the datasheet, writing to the level register has no +	 * effect when GPIO is programmed as input. +	 * Actually the the level register is read-only when configured as input. +	 * Thus presetting the output level before switching to output is _NOT_ possible. +	 * Hence we set the level after configuring the GPIO as output. +	 * But we cannot prevent a short low pulse if direction is set to high +	 * and an external pull-up is connected. +	 */ +	sch_gpio_core_set(gc, gpio_num, val);  	return 0;  } @@ -178,8 +187,6 @@ static int sch_gpio_resume_direction_out(struct gpio_chip *gc,  	u8 curr_dirs;  	unsigned short offset, bit; -	sch_gpio_resume_set(gc, gpio_num, val); -  	offset = RGIO + gpio_num / 8;  	bit = gpio_num % 8; @@ -190,6 +197,17 @@ static int sch_gpio_resume_direction_out(struct gpio_chip *gc,  		outb(curr_dirs & ~(1 << bit), gpio_ba + offset);  	spin_unlock(&gpio_lock); + +	/* +	* according to the datasheet, writing to the level register has no +	* effect when GPIO is programmed as input. +	* Actually the the level register is read-only when configured as input. +	* Thus presetting the output level before switching to output is _NOT_ possible. +	* Hence we set the level after configuring the GPIO as output. +	* But we cannot prevent a short low pulse if direction is set to high +	* and an external pull-up is connected. +	*/ +	sch_gpio_resume_set(gc, gpio_num, val);  	return 0;  } diff --git a/drivers/gpio/gpio-sch311x.c b/drivers/gpio/gpio-sch311x.c new file mode 100644 index 00000000000..f942b80ee40 --- /dev/null +++ b/drivers/gpio/gpio-sch311x.c @@ -0,0 +1,440 @@ +/* + * GPIO driver for the SMSC SCH311x Super-I/O chips + * + * Copyright (C) 2013 Bruno Randolf <br1@einfach.org> + * + * SuperIO functions and chip detection: + * (c) Copyright 2008 Wim Van Sebroeck <wim@iguana.be>. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/gpio.h> +#include <linux/bitops.h> +#include <linux/io.h> + +#define DRV_NAME			"gpio-sch311x" + +#define SCH311X_GPIO_CONF_OUT		0x00 +#define SCH311X_GPIO_CONF_IN		0x01 +#define SCH311X_GPIO_CONF_INVERT	0x02 +#define SCH311X_GPIO_CONF_OPEN_DRAIN	0x80 + +#define SIO_CONFIG_KEY_ENTER		0x55 +#define SIO_CONFIG_KEY_EXIT		0xaa + +#define GP1				0x4b + +static int sch311x_ioports[] = { 0x2e, 0x4e, 0x162e, 0x164e }; + +static struct platform_device *sch311x_gpio_pdev; + +struct sch311x_pdev_data {		/* platform device data */ +	unsigned short runtime_reg;	/* runtime register base address */ +}; + +struct sch311x_gpio_block {		/* one GPIO block runtime data */ +	struct gpio_chip chip; +	unsigned short data_reg;	/* from definition below */ +	unsigned short *config_regs;	/* pointer to definition below */ +	unsigned short runtime_reg;	/* runtime register */ +	spinlock_t lock;		/* lock for this GPIO block */ +}; + +struct sch311x_gpio_priv {		/* driver private data */ +	struct sch311x_gpio_block blocks[6]; +}; + +struct sch311x_gpio_block_def {		/* register address definitions */ +	unsigned short data_reg; +	unsigned short config_regs[8]; +	unsigned short base; +}; + +/* Note: some GPIOs are not available, these are marked with 0x00 */ + +static struct sch311x_gpio_block_def sch311x_gpio_blocks[] = { +	{ +		.data_reg = 0x4b,	/* GP1 */ +		.config_regs = {0x23, 0x24, 0x25, 0x26, 0x27, 0x29, 0x2a, 0x2b}, +		.base = 10, +	}, +	{ +		.data_reg = 0x4c,	/* GP2 */ +		.config_regs = {0x00, 0x2c, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x32}, +		.base = 20, +	}, +	{ +		.data_reg = 0x4d,	/* GP3 */ +		.config_regs = {0x33, 0x34, 0x35, 0x36, 0x37, 0x00, 0x39, 0x3a}, +		.base = 30, +	}, +	{ +		.data_reg = 0x4e,	/* GP4 */ +		.config_regs = {0x3b, 0x00, 0x3d, 0x00, 0x6e, 0x6f, 0x72, 0x73}, +		.base = 40, +	}, +	{ +		.data_reg = 0x4f,	/* GP5 */ +		.config_regs = {0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46}, +		.base = 50, +	}, +	{ +		.data_reg = 0x50,	/* GP6 */ +		.config_regs = {0x47, 0x48, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59}, +		.base = 60, +	}, +}; + +static inline struct sch311x_gpio_block * +to_sch311x_gpio_block(struct gpio_chip *chip) +{ +	return container_of(chip, struct sch311x_gpio_block, chip); +} + + +/* + *	Super-IO functions + */ + +static inline int sch311x_sio_enter(int sio_config_port) +{ +	/* Don't step on other drivers' I/O space by accident. */ +	if (!request_muxed_region(sio_config_port, 2, DRV_NAME)) { +		pr_err(DRV_NAME "I/O address 0x%04x already in use\n", +		       sio_config_port); +		return -EBUSY; +	} + +	outb(SIO_CONFIG_KEY_ENTER, sio_config_port); +	return 0; +} + +static inline void sch311x_sio_exit(int sio_config_port) +{ +	outb(SIO_CONFIG_KEY_EXIT, sio_config_port); +	release_region(sio_config_port, 2); +} + +static inline int sch311x_sio_inb(int sio_config_port, int reg) +{ +	outb(reg, sio_config_port); +	return inb(sio_config_port + 1); +} + +static inline void sch311x_sio_outb(int sio_config_port, int reg, int val) +{ +	outb(reg, sio_config_port); +	outb(val, sio_config_port + 1); +} + + +/* + *	GPIO functions + */ + +static int sch311x_gpio_request(struct gpio_chip *chip, unsigned offset) +{ +	struct sch311x_gpio_block *block = to_sch311x_gpio_block(chip); + +	if (block->config_regs[offset] == 0) /* GPIO is not available */ +		return -ENODEV; + +	if (!request_region(block->runtime_reg + block->config_regs[offset], +			    1, DRV_NAME)) { +		dev_err(chip->dev, "Failed to request region 0x%04x.\n", +			block->runtime_reg + block->config_regs[offset]); +		return -EBUSY; +	} +	return 0; +} + +static void sch311x_gpio_free(struct gpio_chip *chip, unsigned offset) +{ +	struct sch311x_gpio_block *block = to_sch311x_gpio_block(chip); + +	if (block->config_regs[offset] == 0) /* GPIO is not available */ +		return; + +	release_region(block->runtime_reg + block->config_regs[offset], 1); +} + +static int sch311x_gpio_get(struct gpio_chip *chip, unsigned offset) +{ +	struct sch311x_gpio_block *block = to_sch311x_gpio_block(chip); +	unsigned char data; + +	spin_lock(&block->lock); +	data = inb(block->runtime_reg + block->data_reg); +	spin_unlock(&block->lock); + +	return !!(data & BIT(offset)); +} + +static void __sch311x_gpio_set(struct sch311x_gpio_block *block, +			       unsigned offset, int value) +{ +	unsigned char data = inb(block->runtime_reg + block->data_reg); +	if (value) +		data |= BIT(offset); +	else +		data &= ~BIT(offset); +	outb(data, block->runtime_reg + block->data_reg); +} + +static void sch311x_gpio_set(struct gpio_chip *chip, unsigned offset, +			     int value) +{ +	struct sch311x_gpio_block *block = to_sch311x_gpio_block(chip); + +	spin_lock(&block->lock); +	 __sch311x_gpio_set(block, offset, value); +	spin_unlock(&block->lock); +} + +static int sch311x_gpio_direction_in(struct gpio_chip *chip, unsigned offset) +{ +	struct sch311x_gpio_block *block = to_sch311x_gpio_block(chip); + +	spin_lock(&block->lock); +	outb(SCH311X_GPIO_CONF_IN, block->runtime_reg + +	     block->config_regs[offset]); +	spin_unlock(&block->lock); + +	return 0; +} + +static int sch311x_gpio_direction_out(struct gpio_chip *chip, unsigned offset, +				      int value) +{ +	struct sch311x_gpio_block *block = to_sch311x_gpio_block(chip); + +	spin_lock(&block->lock); + +	outb(SCH311X_GPIO_CONF_OUT, block->runtime_reg + +	     block->config_regs[offset]); + +	__sch311x_gpio_set(block, offset, value); + +	spin_unlock(&block->lock); +	return 0; +} + +static int sch311x_gpio_probe(struct platform_device *pdev) +{ +	struct sch311x_pdev_data *pdata = pdev->dev.platform_data; +	struct sch311x_gpio_priv *priv; +	struct sch311x_gpio_block *block; +	int err, i; + +	/* we can register all GPIO data registers at once */ +	if (!request_region(pdata->runtime_reg + GP1, 6, DRV_NAME)) { +		dev_err(&pdev->dev, "Failed to request region 0x%04x-0x%04x.\n", +			pdata->runtime_reg + GP1, pdata->runtime_reg + GP1 + 5); +		return -EBUSY; +	} + +	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); +	if (!priv) +		return -ENOMEM; + +	platform_set_drvdata(pdev, priv); + +	for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) { +		block = &priv->blocks[i]; + +		spin_lock_init(&block->lock); + +		block->chip.label = DRV_NAME; +		block->chip.owner = THIS_MODULE; +		block->chip.request = sch311x_gpio_request; +		block->chip.free = sch311x_gpio_free; +		block->chip.direction_input = sch311x_gpio_direction_in; +		block->chip.direction_output = sch311x_gpio_direction_out; +		block->chip.get = sch311x_gpio_get; +		block->chip.set = sch311x_gpio_set; +		block->chip.ngpio = 8; +		block->chip.dev = &pdev->dev; +		block->chip.base = sch311x_gpio_blocks[i].base; +		block->config_regs = sch311x_gpio_blocks[i].config_regs; +		block->data_reg = sch311x_gpio_blocks[i].data_reg; +		block->runtime_reg = pdata->runtime_reg; + +		err = gpiochip_add(&block->chip); +		if (err < 0) { +			dev_err(&pdev->dev, +				"Could not register gpiochip, %d\n", err); +			goto exit_err; +		} +		dev_info(&pdev->dev, +			 "SMSC SCH311x GPIO block %d registered.\n", i); +	} + +	return 0; + +exit_err: +	release_region(pdata->runtime_reg + GP1, 6); +	/* release already registered chips */ +	for (--i; i >= 0; i--) +		gpiochip_remove(&priv->blocks[i].chip); +	return err; +} + +static int sch311x_gpio_remove(struct platform_device *pdev) +{ +	struct sch311x_pdev_data *pdata = pdev->dev.platform_data; +	struct sch311x_gpio_priv *priv = platform_get_drvdata(pdev); +	int err, i; + +	release_region(pdata->runtime_reg + GP1, 6); + +	for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) { +		err = gpiochip_remove(&priv->blocks[i].chip); +		if (err) +			return err; +		dev_info(&pdev->dev, +			 "SMSC SCH311x GPIO block %d unregistered.\n", i); +	} +	return 0; +} + +static struct platform_driver sch311x_gpio_driver = { +	.driver.name	= DRV_NAME, +	.driver.owner	= THIS_MODULE, +	.probe		= sch311x_gpio_probe, +	.remove		= sch311x_gpio_remove, +}; + + +/* + *	Init & exit routines + */ + +static int __init sch311x_detect(int sio_config_port, unsigned short *addr) +{ +	int err = 0, reg; +	unsigned short base_addr; +	unsigned char dev_id; + +	err = sch311x_sio_enter(sio_config_port); +	if (err) +		return err; + +	/* Check device ID. */ +	reg = sch311x_sio_inb(sio_config_port, 0x20); +	switch (reg) { +	case 0x7c: /* SCH3112 */ +		dev_id = 2; +		break; +	case 0x7d: /* SCH3114 */ +		dev_id = 4; +		break; +	case 0x7f: /* SCH3116 */ +		dev_id = 6; +		break; +	default: +		err = -ENODEV; +		goto exit; +	} + +	/* Select logical device A (runtime registers) */ +	sch311x_sio_outb(sio_config_port, 0x07, 0x0a); + +	/* Check if Logical Device Register is currently active */ +	if ((sch311x_sio_inb(sio_config_port, 0x30) & 0x01) == 0) +		pr_info("Seems that LDN 0x0a is not active...\n"); + +	/* Get the base address of the runtime registers */ +	base_addr = (sch311x_sio_inb(sio_config_port, 0x60) << 8) | +			   sch311x_sio_inb(sio_config_port, 0x61); +	if (!base_addr) { +		pr_err("Base address not set\n"); +		err = -ENODEV; +		goto exit; +	} +	*addr = base_addr; + +	pr_info("Found an SMSC SCH311%d chip at 0x%04x\n", dev_id, base_addr); + +exit: +	sch311x_sio_exit(sio_config_port); +	return err; +} + +static int __init sch311x_gpio_pdev_add(const unsigned short addr) +{ +	struct sch311x_pdev_data pdata; +	int err; + +	pdata.runtime_reg = addr; + +	sch311x_gpio_pdev = platform_device_alloc(DRV_NAME, -1); +	if (!sch311x_gpio_pdev) +		return -ENOMEM; + +	err = platform_device_add_data(sch311x_gpio_pdev, +				       &pdata, sizeof(pdata)); +	if (err) { +		pr_err(DRV_NAME "Platform data allocation failed\n"); +		goto err; +	} + +	err = platform_device_add(sch311x_gpio_pdev); +	if (err) { +		pr_err(DRV_NAME "Device addition failed\n"); +		goto err; +	} +	return 0; + +err: +	platform_device_put(sch311x_gpio_pdev); +	return err; +} + +static int __init sch311x_gpio_init(void) +{ +	int err, i; +	unsigned short addr = 0; + +	for (i = 0; i < ARRAY_SIZE(sch311x_ioports); i++) +		if (sch311x_detect(sch311x_ioports[i], &addr) == 0) +			break; + +	if (!addr) +		return -ENODEV; + +	err = platform_driver_register(&sch311x_gpio_driver); +	if (err) +		return err; + +	err = sch311x_gpio_pdev_add(addr); +	if (err) +		goto unreg_platform_driver; + +	return 0; + +unreg_platform_driver: +	platform_driver_unregister(&sch311x_gpio_driver); +	return err; +} + +static void __exit sch311x_gpio_exit(void) +{ +	platform_device_unregister(sch311x_gpio_pdev); +	platform_driver_unregister(&sch311x_gpio_driver); +} + +module_init(sch311x_gpio_init); +module_exit(sch311x_gpio_exit); + +MODULE_AUTHOR("Bruno Randolf <br1@einfach.org>"); +MODULE_DESCRIPTION("SMSC SCH311x GPIO Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:gpio-sch311x"); diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c index 88f374ac775..7c6c518929b 100644 --- a/drivers/gpio/gpio-sodaville.c +++ b/drivers/gpio/gpio-sodaville.c @@ -176,8 +176,10 @@ static int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,  	sd->id = irq_domain_add_legacy(pdev->dev.of_node, SDV_NUM_PUB_GPIOS,  				sd->irq_base, 0, &irq_domain_sdv_ops, sd); -	if (!sd->id) +	if (!sd->id) { +		ret = -ENODEV;  		goto out_free_irq; +	}  	return 0;  out_free_irq:  	free_irq(pdev->irq, sd); @@ -212,8 +214,10 @@ static int sdv_gpio_probe(struct pci_dev *pdev,  	}  	addr = pci_resource_start(pdev, GPIO_BAR); -	if (!addr) +	if (!addr) { +		ret = -ENODEV;  		goto release_reg; +	}  	sd->gpio_pub_base = ioremap(addr, pci_resource_len(pdev, GPIO_BAR));  	prop = of_get_property(pdev->dev.of_node, "intel,muxctl", &len); @@ -270,7 +274,7 @@ static void sdv_gpio_remove(struct pci_dev *pdev)  	kfree(sd);  } -static DEFINE_PCI_DEVICE_TABLE(sdv_gpio_pci_ids) = { +static const struct pci_device_id sdv_gpio_pci_ids[] = {  	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_SDV_GPIO) },  	{ 0, },  }; diff --git a/drivers/gpio/gpio-spear-spics.c b/drivers/gpio/gpio-spear-spics.c index e9a0415834e..353263c85d2 100644 --- a/drivers/gpio/gpio-spear-spics.c +++ b/drivers/gpio/gpio-spear-spics.c @@ -2,7 +2,7 @@   * SPEAr platform SPI chipselect abstraction over gpiolib   *   * Copyright (C) 2012 ST Microelectronics - * Shiraz Hashim <shiraz.hashim@st.com> + * Shiraz Hashim <shiraz.linux.kernel@gmail.com>   *   * This file is licensed under the terms of the GNU General Public   * License version 2. This program is licensed "as is" without any @@ -129,10 +129,8 @@ static int spics_gpio_probe(struct platform_device *pdev)  	int ret;  	spics = devm_kzalloc(&pdev->dev, sizeof(*spics), GFP_KERNEL); -	if (!spics) { -		dev_err(&pdev->dev, "memory allocation fail\n"); +	if (!spics)  		return -ENOMEM; -	}  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	spics->base = devm_ioremap_resource(&pdev->dev, res); @@ -205,6 +203,6 @@ static int __init spics_gpio_init(void)  }  subsys_initcall(spics_gpio_init); -MODULE_AUTHOR("Shiraz Hashim <shiraz.hashim@st.com>"); +MODULE_AUTHOR("Shiraz Hashim <shiraz.linux.kernel@gmail.com>");  MODULE_DESCRIPTION("ST Microlectronics SPEAr SPI Chip Select Abstraction");  MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c index f2fb12c18da..68e3fcb1ace 100644 --- a/drivers/gpio/gpio-sta2x11.c +++ b/drivers/gpio/gpio-sta2x11.c @@ -146,7 +146,7 @@ static void gsta_gpio_setup(struct gsta_gpio *chip) /* called from probe */  	gpio->dbg_show = NULL;  	gpio->base = gpio_base;  	gpio->ngpio = GSTA_NR_GPIO; -	gpio->can_sleep = 0; +	gpio->can_sleep = false;  	gpio->to_irq = gsta_gpio_to_irq;  	/* diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index b33bad1bb4d..628b5849429 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c @@ -23,7 +23,8 @@  enum { REG_RE, REG_FE, REG_IE };  #define CACHE_NR_REGS	3 -#define CACHE_NR_BANKS	(STMPE_NR_GPIOS / 8) +/* No variant has more than 24 GPIOs */ +#define CACHE_NR_BANKS	(24 / 8)  struct stmpe_gpio {  	struct gpio_chip chip; @@ -31,8 +32,6 @@ struct stmpe_gpio {  	struct device *dev;  	struct mutex irq_lock;  	struct irq_domain *domain; - -	int irq_base;  	unsigned norequest_mask;  	/* Caches of interrupt control registers for bus_lock */ @@ -129,7 +128,7 @@ static struct gpio_chip template_chip = {  	.set			= stmpe_gpio_set,  	.to_irq			= stmpe_gpio_to_irq,  	.request		= stmpe_gpio_request, -	.can_sleep		= 1, +	.can_sleep		= true,  };  static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type) @@ -254,9 +253,10 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)  		while (stat) {  			int bit = __ffs(stat);  			int line = bank * 8 + bit; -			int virq = irq_find_mapping(stmpe_gpio->domain, line); +			int child_irq = irq_find_mapping(stmpe_gpio->domain, +							 line); -			handle_nested_irq(virq); +			handle_nested_irq(child_irq);  			stat &= ~(1 << bit);  		} @@ -271,7 +271,7 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)  	return IRQ_HANDLED;  } -static int stmpe_gpio_irq_map(struct irq_domain *d, unsigned int virq, +static int stmpe_gpio_irq_map(struct irq_domain *d, unsigned int irq,  			      irq_hw_number_t hwirq)  {  	struct stmpe_gpio *stmpe_gpio = d->host_data; @@ -279,26 +279,26 @@ static int stmpe_gpio_irq_map(struct irq_domain *d, unsigned int virq,  	if (!stmpe_gpio)  		return -EINVAL; -	irq_set_chip_data(hwirq, stmpe_gpio); -	irq_set_chip_and_handler(hwirq, &stmpe_gpio_irq_chip, +	irq_set_chip_data(irq, stmpe_gpio); +	irq_set_chip_and_handler(irq, &stmpe_gpio_irq_chip,  				 handle_simple_irq); -	irq_set_nested_thread(hwirq, 1); +	irq_set_nested_thread(irq, 1);  #ifdef CONFIG_ARM -	set_irq_flags(hwirq, IRQF_VALID); +	set_irq_flags(irq, IRQF_VALID);  #else -	irq_set_noprobe(hwirq); +	irq_set_noprobe(irq);  #endif  	return 0;  } -static void stmpe_gpio_irq_unmap(struct irq_domain *d, unsigned int virq) +static void stmpe_gpio_irq_unmap(struct irq_domain *d, unsigned int irq)  {  #ifdef CONFIG_ARM -	set_irq_flags(virq, 0); +	set_irq_flags(irq, 0);  #endif -	irq_set_chip_and_handler(virq, NULL, NULL); -	irq_set_chip_data(virq, NULL); +	irq_set_chip_and_handler(irq, NULL, NULL); +	irq_set_chip_data(irq, NULL);  }  static const struct irq_domain_ops stmpe_gpio_irq_simple_ops = { @@ -310,13 +310,8 @@ static const struct irq_domain_ops stmpe_gpio_irq_simple_ops = {  static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio,  		struct device_node *np)  { -	int base = 0; - -	if (!np) -		base = stmpe_gpio->irq_base; -  	stmpe_gpio->domain = irq_domain_add_simple(np, -				stmpe_gpio->chip.ngpio, base, +				stmpe_gpio->chip.ngpio, 0,  				&stmpe_gpio_irq_simple_ops, stmpe_gpio);  	if (!stmpe_gpio->domain) {  		dev_err(stmpe_gpio->dev, "failed to create irqdomain\n"); @@ -353,7 +348,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev)  #ifdef CONFIG_OF  	stmpe_gpio->chip.of_node = np;  #endif -	stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1; +	stmpe_gpio->chip.base = -1;  	if (pdata)  		stmpe_gpio->norequest_mask = pdata->norequest_mask; @@ -361,9 +356,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev)  		of_property_read_u32(np, "st,norequest-mask",  				&stmpe_gpio->norequest_mask); -	if (irq >= 0) -		stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0); -	else +	if (irq < 0)  		dev_info(&pdev->dev,  			"device configured in no-irq mode; "  			"irqs are not available\n"); diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c index d2983e9ad6a..b51ca9f5c14 100644 --- a/drivers/gpio/gpio-sx150x.c +++ b/drivers/gpio/gpio-sx150x.c @@ -22,7 +22,6 @@  #include <linux/module.h>  #include <linux/mutex.h>  #include <linux/slab.h> -#include <linux/workqueue.h>  #include <linux/i2c/sx150x.h>  #define NO_UPDATE_PENDING	-1 @@ -436,7 +435,7 @@ static void sx150x_init_chip(struct sx150x_chip *chip,  	chip->gpio_chip.set              = sx150x_gpio_set;  	chip->gpio_chip.to_irq           = sx150x_gpio_to_irq;  	chip->gpio_chip.base             = pdata->gpio_base; -	chip->gpio_chip.can_sleep        = 1; +	chip->gpio_chip.can_sleep        = true;  	chip->gpio_chip.ngpio            = chip->dev_cfg->ngpios;  	if (pdata->oscio_is_gpo)  		++chip->gpio_chip.ngpio; diff --git a/drivers/gpio/gpio-syscon.c b/drivers/gpio/gpio-syscon.c new file mode 100644 index 00000000000..b50fe129774 --- /dev/null +++ b/drivers/gpio/gpio-syscon.c @@ -0,0 +1,191 @@ +/* + *  SYSCON GPIO driver + * + *  Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/mfd/syscon.h> + +#define GPIO_SYSCON_FEAT_IN	BIT(0) +#define GPIO_SYSCON_FEAT_OUT	BIT(1) +#define GPIO_SYSCON_FEAT_DIR	BIT(2) + +/* SYSCON driver is designed to use 32-bit wide registers */ +#define SYSCON_REG_SIZE		(4) +#define SYSCON_REG_BITS		(SYSCON_REG_SIZE * 8) + +/** + * struct syscon_gpio_data - Configuration for the device. + * compatible:		SYSCON driver compatible string. + * flags:		Set of GPIO_SYSCON_FEAT_ flags: + *			GPIO_SYSCON_FEAT_IN:	GPIOs supports input, + *			GPIO_SYSCON_FEAT_OUT:	GPIOs supports output, + *			GPIO_SYSCON_FEAT_DIR:	GPIOs supports switch direction. + * bit_count:		Number of bits used as GPIOs. + * dat_bit_offset:	Offset (in bits) to the first GPIO bit. + * dir_bit_offset:	Optional offset (in bits) to the first bit to switch + *			GPIO direction (Used with GPIO_SYSCON_FEAT_DIR flag). + */ + +struct syscon_gpio_data { +	const char	*compatible; +	unsigned int	flags; +	unsigned int	bit_count; +	unsigned int	dat_bit_offset; +	unsigned int	dir_bit_offset; +}; + +struct syscon_gpio_priv { +	struct gpio_chip		chip; +	struct regmap			*syscon; +	const struct syscon_gpio_data	*data; +}; + +static inline struct syscon_gpio_priv *to_syscon_gpio(struct gpio_chip *chip) +{ +	return container_of(chip, struct syscon_gpio_priv, chip); +} + +static int syscon_gpio_get(struct gpio_chip *chip, unsigned offset) +{ +	struct syscon_gpio_priv *priv = to_syscon_gpio(chip); +	unsigned int val, offs = priv->data->dat_bit_offset + offset; +	int ret; + +	ret = regmap_read(priv->syscon, +			  (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, &val); +	if (ret) +		return ret; + +	return !!(val & BIT(offs % SYSCON_REG_BITS)); +} + +static void syscon_gpio_set(struct gpio_chip *chip, unsigned offset, int val) +{ +	struct syscon_gpio_priv *priv = to_syscon_gpio(chip); +	unsigned int offs = priv->data->dat_bit_offset + offset; + +	regmap_update_bits(priv->syscon, +			   (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, +			   BIT(offs % SYSCON_REG_BITS), +			   val ? BIT(offs % SYSCON_REG_BITS) : 0); +} + +static int syscon_gpio_dir_in(struct gpio_chip *chip, unsigned offset) +{ +	struct syscon_gpio_priv *priv = to_syscon_gpio(chip); + +	if (priv->data->flags & GPIO_SYSCON_FEAT_DIR) { +		unsigned int offs = priv->data->dir_bit_offset + offset; + +		regmap_update_bits(priv->syscon, +				   (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, +				   BIT(offs % SYSCON_REG_BITS), 0); +	} + +	return 0; +} + +static int syscon_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int val) +{ +	struct syscon_gpio_priv *priv = to_syscon_gpio(chip); + +	if (priv->data->flags & GPIO_SYSCON_FEAT_DIR) { +		unsigned int offs = priv->data->dir_bit_offset + offset; + +		regmap_update_bits(priv->syscon, +				   (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, +				   BIT(offs % SYSCON_REG_BITS), +				   BIT(offs % SYSCON_REG_BITS)); +	} + +	syscon_gpio_set(chip, offset, val); + +	return 0; +} + +static const struct syscon_gpio_data clps711x_mctrl_gpio = { +	/* ARM CLPS711X SYSFLG1 Bits 8-10 */ +	.compatible	= "cirrus,clps711x-syscon1", +	.flags		= GPIO_SYSCON_FEAT_IN, +	.bit_count	= 3, +	.dat_bit_offset	= 0x40 * 8 + 8, +}; + +static const struct of_device_id syscon_gpio_ids[] = { +	{ +		.compatible	= "cirrus,clps711x-mctrl-gpio", +		.data		= &clps711x_mctrl_gpio, +	}, +	{ } +}; +MODULE_DEVICE_TABLE(of, syscon_gpio_ids); + +static int syscon_gpio_probe(struct platform_device *pdev) +{ +	struct device *dev = &pdev->dev; +	const struct of_device_id *of_id = of_match_device(syscon_gpio_ids, dev); +	struct syscon_gpio_priv *priv; + +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +	if (!priv) +		return -ENOMEM; + +	priv->data = of_id->data; + +	priv->syscon = +		syscon_regmap_lookup_by_compatible(priv->data->compatible); +	if (IS_ERR(priv->syscon)) +		return PTR_ERR(priv->syscon); + +	priv->chip.dev = dev; +	priv->chip.owner = THIS_MODULE; +	priv->chip.label = dev_name(dev); +	priv->chip.base = -1; +	priv->chip.ngpio = priv->data->bit_count; +	priv->chip.get = syscon_gpio_get; +	if (priv->data->flags & GPIO_SYSCON_FEAT_IN) +		priv->chip.direction_input = syscon_gpio_dir_in; +	if (priv->data->flags & GPIO_SYSCON_FEAT_OUT) { +		priv->chip.set = syscon_gpio_set; +		priv->chip.direction_output = syscon_gpio_dir_out; +	} + +	platform_set_drvdata(pdev, priv); + +	return gpiochip_add(&priv->chip); +} + +static int syscon_gpio_remove(struct platform_device *pdev) +{ +	struct syscon_gpio_priv *priv = platform_get_drvdata(pdev); + +	return gpiochip_remove(&priv->chip); +} + +static struct platform_driver syscon_gpio_driver = { +	.driver	= { +		.name		= "gpio-syscon", +		.owner		= THIS_MODULE, +		.of_match_table	= syscon_gpio_ids, +	}, +	.probe	= syscon_gpio_probe, +	.remove	= syscon_gpio_remove, +}; +module_platform_driver(syscon_gpio_driver); + +MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>"); +MODULE_DESCRIPTION("SYSCON GPIO driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c new file mode 100644 index 00000000000..07bce97647a --- /dev/null +++ b/drivers/gpio/gpio-tb10x.c @@ -0,0 +1,329 @@ +/* Abilis Systems MODULE DESCRIPTION + * + * Copyright (C) Abilis Systems 2013 + * + * Authors: Sascha Leuenberger <sascha.leuenberger@abilis.com> + *          Christian Ruppert <christian.ruppert@abilis.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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/gpio.h> +#include <linux/slab.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/of_gpio.h> +#include <linux/spinlock.h> +#include <linux/bitops.h> +#include <linux/pinctrl/consumer.h> + +#define TB10X_GPIO_DIR_IN	(0x00000000) +#define TB10X_GPIO_DIR_OUT	(0x00000001) +#define OFFSET_TO_REG_DDR	(0x00) +#define OFFSET_TO_REG_DATA	(0x04) +#define OFFSET_TO_REG_INT_EN	(0x08) +#define OFFSET_TO_REG_CHANGE	(0x0C) +#define OFFSET_TO_REG_WRMASK	(0x10) +#define OFFSET_TO_REG_INT_TYPE	(0x14) + + +/** + * @spinlock: used for atomic read/modify/write of registers + * @base: register base address + * @domain: IRQ domain of GPIO generated interrupts managed by this controller + * @irq: Interrupt line of parent interrupt controller + * @gc: gpio_chip structure associated to this GPIO controller + */ +struct tb10x_gpio { +	spinlock_t spinlock; +	void __iomem *base; +	struct irq_domain *domain; +	int irq; +	struct gpio_chip gc; +}; + +static inline u32 tb10x_reg_read(struct tb10x_gpio *gpio, unsigned int offs) +{ +	return ioread32(gpio->base + offs); +} + +static inline void tb10x_reg_write(struct tb10x_gpio *gpio, unsigned int offs, +				u32 val) +{ +	iowrite32(val, gpio->base + offs); +} + +static inline void tb10x_set_bits(struct tb10x_gpio *gpio, unsigned int offs, +				u32 mask, u32 val) +{ +	u32 r; +	unsigned long flags; + +	spin_lock_irqsave(&gpio->spinlock, flags); + +	r = tb10x_reg_read(gpio, offs); +	r = (r & ~mask) | (val & mask); + +	tb10x_reg_write(gpio, offs, r); + +	spin_unlock_irqrestore(&gpio->spinlock, flags); +} + +static inline struct tb10x_gpio *to_tb10x_gpio(struct gpio_chip *chip) +{ +	return container_of(chip, struct tb10x_gpio, gc); +} + +static int tb10x_gpio_direction_in(struct gpio_chip *chip, unsigned offset) +{ +	struct tb10x_gpio *tb10x_gpio = to_tb10x_gpio(chip); +	int mask = BIT(offset); +	int val = TB10X_GPIO_DIR_IN << offset; + +	tb10x_set_bits(tb10x_gpio, OFFSET_TO_REG_DDR, mask, val); + +	return 0; +} + +static int tb10x_gpio_get(struct gpio_chip *chip, unsigned offset) +{ +	struct tb10x_gpio *tb10x_gpio = to_tb10x_gpio(chip); +	int val; + +	val = tb10x_reg_read(tb10x_gpio, OFFSET_TO_REG_DATA); + +	if (val & BIT(offset)) +		return 1; +	else +		return 0; +} + +static void tb10x_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ +	struct tb10x_gpio *tb10x_gpio = to_tb10x_gpio(chip); +	int mask = BIT(offset); +	int val = value << offset; + +	tb10x_set_bits(tb10x_gpio, OFFSET_TO_REG_DATA, mask, val); +} + +static int tb10x_gpio_direction_out(struct gpio_chip *chip, +					unsigned offset, int value) +{ +	struct tb10x_gpio *tb10x_gpio = to_tb10x_gpio(chip); +	int mask = BIT(offset); +	int val = TB10X_GPIO_DIR_OUT << offset; + +	tb10x_gpio_set(chip, offset, value); +	tb10x_set_bits(tb10x_gpio, OFFSET_TO_REG_DDR, mask, val); + +	return 0; +} + +static int tb10x_gpio_request(struct gpio_chip *chip, unsigned offset) +{ +	return pinctrl_request_gpio(chip->base + offset); +} + +static void tb10x_gpio_free(struct gpio_chip *chip, unsigned offset) +{ +	pinctrl_free_gpio(chip->base + offset); +} + +static int tb10x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ +	struct tb10x_gpio *tb10x_gpio = to_tb10x_gpio(chip); + +	return irq_create_mapping(tb10x_gpio->domain, offset); +} + +static int tb10x_gpio_irq_set_type(struct irq_data *data, unsigned int type) +{ +	if ((type & IRQF_TRIGGER_MASK) != IRQ_TYPE_EDGE_BOTH) { +		pr_err("Only (both) edge triggered interrupts supported.\n"); +		return -EINVAL; +	} + +	irqd_set_trigger_type(data, type); + +	return IRQ_SET_MASK_OK; +} + +static irqreturn_t tb10x_gpio_irq_cascade(int irq, void *data) +{ +	struct tb10x_gpio *tb10x_gpio = data; +	u32 r = tb10x_reg_read(tb10x_gpio, OFFSET_TO_REG_CHANGE); +	u32 m = tb10x_reg_read(tb10x_gpio, OFFSET_TO_REG_INT_EN); +	const unsigned long bits = r & m; +	int i; + +	for_each_set_bit(i, &bits, 32) +		generic_handle_irq(irq_find_mapping(tb10x_gpio->domain, i)); + +	return IRQ_HANDLED; +} + +static int tb10x_gpio_probe(struct platform_device *pdev) +{ +	struct tb10x_gpio *tb10x_gpio; +	struct resource *mem; +	struct device_node *dn = pdev->dev.of_node; +	int ret = -EBUSY; +	u32 ngpio; + +	if (!dn) +		return -EINVAL; + +	if (of_property_read_u32(dn, "abilis,ngpio", &ngpio)) +		return -EINVAL; + +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	if (!mem) { +		dev_err(&pdev->dev, "No memory resource defined.\n"); +		return -EINVAL; +	} + +	tb10x_gpio = devm_kzalloc(&pdev->dev, sizeof(*tb10x_gpio), GFP_KERNEL); +	if (tb10x_gpio == NULL) +		return -ENOMEM; + +	spin_lock_init(&tb10x_gpio->spinlock); + +	tb10x_gpio->base = devm_ioremap_resource(&pdev->dev, mem); +	if (IS_ERR(tb10x_gpio->base)) +		return PTR_ERR(tb10x_gpio->base); + +	tb10x_gpio->gc.label		= of_node_full_name(dn); +	tb10x_gpio->gc.dev		= &pdev->dev; +	tb10x_gpio->gc.owner		= THIS_MODULE; +	tb10x_gpio->gc.direction_input	= tb10x_gpio_direction_in; +	tb10x_gpio->gc.get		= tb10x_gpio_get; +	tb10x_gpio->gc.direction_output	= tb10x_gpio_direction_out; +	tb10x_gpio->gc.set		= tb10x_gpio_set; +	tb10x_gpio->gc.request		= tb10x_gpio_request; +	tb10x_gpio->gc.free		= tb10x_gpio_free; +	tb10x_gpio->gc.base		= -1; +	tb10x_gpio->gc.ngpio		= ngpio; +	tb10x_gpio->gc.can_sleep	= false; + + +	ret = gpiochip_add(&tb10x_gpio->gc); +	if (ret < 0) { +		dev_err(&pdev->dev, "Could not add gpiochip.\n"); +		goto fail_gpiochip_registration; +	} + +	platform_set_drvdata(pdev, tb10x_gpio); + +	if (of_find_property(dn, "interrupt-controller", NULL)) { +		struct irq_chip_generic *gc; + +		ret = platform_get_irq(pdev, 0); +		if (ret < 0) { +			dev_err(&pdev->dev, "No interrupt specified.\n"); +			goto fail_get_irq; +		} + +		tb10x_gpio->gc.to_irq	= tb10x_gpio_to_irq; +		tb10x_gpio->irq		= ret; + +		ret = devm_request_irq(&pdev->dev, ret, tb10x_gpio_irq_cascade, +				IRQF_TRIGGER_NONE | IRQF_SHARED, +				dev_name(&pdev->dev), tb10x_gpio); +		if (ret != 0) +			goto fail_request_irq; + +		tb10x_gpio->domain = irq_domain_add_linear(dn, +						tb10x_gpio->gc.ngpio, +						&irq_generic_chip_ops, NULL); +		if (!tb10x_gpio->domain) { +			ret = -ENOMEM; +			goto fail_irq_domain; +		} + +		ret = irq_alloc_domain_generic_chips(tb10x_gpio->domain, +				tb10x_gpio->gc.ngpio, 1, tb10x_gpio->gc.label, +				handle_edge_irq, IRQ_NOREQUEST, IRQ_NOPROBE, +				IRQ_GC_INIT_MASK_CACHE); +		if (ret) +			goto fail_irq_domain; + +		gc = tb10x_gpio->domain->gc->gc[0]; +		gc->reg_base                         = tb10x_gpio->base; +		gc->chip_types[0].type               = IRQ_TYPE_EDGE_BOTH; +		gc->chip_types[0].chip.irq_ack       = irq_gc_ack_set_bit; +		gc->chip_types[0].chip.irq_mask      = irq_gc_mask_clr_bit; +		gc->chip_types[0].chip.irq_unmask    = irq_gc_mask_set_bit; +		gc->chip_types[0].chip.irq_set_type  = tb10x_gpio_irq_set_type; +		gc->chip_types[0].regs.ack           = OFFSET_TO_REG_CHANGE; +		gc->chip_types[0].regs.mask          = OFFSET_TO_REG_INT_EN; +	} + +	return 0; + +fail_irq_domain: +fail_request_irq: +fail_get_irq: +	gpiochip_remove(&tb10x_gpio->gc); +fail_gpiochip_registration: +fail_ioremap: +	return ret; +} + +static int __exit tb10x_gpio_remove(struct platform_device *pdev) +{ +	struct tb10x_gpio *tb10x_gpio = platform_get_drvdata(pdev); +	int ret; + +	if (tb10x_gpio->gc.to_irq) { +		irq_remove_generic_chip(tb10x_gpio->domain->gc->gc[0], +					BIT(tb10x_gpio->gc.ngpio) - 1, 0, 0); +		kfree(tb10x_gpio->domain->gc); +		irq_domain_remove(tb10x_gpio->domain); +		free_irq(tb10x_gpio->irq, tb10x_gpio); +	} +	ret = gpiochip_remove(&tb10x_gpio->gc); +	if (ret) +		return ret; + +	return 0; +} + +static const struct of_device_id tb10x_gpio_dt_ids[] = { +	{ .compatible = "abilis,tb10x-gpio" }, +	{ } +}; +MODULE_DEVICE_TABLE(of, tb10x_gpio_dt_ids); + +static struct platform_driver tb10x_gpio_driver = { +	.probe		= tb10x_gpio_probe, +	.remove		= tb10x_gpio_remove, +	.driver = { +		.name	= "tb10x-gpio", +		.of_match_table = tb10x_gpio_dt_ids, +		.owner	= THIS_MODULE, +	} +}; + +module_platform_driver(tb10x_gpio_driver); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("tb10x gpio."); +MODULE_VERSION("0.0.1"); diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c index 4a5de273c23..51f7cbd9ff7 100644 --- a/drivers/gpio/gpio-tc3589x.c +++ b/drivers/gpio/gpio-tc3589x.c @@ -12,8 +12,6 @@  #include <linux/slab.h>  #include <linux/gpio.h>  #include <linux/of.h> -#include <linux/irq.h> -#include <linux/irqdomain.h>  #include <linux/interrupt.h>  #include <linux/mfd/tc3589x.h> @@ -31,10 +29,6 @@ struct tc3589x_gpio {  	struct tc3589x *tc3589x;  	struct device *dev;  	struct mutex irq_lock; -	struct irq_domain *domain; - -	int irq_base; -  	/* Caches of interrupt control registers for bus_lock */  	u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];  	u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS]; @@ -95,30 +89,6 @@ static int tc3589x_gpio_direction_input(struct gpio_chip *chip,  	return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0);  } -/** - * tc3589x_gpio_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ - * - * @tc3589x_gpio: tc3589x_gpio_irq controller to operate on. - * @irq: index of the interrupt requested in the chip IRQs - * - * Useful for drivers to request their own IRQs. - */ -static int tc3589x_gpio_irq_get_virq(struct tc3589x_gpio *tc3589x_gpio, -				     int irq) -{ -	if (!tc3589x_gpio) -		return -EINVAL; - -	return irq_create_mapping(tc3589x_gpio->domain, irq); -} - -static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ -	struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); - -	return tc3589x_gpio_irq_get_virq(tc3589x_gpio, offset); -} -  static struct gpio_chip template_chip = {  	.label			= "tc3589x",  	.owner			= THIS_MODULE, @@ -126,13 +96,13 @@ static struct gpio_chip template_chip = {  	.get			= tc3589x_gpio_get,  	.direction_output	= tc3589x_gpio_direction_output,  	.set			= tc3589x_gpio_set, -	.to_irq			= tc3589x_gpio_to_irq, -	.can_sleep		= 1, +	.can_sleep		= true,  };  static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)  { -	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); +	struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +	struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);  	int offset = d->hwirq;  	int regoffset = offset / 8;  	int mask = 1 << (offset % 8); @@ -159,14 +129,16 @@ static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)  static void tc3589x_gpio_irq_lock(struct irq_data *d)  { -	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); +	struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +	struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);  	mutex_lock(&tc3589x_gpio->irq_lock);  }  static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)  { -	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); +	struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +	struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);  	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;  	static const u8 regmap[] = {  		[REG_IBE]	= TC3589x_GPIOIBE0, @@ -194,7 +166,8 @@ static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)  static void tc3589x_gpio_irq_mask(struct irq_data *d)  { -	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); +	struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +	struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);  	int offset = d->hwirq;  	int regoffset = offset / 8;  	int mask = 1 << (offset % 8); @@ -204,7 +177,8 @@ static void tc3589x_gpio_irq_mask(struct irq_data *d)  static void tc3589x_gpio_irq_unmask(struct irq_data *d)  { -	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); +	struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +	struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);  	int offset = d->hwirq;  	int regoffset = offset / 8;  	int mask = 1 << (offset % 8); @@ -242,9 +216,10 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)  		while (stat) {  			int bit = __ffs(stat);  			int line = i * 8 + bit; -			int virq = tc3589x_gpio_irq_get_virq(tc3589x_gpio, line); +			int irq = irq_find_mapping(tc3589x_gpio->chip.irqdomain, +						   line); -			handle_nested_irq(virq); +			handle_nested_irq(irq);  			stat &= ~(1 << bit);  		} @@ -254,61 +229,6 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)  	return IRQ_HANDLED;  } -static int tc3589x_gpio_irq_map(struct irq_domain *d, unsigned int virq, -				irq_hw_number_t hwirq) -{ -	struct tc3589x *tc3589x_gpio = d->host_data; - -	irq_set_chip_data(virq, tc3589x_gpio); -	irq_set_chip_and_handler(virq, &tc3589x_gpio_irq_chip, -				handle_simple_irq); -	irq_set_nested_thread(virq, 1); -#ifdef CONFIG_ARM -	set_irq_flags(virq, IRQF_VALID); -#else -	irq_set_noprobe(virq); -#endif - -	return 0; -} - -static void tc3589x_gpio_irq_unmap(struct irq_domain *d, unsigned int virq) -{ -#ifdef CONFIG_ARM -	set_irq_flags(virq, 0); -#endif -	irq_set_chip_and_handler(virq, NULL, NULL); -	irq_set_chip_data(virq, NULL); -} - -static struct irq_domain_ops tc3589x_irq_ops = { -	.map    = tc3589x_gpio_irq_map, -	.unmap  = tc3589x_gpio_irq_unmap, -	.xlate  = irq_domain_xlate_twocell, -}; - -static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio, -				struct device_node *np) -{ -	int base = tc3589x_gpio->irq_base; - -	/* -	 * If this results in a linear domain, irq_create_mapping() will -	 * take care of allocating IRQ descriptors at runtime. When a base -	 * is provided, the IRQ descriptors will be allocated when the -	 * domain is instantiated. -	 */ -	tc3589x_gpio->domain = irq_domain_add_simple(np, -			tc3589x_gpio->chip.ngpio, base, &tc3589x_irq_ops, -			tc3589x_gpio); -	if (!tc3589x_gpio->domain) { -		dev_err(tc3589x_gpio->dev, "Failed to create irqdomain\n"); -		return -ENOSYS; -	} - -	return 0; -} -  static int tc3589x_gpio_probe(struct platform_device *pdev)  {  	struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent); @@ -329,7 +249,8 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)  	if (irq < 0)  		return irq; -	tc3589x_gpio = kzalloc(sizeof(struct tc3589x_gpio), GFP_KERNEL); +	tc3589x_gpio = devm_kzalloc(&pdev->dev, sizeof(struct tc3589x_gpio), +				    GFP_KERNEL);  	if (!tc3589x_gpio)  		return -ENOMEM; @@ -347,30 +268,36 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)  	tc3589x_gpio->chip.of_node = np;  #endif -	tc3589x_gpio->irq_base = tc3589x->irq_base ? -		tc3589x->irq_base + TC3589x_INT_GPIO(0) : 0; -  	/* Bring the GPIO module out of reset */  	ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL,  			       TC3589x_RSTCTRL_GPIRST, 0);  	if (ret < 0) -		goto out_free; - -	ret = tc3589x_gpio_irq_init(tc3589x_gpio, np); -	if (ret) -		goto out_free; +		return ret; -	ret = request_threaded_irq(irq, NULL, tc3589x_gpio_irq, IRQF_ONESHOT, -				   "tc3589x-gpio", tc3589x_gpio); +	ret = devm_request_threaded_irq(&pdev->dev, +					irq, NULL, tc3589x_gpio_irq, +					IRQF_ONESHOT, "tc3589x-gpio", +					tc3589x_gpio);  	if (ret) {  		dev_err(&pdev->dev, "unable to get irq: %d\n", ret); -		goto out_free; +		return ret;  	}  	ret = gpiochip_add(&tc3589x_gpio->chip);  	if (ret) {  		dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); -		goto out_freeirq; +		return ret; +	} + +	ret =  gpiochip_irqchip_add(&tc3589x_gpio->chip, +				    &tc3589x_gpio_irq_chip, +				    0, +				    handle_simple_irq, +				    IRQ_TYPE_NONE); +	if (ret) { +		dev_err(&pdev->dev, +			"could not connect irqchip to gpiochip\n"); +		return ret;  	}  	if (pdata && pdata->setup) @@ -379,12 +306,6 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, tc3589x_gpio);  	return 0; - -out_freeirq: -	free_irq(irq, tc3589x_gpio); -out_free: -	kfree(tc3589x_gpio); -	return ret;  }  static int tc3589x_gpio_remove(struct platform_device *pdev) @@ -392,7 +313,6 @@ static int tc3589x_gpio_remove(struct platform_device *pdev)  	struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);  	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;  	struct tc3589x_gpio_platform_data *pdata = tc3589x->pdata->gpio; -	int irq = platform_get_irq(pdev, 0);  	int ret;  	if (pdata && pdata->remove) @@ -405,10 +325,6 @@ static int tc3589x_gpio_remove(struct platform_device *pdev)  		return ret;  	} -	free_irq(irq, tc3589x_gpio); - -	kfree(tc3589x_gpio); -  	return 0;  } diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 9a62672f1be..4e8fb8261a8 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -75,6 +75,7 @@ struct tegra_gpio_bank {  #endif  }; +static struct device *dev;  static struct irq_domain *irq_domain;  static void __iomem *regs;  static u32 tegra_gpio_bank_count; @@ -205,6 +206,7 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)  	int lvl_type;  	int val;  	unsigned long flags; +	int ret;  	switch (type & IRQ_TYPE_SENSE_MASK) {  	case IRQ_TYPE_EDGE_RISING: @@ -231,6 +233,12 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)  		return -EINVAL;  	} +	ret = gpio_lock_as_irq(&tegra_gpio_chip, gpio); +	if (ret) { +		dev_err(dev, "unable to lock Tegra GPIO %d as IRQ\n", gpio); +		return ret; +	} +  	spin_lock_irqsave(&bank->lvl_lock[port], flags);  	val = tegra_gpio_readl(GPIO_INT_LVL(gpio)); @@ -251,6 +259,13 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)  	return 0;  } +static void tegra_gpio_irq_shutdown(struct irq_data *d) +{ +	int gpio = d->hwirq; + +	gpio_unlock_as_irq(&tegra_gpio_chip, gpio); +} +  static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  {  	struct tegra_gpio_bank *bank; @@ -368,6 +383,7 @@ static struct irq_chip tegra_gpio_irq_chip = {  	.irq_mask	= tegra_gpio_irq_mask,  	.irq_unmask	= tegra_gpio_irq_unmask,  	.irq_set_type	= tegra_gpio_irq_set_type, +	.irq_shutdown	= tegra_gpio_irq_shutdown,  #ifdef CONFIG_PM_SLEEP  	.irq_set_wake	= tegra_gpio_irq_set_wake,  #endif @@ -392,7 +408,7 @@ static struct tegra_gpio_soc_config tegra30_gpio_config = {  	.upper_offset = 0x80,  }; -static struct of_device_id tegra_gpio_of_match[] = { +static const struct of_device_id tegra_gpio_of_match[] = {  	{ .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config },  	{ .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config },  	{ }, @@ -409,10 +425,13 @@ static int tegra_gpio_probe(struct platform_device *pdev)  	struct tegra_gpio_soc_config *config;  	struct resource *res;  	struct tegra_gpio_bank *bank; +	int ret;  	int gpio;  	int i;  	int j; +	dev = &pdev->dev; +  	match = of_match_device(tegra_gpio_of_match, &pdev->dev);  	if (!match) {  		dev_err(&pdev->dev, "Error: No device match found\n"); @@ -439,10 +458,8 @@ static int tegra_gpio_probe(struct platform_device *pdev)  	tegra_gpio_banks = devm_kzalloc(&pdev->dev,  			tegra_gpio_bank_count * sizeof(*tegra_gpio_banks),  			GFP_KERNEL); -	if (!tegra_gpio_banks) { -		dev_err(&pdev->dev, "Couldn't allocate bank structure\n"); +	if (!tegra_gpio_banks)  		return -ENODEV; -	}  	irq_domain = irq_domain_add_linear(pdev->dev.of_node,  					   tegra_gpio_chip.ngpio, @@ -476,7 +493,11 @@ static int tegra_gpio_probe(struct platform_device *pdev)  	tegra_gpio_chip.of_node = pdev->dev.of_node; -	gpiochip_add(&tegra_gpio_chip); +	ret = gpiochip_add(&tegra_gpio_chip); +	if (ret < 0) { +		irq_domain_remove(irq_domain); +		return ret; +	}  	for (gpio = 0; gpio < tegra_gpio_chip.ngpio; gpio++) {  		int irq = irq_create_mapping(irq_domain, gpio); diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index 7a0e956ef1e..efc7c129016 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -224,6 +224,7 @@ static struct irq_chip timbgpio_irqchip = {  static int timbgpio_probe(struct platform_device *pdev)  {  	int err, i; +	struct device *dev = &pdev->dev;  	struct gpio_chip *gc;  	struct timbgpio *tgpio;  	struct resource *iomem; @@ -231,35 +232,35 @@ static int timbgpio_probe(struct platform_device *pdev)  	int irq = platform_get_irq(pdev, 0);  	if (!pdata || pdata->nr_pins > 32) { -		err = -EINVAL; -		goto err_mem; +		dev_err(dev, "Invalid platform data\n"); +		return -EINVAL;  	}  	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!iomem) { -		err = -EINVAL; -		goto err_mem; +		dev_err(dev, "Unable to get resource\n"); +		return -EINVAL;  	} -	tgpio = kzalloc(sizeof(*tgpio), GFP_KERNEL); +	tgpio = devm_kzalloc(dev, sizeof(struct timbgpio), GFP_KERNEL);  	if (!tgpio) { -		err = -EINVAL; -		goto err_mem; +		dev_err(dev, "Memory alloc failed\n"); +		return -EINVAL;  	}  	tgpio->irq_base = pdata->irq_base;  	spin_lock_init(&tgpio->lock); -	if (!request_mem_region(iomem->start, resource_size(iomem), -		DRIVER_NAME)) { -		err = -EBUSY; -		goto err_request; +	if (!devm_request_mem_region(dev, iomem->start, resource_size(iomem), +				     DRIVER_NAME)) { +		dev_err(dev, "Region already claimed\n"); +		return -EBUSY;  	} -	tgpio->membase = ioremap(iomem->start, resource_size(iomem)); +	tgpio->membase = devm_ioremap(dev, iomem->start, resource_size(iomem));  	if (!tgpio->membase) { -		err = -ENOMEM; -		goto err_ioremap; +		dev_err(dev, "Cannot ioremap\n"); +		return -ENOMEM;  	}  	gc = &tgpio->gpio; @@ -275,11 +276,11 @@ static int timbgpio_probe(struct platform_device *pdev)  	gc->dbg_show = NULL;  	gc->base = pdata->gpio_base;  	gc->ngpio = pdata->nr_pins; -	gc->can_sleep = 0; +	gc->can_sleep = false;  	err = gpiochip_add(gc);  	if (err) -		goto err_chipadd; +		return err;  	platform_set_drvdata(pdev, tgpio); @@ -290,8 +291,8 @@ static int timbgpio_probe(struct platform_device *pdev)  		return 0;  	for (i = 0; i < pdata->nr_pins; i++) { -		irq_set_chip_and_handler_name(tgpio->irq_base + i, -			&timbgpio_irqchip, handle_simple_irq, "mux"); +		irq_set_chip_and_handler(tgpio->irq_base + i, +			&timbgpio_irqchip, handle_simple_irq);  		irq_set_chip_data(tgpio->irq_base + i, tgpio);  #ifdef CONFIG_ARM  		set_irq_flags(tgpio->irq_base + i, IRQF_VALID | IRQF_PROBE); @@ -302,17 +303,6 @@ static int timbgpio_probe(struct platform_device *pdev)  	irq_set_chained_handler(irq, timbgpio_irq);  	return 0; - -err_chipadd: -	iounmap(tgpio->membase); -err_ioremap: -	release_mem_region(iomem->start, resource_size(iomem)); -err_request: -	kfree(tgpio); -err_mem: -	printk(KERN_ERR DRIVER_NAME": Failed to register GPIOs: %d\n", err); - -	return err;  }  static int timbgpio_remove(struct platform_device *pdev) @@ -320,7 +310,6 @@ static int timbgpio_remove(struct platform_device *pdev)  	int err;  	struct timbgpio_platform_data *pdata = dev_get_platdata(&pdev->dev);  	struct timbgpio *tgpio = platform_get_drvdata(pdev); -	struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	int irq = platform_get_irq(pdev, 0);  	if (irq >= 0 && tgpio->irq_base > 0) { @@ -338,10 +327,6 @@ static int timbgpio_remove(struct platform_device *pdev)  	if (err)  		printk(KERN_ERR DRIVER_NAME": failed to remove gpio_chip\n"); -	iounmap(tgpio->membase); -	release_mem_region(iomem->start, resource_size(iomem)); -	kfree(tgpio); -  	return 0;  } diff --git a/drivers/gpio/gpio-tnetv107x.c b/drivers/gpio/gpio-tnetv107x.c deleted file mode 100644 index 3fa3e2867e1..00000000000 --- a/drivers/gpio/gpio-tnetv107x.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Texas Instruments TNETV107X GPIO Controller - * - * Copyright (C) 2010 Texas Instruments - * - * 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. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/gpio.h> - -#include <mach/common.h> -#include <mach/tnetv107x.h> - -struct tnetv107x_gpio_regs { -	u32	idver; -	u32	data_in[3]; -	u32	data_out[3]; -	u32	direction[3]; -	u32	enable[3]; -}; - -#define gpio_reg_index(gpio)	((gpio) >> 5) -#define gpio_reg_bit(gpio)	BIT((gpio) & 0x1f) - -#define gpio_reg_rmw(reg, mask, val)	\ -	__raw_writel((__raw_readl(reg) & ~(mask)) | (val), (reg)) - -#define gpio_reg_set_bit(reg, gpio)	\ -	gpio_reg_rmw((reg) + gpio_reg_index(gpio), 0, gpio_reg_bit(gpio)) - -#define gpio_reg_clear_bit(reg, gpio)	\ -	gpio_reg_rmw((reg) + gpio_reg_index(gpio), gpio_reg_bit(gpio), 0) - -#define gpio_reg_get_bit(reg, gpio)	\ -	(__raw_readl((reg) + gpio_reg_index(gpio)) & gpio_reg_bit(gpio)) - -#define chip2controller(chip)		\ -	container_of(chip, struct davinci_gpio_controller, chip) - -#define TNETV107X_GPIO_CTLRS	DIV_ROUND_UP(TNETV107X_N_GPIO, 32) - -static struct davinci_gpio_controller chips[TNETV107X_GPIO_CTLRS]; - -static int tnetv107x_gpio_request(struct gpio_chip *chip, unsigned offset) -{ -	struct davinci_gpio_controller *ctlr = chip2controller(chip); -	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; -	unsigned gpio = chip->base + offset; -	unsigned long flags; - -	spin_lock_irqsave(&ctlr->lock, flags); - -	gpio_reg_set_bit(regs->enable, gpio); - -	spin_unlock_irqrestore(&ctlr->lock, flags); - -	return 0; -} - -static void tnetv107x_gpio_free(struct gpio_chip *chip, unsigned offset) -{ -	struct davinci_gpio_controller *ctlr = chip2controller(chip); -	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; -	unsigned gpio = chip->base + offset; -	unsigned long flags; - -	spin_lock_irqsave(&ctlr->lock, flags); - -	gpio_reg_clear_bit(regs->enable, gpio); - -	spin_unlock_irqrestore(&ctlr->lock, flags); -} - -static int tnetv107x_gpio_dir_in(struct gpio_chip *chip, unsigned offset) -{ -	struct davinci_gpio_controller *ctlr = chip2controller(chip); -	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; -	unsigned gpio = chip->base + offset; -	unsigned long flags; - -	spin_lock_irqsave(&ctlr->lock, flags); - -	gpio_reg_set_bit(regs->direction, gpio); - -	spin_unlock_irqrestore(&ctlr->lock, flags); - -	return 0; -} - -static int tnetv107x_gpio_dir_out(struct gpio_chip *chip, -		unsigned offset, int value) -{ -	struct davinci_gpio_controller *ctlr = chip2controller(chip); -	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; -	unsigned gpio = chip->base + offset; -	unsigned long flags; - -	spin_lock_irqsave(&ctlr->lock, flags); - -	if (value) -		gpio_reg_set_bit(regs->data_out, gpio); -	else -		gpio_reg_clear_bit(regs->data_out, gpio); - -	gpio_reg_clear_bit(regs->direction, gpio); - -	spin_unlock_irqrestore(&ctlr->lock, flags); - -	return 0; -} - -static int tnetv107x_gpio_get(struct gpio_chip *chip, unsigned offset) -{ -	struct davinci_gpio_controller *ctlr = chip2controller(chip); -	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; -	unsigned gpio = chip->base + offset; -	int ret; - -	ret = gpio_reg_get_bit(regs->data_in, gpio); - -	return ret ? 1 : 0; -} - -static void tnetv107x_gpio_set(struct gpio_chip *chip, -		unsigned offset, int value) -{ -	struct davinci_gpio_controller *ctlr = chip2controller(chip); -	struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs; -	unsigned gpio = chip->base + offset; -	unsigned long flags; - -	spin_lock_irqsave(&ctlr->lock, flags); - -	if (value) -		gpio_reg_set_bit(regs->data_out, gpio); -	else -		gpio_reg_clear_bit(regs->data_out, gpio); - -	spin_unlock_irqrestore(&ctlr->lock, flags); -} - -static int __init tnetv107x_gpio_setup(void) -{ -	int i, base; -	unsigned ngpio; -	struct davinci_soc_info *soc_info = &davinci_soc_info; -	struct tnetv107x_gpio_regs *regs; -	struct davinci_gpio_controller *ctlr; - -	if (soc_info->gpio_type != GPIO_TYPE_TNETV107X) -		return 0; - -	ngpio = soc_info->gpio_num; -	if (ngpio == 0) { -		pr_err("GPIO setup:  how many GPIOs?\n"); -		return -EINVAL; -	} - -	if (WARN_ON(TNETV107X_N_GPIO < ngpio)) -		ngpio = TNETV107X_N_GPIO; - -	regs = ioremap(soc_info->gpio_base, SZ_4K); -	if (WARN_ON(!regs)) -		return -EINVAL; - -	for (i = 0, base = 0; base < ngpio; i++, base += 32) { -		ctlr = &chips[i]; - -		ctlr->chip.label	= "tnetv107x"; -		ctlr->chip.can_sleep	= 0; -		ctlr->chip.base		= base; -		ctlr->chip.ngpio	= ngpio - base; -		if (ctlr->chip.ngpio > 32) -			ctlr->chip.ngpio = 32; - -		ctlr->chip.request		= tnetv107x_gpio_request; -		ctlr->chip.free			= tnetv107x_gpio_free; -		ctlr->chip.direction_input	= tnetv107x_gpio_dir_in; -		ctlr->chip.get			= tnetv107x_gpio_get; -		ctlr->chip.direction_output	= tnetv107x_gpio_dir_out; -		ctlr->chip.set			= tnetv107x_gpio_set; - -		spin_lock_init(&ctlr->lock); - -		ctlr->regs	= regs; -		ctlr->set_data	= ®s->data_out[i]; -		ctlr->clr_data	= ®s->data_out[i]; -		ctlr->in_data	= ®s->data_in[i]; - -		gpiochip_add(&ctlr->chip); -	} - -	soc_info->gpio_ctlrs = chips; -	soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32); -	return 0; -} -pure_initcall(tnetv107x_gpio_setup); diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c index 29e8e750bd4..a69fbea4125 100644 --- a/drivers/gpio/gpio-tps6586x.c +++ b/drivers/gpio/gpio-tps6586x.c @@ -97,10 +97,8 @@ static int tps6586x_gpio_probe(struct platform_device *pdev)  	pdata = dev_get_platdata(pdev->dev.parent);  	tps6586x_gpio = devm_kzalloc(&pdev->dev,  				sizeof(*tps6586x_gpio), GFP_KERNEL); -	if (!tps6586x_gpio) { -		dev_err(&pdev->dev, "Could not allocate tps6586x_gpio\n"); +	if (!tps6586x_gpio)  		return -ENOMEM; -	}  	tps6586x_gpio->parent = pdev->dev.parent; @@ -108,7 +106,7 @@ static int tps6586x_gpio_probe(struct platform_device *pdev)  	tps6586x_gpio->gpio_chip.label = pdev->name;  	tps6586x_gpio->gpio_chip.dev = &pdev->dev;  	tps6586x_gpio->gpio_chip.ngpio = 4; -	tps6586x_gpio->gpio_chip.can_sleep = 1; +	tps6586x_gpio->gpio_chip.can_sleep = true;  	/* FIXME: add handling of GPIOs as dedicated inputs */  	tps6586x_gpio->gpio_chip.direction_output = tps6586x_gpio_output; diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c index 06146219d9d..e2f8cda235e 100644 --- a/drivers/gpio/gpio-tps65910.c +++ b/drivers/gpio/gpio-tps65910.c @@ -123,10 +123,8 @@ static int tps65910_gpio_probe(struct platform_device *pdev)  	tps65910_gpio = devm_kzalloc(&pdev->dev,  				sizeof(*tps65910_gpio), GFP_KERNEL); -	if (!tps65910_gpio) { -		dev_err(&pdev->dev, "Could not allocate tps65910_gpio\n"); +	if (!tps65910_gpio)  		return -ENOMEM; -	}  	tps65910_gpio->tps65910 = tps65910; @@ -143,7 +141,7 @@ static int tps65910_gpio_probe(struct platform_device *pdev)  	default:  		return -EINVAL;  	} -	tps65910_gpio->gpio_chip.can_sleep = 1; +	tps65910_gpio->gpio_chip.can_sleep = true;  	tps65910_gpio->gpio_chip.direction_input = tps65910_gpio_input;  	tps65910_gpio->gpio_chip.direction_output = tps65910_gpio_output;  	tps65910_gpio->gpio_chip.set	= tps65910_gpio_set; diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c index 276a4229b03..59ee486cb8b 100644 --- a/drivers/gpio/gpio-tps65912.c +++ b/drivers/gpio/gpio-tps65912.c @@ -79,7 +79,7 @@ static struct gpio_chip template_chip = {  	.direction_output	= tps65912_gpio_output,  	.get			= tps65912_gpio_get,  	.set			= tps65912_gpio_set, -	.can_sleep		= 1, +	.can_sleep		= true,  	.ngpio			= 5,  	.base			= -1,  }; diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c index d8e4f6efcb2..3ebb1a5ff22 100644 --- a/drivers/gpio/gpio-twl4030.c +++ b/drivers/gpio/gpio-twl4030.c @@ -139,7 +139,6 @@ static u8 cached_leden;  static void twl4030_led_set_value(int led, int value)  {  	u8 mask = LEDEN_LEDAON | LEDEN_LEDAPWM; -	int status;  	if (led)  		mask <<= 1; @@ -148,8 +147,9 @@ static void twl4030_led_set_value(int led, int value)  		cached_leden &= ~mask;  	else  		cached_leden |= mask; -	status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden, -				  TWL4030_LED_LEDEN_REG); + +	WARN_ON_ONCE(twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden, +				      TWL4030_LED_LEDEN_REG));  }  static int twl4030_set_gpio_direction(int gpio, int is_input) @@ -300,7 +300,7 @@ static int twl_direction_in(struct gpio_chip *chip, unsigned offset)  	if (offset < TWL4030_GPIO_MAX)  		ret = twl4030_set_gpio_direction(offset, 1);  	else -		ret = -EINVAL; +		ret = -EINVAL;	/* LED outputs can't be set as input */  	if (!ret)  		priv->direction &= ~BIT(offset); @@ -354,17 +354,27 @@ static void twl_set(struct gpio_chip *chip, unsigned offset, int value)  static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value)  {  	struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); +	int ret = 0;  	mutex_lock(&priv->mutex); -	if (offset < TWL4030_GPIO_MAX) -		twl4030_set_gpio_dataout(offset, value); +	if (offset < TWL4030_GPIO_MAX) { +		ret = twl4030_set_gpio_direction(offset, 0); +		if (ret) { +			mutex_unlock(&priv->mutex); +			return ret; +		} +	} + +	/* +	 *  LED gpios i.e. offset >= TWL4030_GPIO_MAX are always output +	 */  	priv->direction |= BIT(offset);  	mutex_unlock(&priv->mutex);  	twl_set(chip, offset, value); -	return 0; +	return ret;  }  static int twl_to_irq(struct gpio_chip *chip, unsigned offset) @@ -386,7 +396,7 @@ static struct gpio_chip template_chip = {  	.direction_output	= twl_direction_out,  	.set			= twl_set,  	.to_irq			= twl_to_irq, -	.can_sleep		= 1, +	.can_sleep		= true,  };  /*----------------------------------------------------------------------*/ @@ -435,7 +445,8 @@ static int gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)  static int gpio_twl4030_remove(struct platform_device *pdev); -static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev) +static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev, +				struct twl4030_gpio_platform_data *pdata)  {  	struct twl4030_gpio_platform_data *omap_twl_info; @@ -443,6 +454,9 @@ static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev)  	if (!omap_twl_info)  		return NULL; +	if (pdata) +		*omap_twl_info = *pdata; +  	omap_twl_info->use_leds = of_property_read_bool(dev->of_node,  			"ti,use-leds"); @@ -500,7 +514,7 @@ no_irqs:  	mutex_init(&priv->mutex);  	if (node) -		pdata = of_gpio_twl4030(&pdev->dev); +		pdata = of_gpio_twl4030(&pdev->dev, pdata);  	if (pdata == NULL) {  		dev_err(&pdev->dev, "Platform data is missing\n"); @@ -594,7 +608,7 @@ static struct platform_driver gpio_twl4030_driver = {  	.driver = {  		.name	= "twl4030_gpio",  		.owner	= THIS_MODULE, -		.of_match_table = of_match_ptr(twl_gpio_match), +		.of_match_table = twl_gpio_match,  	},  	.probe		= gpio_twl4030_probe,  	.remove		= gpio_twl4030_remove, diff --git a/drivers/gpio/gpio-twl6040.c b/drivers/gpio/gpio-twl6040.c index d420d30b86e..0caf5cd1b47 100644 --- a/drivers/gpio/gpio-twl6040.c +++ b/drivers/gpio/gpio-twl6040.c @@ -77,7 +77,7 @@ static struct gpio_chip twl6040gpo_chip = {  	.get			= twl6040gpo_get,  	.direction_output	= twl6040gpo_direction_out,  	.set			= twl6040gpo_set, -	.can_sleep		= 1, +	.can_sleep		= true,  };  /*----------------------------------------------------------------------*/ diff --git a/drivers/gpio/gpio-tz1090.c b/drivers/gpio/gpio-tz1090.c index 23e06139241..5246a60eff6 100644 --- a/drivers/gpio/gpio-tz1090.c +++ b/drivers/gpio/gpio-tz1090.c @@ -488,26 +488,26 @@ static int tz1090_gpio_bank_probe(struct tz1090_gpio_bank_info *info)  	gc->chip_types[0].handler		= handle_level_irq;  	gc->chip_types[0].regs.ack		= REG_GPIO_IRQ_STS;  	gc->chip_types[0].regs.mask		= REG_GPIO_IRQ_EN; -	gc->chip_types[0].chip.irq_startup	= gpio_startup_irq, -	gc->chip_types[0].chip.irq_ack		= irq_gc_ack_clr_bit, -	gc->chip_types[0].chip.irq_mask		= irq_gc_mask_clr_bit, -	gc->chip_types[0].chip.irq_unmask	= irq_gc_mask_set_bit, -	gc->chip_types[0].chip.irq_set_type	= gpio_set_irq_type, -	gc->chip_types[0].chip.irq_set_wake	= gpio_set_irq_wake, -	gc->chip_types[0].chip.flags		= IRQCHIP_MASK_ON_SUSPEND, +	gc->chip_types[0].chip.irq_startup	= gpio_startup_irq; +	gc->chip_types[0].chip.irq_ack		= irq_gc_ack_clr_bit; +	gc->chip_types[0].chip.irq_mask		= irq_gc_mask_clr_bit; +	gc->chip_types[0].chip.irq_unmask	= irq_gc_mask_set_bit; +	gc->chip_types[0].chip.irq_set_type	= gpio_set_irq_type; +	gc->chip_types[0].chip.irq_set_wake	= gpio_set_irq_wake; +	gc->chip_types[0].chip.flags		= IRQCHIP_MASK_ON_SUSPEND;  	/* edge chip type */  	gc->chip_types[1].type			= IRQ_TYPE_EDGE_BOTH;  	gc->chip_types[1].handler		= handle_edge_irq;  	gc->chip_types[1].regs.ack		= REG_GPIO_IRQ_STS;  	gc->chip_types[1].regs.mask		= REG_GPIO_IRQ_EN; -	gc->chip_types[1].chip.irq_startup	= gpio_startup_irq, -	gc->chip_types[1].chip.irq_ack		= irq_gc_ack_clr_bit, -	gc->chip_types[1].chip.irq_mask		= irq_gc_mask_clr_bit, -	gc->chip_types[1].chip.irq_unmask	= irq_gc_mask_set_bit, -	gc->chip_types[1].chip.irq_set_type	= gpio_set_irq_type, -	gc->chip_types[1].chip.irq_set_wake	= gpio_set_irq_wake, -	gc->chip_types[1].chip.flags		= IRQCHIP_MASK_ON_SUSPEND, +	gc->chip_types[1].chip.irq_startup	= gpio_startup_irq; +	gc->chip_types[1].chip.irq_ack		= irq_gc_ack_clr_bit; +	gc->chip_types[1].chip.irq_mask		= irq_gc_mask_clr_bit; +	gc->chip_types[1].chip.irq_unmask	= irq_gc_mask_set_bit; +	gc->chip_types[1].chip.irq_set_type	= gpio_set_irq_type; +	gc->chip_types[1].chip.irq_set_wake	= gpio_set_irq_wake; +	gc->chip_types[1].chip.flags		= IRQCHIP_MASK_ON_SUSPEND;  	/* Setup chained handler for this GPIO bank */  	irq_set_handler_data(bank->irq, bank); diff --git a/drivers/gpio/gpio-ucb1400.c b/drivers/gpio/gpio-ucb1400.c index 1a605f2a0f5..2445fe77117 100644 --- a/drivers/gpio/gpio-ucb1400.c +++ b/drivers/gpio/gpio-ucb1400.c @@ -64,7 +64,7 @@ static int ucb1400_gpio_probe(struct platform_device *dev)  	ucb->gc.direction_output = ucb1400_gpio_dir_out;  	ucb->gc.get = ucb1400_gpio_get;  	ucb->gc.set = ucb1400_gpio_set; -	ucb->gc.can_sleep = 1; +	ucb->gc.can_sleep = true;  	err = gpiochip_add(&ucb->gc);  	if (err) @@ -105,3 +105,4 @@ module_platform_driver(ucb1400_gpio_driver);  MODULE_DESCRIPTION("Philips UCB1400 GPIO driver");  MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:ucb1400_gpio"); diff --git a/drivers/gpio/gpio-viperboard.c b/drivers/gpio/gpio-viperboard.c index 5ac2919197f..79e3b583671 100644 --- a/drivers/gpio/gpio-viperboard.c +++ b/drivers/gpio/gpio-viperboard.c @@ -413,7 +413,7 @@ static int vprbrd_gpio_probe(struct platform_device *pdev)  	vb_gpio->gpioa.owner = THIS_MODULE;  	vb_gpio->gpioa.base = -1;  	vb_gpio->gpioa.ngpio = 16; -	vb_gpio->gpioa.can_sleep = 1; +	vb_gpio->gpioa.can_sleep = true;  	vb_gpio->gpioa.set = vprbrd_gpioa_set;  	vb_gpio->gpioa.get = vprbrd_gpioa_get;  	vb_gpio->gpioa.direction_input = vprbrd_gpioa_direction_input; @@ -430,7 +430,7 @@ static int vprbrd_gpio_probe(struct platform_device *pdev)  	vb_gpio->gpiob.owner = THIS_MODULE;  	vb_gpio->gpiob.base = -1;  	vb_gpio->gpiob.ngpio = 16; -	vb_gpio->gpiob.can_sleep = 1; +	vb_gpio->gpiob.can_sleep = true;  	vb_gpio->gpiob.set = vprbrd_gpiob_set;  	vb_gpio->gpiob.get = vprbrd_gpiob_get;  	vb_gpio->gpiob.direction_input = vprbrd_gpiob_direction_input; diff --git a/drivers/gpio/gpio-vr41xx.c b/drivers/gpio/gpio-vr41xx.c index 9902732a382..66cbcc108e6 100644 --- a/drivers/gpio/gpio-vr41xx.c +++ b/drivers/gpio/gpio-vr41xx.c @@ -81,6 +81,7 @@ static DEFINE_SPINLOCK(giu_lock);  static unsigned long giu_flags;  static void __iomem *giu_base; +static struct gpio_chip vr41xx_gpio_chip;  #define giu_read(offset)		readw(giu_base + (offset))  #define giu_write(offset, value)	writew((value), giu_base + (offset)) @@ -135,12 +136,31 @@ static void unmask_giuint_low(struct irq_data *d)  	giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq));  } +static unsigned int startup_giuint(struct irq_data *data) +{ +	if (gpio_lock_as_irq(&vr41xx_gpio_chip, data->hwirq)) +		dev_err(vr41xx_gpio_chip.dev, +			"unable to lock HW IRQ %lu for IRQ\n", +			data->hwirq); +	/* Satisfy the .enable semantics by unmasking the line */ +	unmask_giuint_low(data); +	return 0; +} + +static void shutdown_giuint(struct irq_data *data) +{ +	mask_giuint_low(data); +	gpio_unlock_as_irq(&vr41xx_gpio_chip, data->hwirq); +} +  static struct irq_chip giuint_low_irq_chip = {  	.name		= "GIUINTL",  	.irq_ack	= ack_giuint_low,  	.irq_mask	= mask_giuint_low,  	.irq_mask_ack	= mask_ack_giuint_low,  	.irq_unmask	= unmask_giuint_low, +	.irq_startup	= startup_giuint, +	.irq_shutdown	= shutdown_giuint,  };  static void ack_giuint_high(struct irq_data *d) diff --git a/drivers/gpio/gpio-vx855.c b/drivers/gpio/gpio-vx855.c index cddfa22edb4..0fd23b6a753 100644 --- a/drivers/gpio/gpio-vx855.c +++ b/drivers/gpio/gpio-vx855.c @@ -214,7 +214,7 @@ static void vx855gpio_gpio_setup(struct vx855_gpio *vg)  	c->dbg_show = NULL;  	c->base = 0;  	c->ngpio = NR_VX855_GP; -	c->can_sleep = 0; +	c->can_sleep = false;  	c->names = vx855gpio_names;  } diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c index 456000c5c45..b18a1a26425 100644 --- a/drivers/gpio/gpio-wm831x.c +++ b/drivers/gpio/gpio-wm831x.c @@ -240,7 +240,7 @@ static struct gpio_chip template_chip = {  	.to_irq			= wm831x_gpio_to_irq,  	.set_debounce		= wm831x_gpio_set_debounce,  	.dbg_show		= wm831x_gpio_dbg_show, -	.can_sleep		= 1, +	.can_sleep		= true,  };  static int wm831x_gpio_probe(struct platform_device *pdev) diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c index fc49154be7b..2487f9d575d 100644 --- a/drivers/gpio/gpio-wm8350.c +++ b/drivers/gpio/gpio-wm8350.c @@ -106,7 +106,7 @@ static struct gpio_chip template_chip = {  	.direction_output	= wm8350_gpio_direction_out,  	.set			= wm8350_gpio_set,  	.to_irq			= wm8350_gpio_to_irq, -	.can_sleep		= 1, +	.can_sleep		= true,  };  static int wm8350_gpio_probe(struct platform_device *pdev) diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c index a53dbdefc7e..d93b6b58167 100644 --- a/drivers/gpio/gpio-wm8994.c +++ b/drivers/gpio/gpio-wm8994.c @@ -242,7 +242,7 @@ static struct gpio_chip template_chip = {  	.set			= wm8994_gpio_set,  	.to_irq			= wm8994_gpio_to_irq,  	.dbg_show		= wm8994_gpio_dbg_show, -	.can_sleep		= 1, +	.can_sleep		= true,  };  static int wm8994_gpio_probe(struct platform_device *pdev) diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index 792a05ad464..12481867daf 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -289,7 +289,7 @@ static int xgpio_of_probe(struct device_node *np)  	return 0;  } -static struct of_device_id xgpio_of_match[] = { +static const struct of_device_id xgpio_of_match[] = {  	{ .compatible = "xlnx,xps-gpio-1.00.a", },  	{ /* end of list */ },  }; diff --git a/drivers/gpio/gpio-xtensa.c b/drivers/gpio/gpio-xtensa.c new file mode 100644 index 00000000000..7081304d679 --- /dev/null +++ b/drivers/gpio/gpio-xtensa.c @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2013 TangoTec 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 Xtensa LX4 GPIO32 Option + * + * Documentation: Xtensa LX4 Microprocessor Data Book, Section 2.22 + * + * GPIO32 is a standard optional extension to the Xtensa architecture core that + * provides preconfigured output and input ports for intra SoC signaling. The + * GPIO32 option is implemented as 32bit Tensilica Instruction Extension (TIE) + * output state called EXPSTATE, and 32bit input wire called IMPWIRE. This + * driver treats input and output states as two distinct devices. + * + * Access to GPIO32 specific instructions is controlled by the CPENABLE + * (Coprocessor Enable Bits) register. By default Xtensa Linux startup code + * disables access to all coprocessors. This driver sets the CPENABLE bit + * corresponding to GPIO32 before any GPIO32 specific instruction, and restores + * CPENABLE state after that. + * + * This driver is currently incompatible with SMP. The GPIO32 extension is not + * guaranteed to be available in all cores. Moreover, each core controls a + * different set of IO wires. A theoretical SMP aware version of this driver + * would need to have a per core workqueue to do the actual GPIO manipulation. + */ + +#include <linux/err.h> +#include <linux/module.h> +#include <linux/gpio.h> +#include <linux/bitops.h> +#include <linux/platform_device.h> + +#include <asm/coprocessor.h> /* CPENABLE read/write macros */ + +#ifndef XCHAL_CP_ID_XTIOP +#error GPIO32 option is not enabled for your xtensa core variant +#endif + +#if XCHAL_HAVE_CP + +static inline unsigned long enable_cp(unsigned long *cpenable) +{ +	unsigned long flags; + +	local_irq_save(flags); +	RSR_CPENABLE(*cpenable); +	WSR_CPENABLE(*cpenable | BIT(XCHAL_CP_ID_XTIOP)); + +	return flags; +} + +static inline void disable_cp(unsigned long flags, unsigned long cpenable) +{ +	WSR_CPENABLE(cpenable); +	local_irq_restore(flags); +} + +#else + +static inline unsigned long enable_cp(unsigned long *cpenable) +{ +	*cpenable = 0; /* avoid uninitialized value warning */ +	return 0; +} + +static inline void disable_cp(unsigned long flags, unsigned long cpenable) +{ +} + +#endif /* XCHAL_HAVE_CP */ + +static int xtensa_impwire_get_direction(struct gpio_chip *gc, unsigned offset) +{ +	return 1; /* input only */ +} + +static int xtensa_impwire_get_value(struct gpio_chip *gc, unsigned offset) +{ +	unsigned long flags, saved_cpenable; +	u32 impwire; + +	flags = enable_cp(&saved_cpenable); +	__asm__ __volatile__("read_impwire %0" : "=a" (impwire)); +	disable_cp(flags, saved_cpenable); + +	return !!(impwire & BIT(offset)); +} + +static void xtensa_impwire_set_value(struct gpio_chip *gc, unsigned offset, +				    int value) +{ +	BUG(); /* output only; should never be called */ +} + +static int xtensa_expstate_get_direction(struct gpio_chip *gc, unsigned offset) +{ +	return 0; /* output only */ +} + +static int xtensa_expstate_get_value(struct gpio_chip *gc, unsigned offset) +{ +	unsigned long flags, saved_cpenable; +	u32 expstate; + +	flags = enable_cp(&saved_cpenable); +	__asm__ __volatile__("rur.expstate %0" : "=a" (expstate)); +	disable_cp(flags, saved_cpenable); + +	return !!(expstate & BIT(offset)); +} + +static void xtensa_expstate_set_value(struct gpio_chip *gc, unsigned offset, +				     int value) +{ +	unsigned long flags, saved_cpenable; +	u32 mask = BIT(offset); +	u32 val = value ? BIT(offset) : 0; + +	flags = enable_cp(&saved_cpenable); +	__asm__ __volatile__("wrmsk_expstate %0, %1" +			     :: "a" (val), "a" (mask)); +	disable_cp(flags, saved_cpenable); +} + +static struct gpio_chip impwire_chip = { +	.label		= "impwire", +	.base		= -1, +	.ngpio		= 32, +	.get_direction	= xtensa_impwire_get_direction, +	.get		= xtensa_impwire_get_value, +	.set		= xtensa_impwire_set_value, +}; + +static struct gpio_chip expstate_chip = { +	.label		= "expstate", +	.base		= -1, +	.ngpio		= 32, +	.get_direction	= xtensa_expstate_get_direction, +	.get		= xtensa_expstate_get_value, +	.set		= xtensa_expstate_set_value, +}; + +static int xtensa_gpio_probe(struct platform_device *pdev) +{ +	int ret; + +	ret = gpiochip_add(&impwire_chip); +	if (ret) +		return ret; +	return gpiochip_add(&expstate_chip); +} + +static struct platform_driver xtensa_gpio_driver = { +	.driver		= { +		.name		= "xtensa-gpio", +		.owner		= THIS_MODULE, +	}, +	.probe		= xtensa_gpio_probe, +}; + +static int __init xtensa_gpio_init(void) +{ +	struct platform_device *pdev; + +	pdev = platform_device_register_simple("xtensa-gpio", 0, NULL, 0); +	if (IS_ERR(pdev)) +		return PTR_ERR(pdev); + +	return platform_driver_register(&xtensa_gpio_driver); +} +device_initcall(xtensa_gpio_init); + +MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); +MODULE_DESCRIPTION("Xtensa LX4 GPIO32 driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-zevio.c b/drivers/gpio/gpio-zevio.c new file mode 100644 index 00000000000..54e54e4cc6c --- /dev/null +++ b/drivers/gpio/gpio-zevio.c @@ -0,0 +1,224 @@ +/* + * 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> +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/bitops.h> +#include <linux/io.h> +#include <linux/of_device.h> +#include <linux/of_gpio.h> +#include <linux/slab.h> +#include <linux/gpio.h> + +/* + * Memory layout: + * This chip has four gpio sections, each controls 8 GPIOs. + * Bit 0 in section 0 is GPIO 0, bit 2 in section 1 is GPIO 10. + * Disclaimer: Reverse engineered! + * For more information refer to: + * http://hackspire.unsads.com/wiki/index.php/Memory-mapped_I/O_ports#90000000_-_General_Purpose_I.2FO_.28GPIO.29 + * + * 0x00-0x3F: Section 0 + *     +0x00: Masked interrupt status (read-only) + *     +0x04: R: Interrupt status W: Reset interrupt status + *     +0x08: R: Interrupt mask W: Mask interrupt + *     +0x0C: W: Unmask interrupt (write-only) + *     +0x10: Direction: I/O=1/0 + *     +0x14: Output + *     +0x18: Input (read-only) + *     +0x20: R: Level interrupt W: Set as level interrupt + * 0x40-0x7F: Section 1 + * 0x80-0xBF: Section 2 + * 0xC0-0xFF: Section 3 + */ + +#define ZEVIO_GPIO_SECTION_SIZE			0x40 + +/* Offsets to various registers */ +#define ZEVIO_GPIO_INT_MASKED_STATUS	0x00 +#define ZEVIO_GPIO_INT_STATUS		0x04 +#define ZEVIO_GPIO_INT_UNMASK		0x08 +#define ZEVIO_GPIO_INT_MASK		0x0C +#define ZEVIO_GPIO_DIRECTION		0x10 +#define ZEVIO_GPIO_OUTPUT		0x14 +#define ZEVIO_GPIO_INPUT			0x18 +#define ZEVIO_GPIO_INT_STICKY		0x20 + +#define to_zevio_gpio(chip) container_of(to_of_mm_gpio_chip(chip), \ +				struct zevio_gpio, chip) + +/* Bit number of GPIO in its section */ +#define ZEVIO_GPIO_BIT(gpio) (gpio&7) + +struct zevio_gpio { +	spinlock_t		lock; +	struct of_mm_gpio_chip	chip; +}; + +static inline u32 zevio_gpio_port_get(struct zevio_gpio *c, unsigned pin, +					unsigned port_offset) +{ +	unsigned section_offset = ((pin >> 3) & 3)*ZEVIO_GPIO_SECTION_SIZE; +	return readl(IOMEM(c->chip.regs + section_offset + port_offset)); +} + +static inline void zevio_gpio_port_set(struct zevio_gpio *c, unsigned pin, +					unsigned port_offset, u32 val) +{ +	unsigned section_offset = ((pin >> 3) & 3)*ZEVIO_GPIO_SECTION_SIZE; +	writel(val, IOMEM(c->chip.regs + section_offset + port_offset)); +} + +/* Functions for struct gpio_chip */ +static int zevio_gpio_get(struct gpio_chip *chip, unsigned pin) +{ +	struct zevio_gpio *controller = to_zevio_gpio(chip); +	u32 val, dir; + +	spin_lock(&controller->lock); +	dir = zevio_gpio_port_get(controller, pin, ZEVIO_GPIO_DIRECTION); +	if (dir & BIT(ZEVIO_GPIO_BIT(pin))) +		val = zevio_gpio_port_get(controller, pin, ZEVIO_GPIO_INPUT); +	else +		val = zevio_gpio_port_get(controller, pin, ZEVIO_GPIO_OUTPUT); +	spin_unlock(&controller->lock); + +	return (val >> ZEVIO_GPIO_BIT(pin)) & 0x1; +} + +static void zevio_gpio_set(struct gpio_chip *chip, unsigned pin, int value) +{ +	struct zevio_gpio *controller = to_zevio_gpio(chip); +	u32 val; + +	spin_lock(&controller->lock); +	val = zevio_gpio_port_get(controller, pin, ZEVIO_GPIO_OUTPUT); +	if (value) +		val |= BIT(ZEVIO_GPIO_BIT(pin)); +	else +		val &= ~BIT(ZEVIO_GPIO_BIT(pin)); + +	zevio_gpio_port_set(controller, pin, ZEVIO_GPIO_OUTPUT, val); +	spin_unlock(&controller->lock); +} + +static int zevio_gpio_direction_input(struct gpio_chip *chip, unsigned pin) +{ +	struct zevio_gpio *controller = to_zevio_gpio(chip); +	u32 val; + +	spin_lock(&controller->lock); + +	val = zevio_gpio_port_get(controller, pin, ZEVIO_GPIO_DIRECTION); +	val |= BIT(ZEVIO_GPIO_BIT(pin)); +	zevio_gpio_port_set(controller, pin, ZEVIO_GPIO_DIRECTION, val); + +	spin_unlock(&controller->lock); + +	return 0; +} + +static int zevio_gpio_direction_output(struct gpio_chip *chip, +				       unsigned pin, int value) +{ +	struct zevio_gpio *controller = to_zevio_gpio(chip); +	u32 val; + +	spin_lock(&controller->lock); +	val = zevio_gpio_port_get(controller, pin, ZEVIO_GPIO_OUTPUT); +	if (value) +		val |= BIT(ZEVIO_GPIO_BIT(pin)); +	else +		val &= ~BIT(ZEVIO_GPIO_BIT(pin)); + +	zevio_gpio_port_set(controller, pin, ZEVIO_GPIO_OUTPUT, val); +	val = zevio_gpio_port_get(controller, pin, ZEVIO_GPIO_DIRECTION); +	val &= ~BIT(ZEVIO_GPIO_BIT(pin)); +	zevio_gpio_port_set(controller, pin, ZEVIO_GPIO_DIRECTION, val); + +	spin_unlock(&controller->lock); + +	return 0; +} + +static int zevio_gpio_to_irq(struct gpio_chip *chip, unsigned pin) +{ +	/* +	 * TODO: Implement IRQs. +	 * Not implemented yet due to weird lockups +	 */ + +	return -ENXIO; +} + +static struct gpio_chip zevio_gpio_chip = { +	.direction_input	= zevio_gpio_direction_input, +	.direction_output	= zevio_gpio_direction_output, +	.set			= zevio_gpio_set, +	.get			= zevio_gpio_get, +	.to_irq			= zevio_gpio_to_irq, +	.base			= 0, +	.owner			= THIS_MODULE, +	.ngpio			= 32, +	.of_gpio_n_cells	= 2, +}; + +/* Initialization */ +static int zevio_gpio_probe(struct platform_device *pdev) +{ +	struct zevio_gpio *controller; +	int status, i; + +	controller = devm_kzalloc(&pdev->dev, sizeof(*controller), GFP_KERNEL); +	if (!controller) +		return -ENOMEM; + +	/* Copy our reference */ +	controller->chip.gc = zevio_gpio_chip; +	controller->chip.gc.dev = &pdev->dev; + +	status = of_mm_gpiochip_add(pdev->dev.of_node, &(controller->chip)); +	if (status) { +		dev_err(&pdev->dev, "failed to add gpiochip: %d\n", status); +		return status; +	} + +	spin_lock_init(&controller->lock); + +	/* Disable interrupts, they only cause errors */ +	for (i = 0; i < controller->chip.gc.ngpio; i += 8) +		zevio_gpio_port_set(controller, i, ZEVIO_GPIO_INT_MASK, 0xFF); + +	dev_dbg(controller->chip.gc.dev, "ZEVIO GPIO controller set up!\n"); + +	return 0; +} + +static const struct of_device_id zevio_gpio_of_match[] = { +	{ .compatible = "lsi,zevio-gpio", }, +	{ }, +}; + +MODULE_DEVICE_TABLE(of, zevio_gpio_of_match); + +static struct platform_driver zevio_gpio_driver = { +	.driver		= { +		.name	= "gpio-zevio", +		.owner	= THIS_MODULE, +		.of_match_table = zevio_gpio_of_match, +	}, +	.probe		= zevio_gpio_probe, +}; +module_platform_driver(zevio_gpio_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Fabian Vogt <fabian@ritter-vogt.de>"); +MODULE_DESCRIPTION("LSI ZEVIO SoC GPIO driver"); diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 5c1ef2b3ef1..4a987917c18 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -11,19 +11,40 @@   */  #include <linux/errno.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> +#include <linux/gpio/driver.h>  #include <linux/export.h> -#include <linux/acpi_gpio.h>  #include <linux/acpi.h>  #include <linux/interrupt.h> +#include <linux/mutex.h> -struct acpi_gpio_evt_pin { +#include "gpiolib.h" + +struct acpi_gpio_event {  	struct list_head node; -	acpi_handle *evt_handle; +	acpi_handle handle;  	unsigned int pin;  	unsigned int irq;  }; +struct acpi_gpio_connection { +	struct list_head node; +	struct gpio_desc *desc; +}; + +struct acpi_gpio_chip { +	/* +	 * ACPICA requires that the first field of the context parameter +	 * passed to acpi_install_address_space_handler() is large enough +	 * to hold struct acpi_connection_info. +	 */ +	struct acpi_connection_info conn_info; +	struct list_head conns; +	struct mutex conn_lock; +	struct gpio_chip *chip; +	struct list_head events; +}; +  static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)  {  	if (!gc->dev) @@ -33,14 +54,15 @@ static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)  }  /** - * acpi_get_gpio() - Translate ACPI GPIO pin to GPIO number usable with GPIO API + * acpi_get_gpiod() - Translate ACPI GPIO pin to GPIO descriptor usable with GPIO API   * @path:	ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1")   * @pin:	ACPI GPIO pin number (0-based, controller-relative)   * - * Returns GPIO number to use with Linux generic GPIO API, or errno error value + * Returns GPIO descriptor to use with Linux generic GPIO API, or ERR_PTR + * error value   */ -int acpi_get_gpio(char *path, int pin) +static struct gpio_desc *acpi_get_gpiod(char *path, int pin)  {  	struct gpio_chip *chip;  	acpi_handle handle; @@ -48,52 +70,158 @@ int acpi_get_gpio(char *path, int pin)  	status = acpi_get_handle(NULL, path, &handle);  	if (ACPI_FAILURE(status)) -		return -ENODEV; +		return ERR_PTR(-ENODEV);  	chip = gpiochip_find(handle, acpi_gpiochip_find);  	if (!chip) -		return -ENODEV; +		return ERR_PTR(-ENODEV); -	if (!gpio_is_valid(chip->base + pin)) -		return -EINVAL; +	if (pin < 0 || pin > chip->ngpio) +		return ERR_PTR(-EINVAL); -	return chip->base + pin; +	return gpiochip_get_desc(chip, pin);  } -EXPORT_SYMBOL_GPL(acpi_get_gpio);  static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)  { -	acpi_handle handle = data; +	struct acpi_gpio_event *event = data; -	acpi_evaluate_object(handle, NULL, NULL, NULL); +	acpi_evaluate_object(event->handle, NULL, NULL, NULL);  	return IRQ_HANDLED;  }  static irqreturn_t acpi_gpio_irq_handler_evt(int irq, void *data)  { -	struct acpi_gpio_evt_pin *evt_pin = data; -	struct acpi_object_list args; -	union acpi_object arg; - -	arg.type = ACPI_TYPE_INTEGER; -	arg.integer.value = evt_pin->pin; -	args.count = 1; -	args.pointer = &arg; +	struct acpi_gpio_event *event = data; -	acpi_evaluate_object(evt_pin->evt_handle, NULL, &args, NULL); +	acpi_execute_simple_method(event->handle, NULL, event->pin);  	return IRQ_HANDLED;  } -static void acpi_gpio_evt_dh(acpi_handle handle, void *data) +static void acpi_gpio_chip_dh(acpi_handle handle, void *data)  {  	/* The address of this function is used as a key. */  } +static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares, +						   void *context) +{ +	struct acpi_gpio_chip *acpi_gpio = context; +	struct gpio_chip *chip = acpi_gpio->chip; +	struct acpi_resource_gpio *agpio; +	acpi_handle handle, evt_handle; +	struct acpi_gpio_event *event; +	irq_handler_t handler = NULL; +	struct gpio_desc *desc; +	unsigned long irqflags; +	int ret, pin, irq; + +	if (ares->type != ACPI_RESOURCE_TYPE_GPIO) +		return AE_OK; + +	agpio = &ares->data.gpio; +	if (agpio->connection_type != ACPI_RESOURCE_GPIO_TYPE_INT) +		return AE_OK; + +	handle = ACPI_HANDLE(chip->dev); +	pin = agpio->pin_table[0]; + +	if (pin <= 255) { +		char ev_name[5]; +		sprintf(ev_name, "_%c%02X", +			agpio->triggering == ACPI_EDGE_SENSITIVE ? 'E' : 'L', +			pin); +		if (ACPI_SUCCESS(acpi_get_handle(handle, ev_name, &evt_handle))) +			handler = acpi_gpio_irq_handler; +	} +	if (!handler) { +		if (ACPI_SUCCESS(acpi_get_handle(handle, "_EVT", &evt_handle))) +			handler = acpi_gpio_irq_handler_evt; +	} +	if (!handler) +		return AE_BAD_PARAMETER; + +	desc = gpiochip_get_desc(chip, pin); +	if (IS_ERR(desc)) { +		dev_err(chip->dev, "Failed to get GPIO descriptor\n"); +		return AE_ERROR; +	} + +	ret = gpiochip_request_own_desc(desc, "ACPI:Event"); +	if (ret) { +		dev_err(chip->dev, "Failed to request GPIO\n"); +		return AE_ERROR; +	} + +	gpiod_direction_input(desc); + +	ret = gpiod_lock_as_irq(desc); +	if (ret) { +		dev_err(chip->dev, "Failed to lock GPIO as interrupt\n"); +		goto fail_free_desc; +	} + +	irq = gpiod_to_irq(desc); +	if (irq < 0) { +		dev_err(chip->dev, "Failed to translate GPIO to IRQ\n"); +		goto fail_unlock_irq; +	} + +	irqflags = IRQF_ONESHOT; +	if (agpio->triggering == ACPI_LEVEL_SENSITIVE) { +		if (agpio->polarity == ACPI_ACTIVE_HIGH) +			irqflags |= IRQF_TRIGGER_HIGH; +		else +			irqflags |= IRQF_TRIGGER_LOW; +	} else { +		switch (agpio->polarity) { +		case ACPI_ACTIVE_HIGH: +			irqflags |= IRQF_TRIGGER_RISING; +			break; +		case ACPI_ACTIVE_LOW: +			irqflags |= IRQF_TRIGGER_FALLING; +			break; +		default: +			irqflags |= IRQF_TRIGGER_RISING | +				    IRQF_TRIGGER_FALLING; +			break; +		} +	} + +	event = kzalloc(sizeof(*event), GFP_KERNEL); +	if (!event) +		goto fail_unlock_irq; + +	event->handle = evt_handle; +	event->irq = irq; +	event->pin = pin; + +	ret = request_threaded_irq(event->irq, NULL, handler, irqflags, +				   "ACPI:Event", event); +	if (ret) { +		dev_err(chip->dev, "Failed to setup interrupt handler for %d\n", +			event->irq); +		goto fail_free_event; +	} + +	list_add_tail(&event->node, &acpi_gpio->events); +	return AE_OK; + +fail_free_event: +	kfree(event); +fail_unlock_irq: +	gpiod_unlock_as_irq(desc); +fail_free_desc: +	gpiochip_free_own_desc(desc); + +	return AE_ERROR; +} +  /**   * acpi_gpiochip_request_interrupts() - Register isr for gpio chip ACPI events - * @chip:      gpio chip + * @acpi_gpio:      ACPI GPIO chip   *   * ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are   * handled by ACPI event methods which need to be called from the GPIO @@ -101,110 +229,51 @@ static void acpi_gpio_evt_dh(acpi_handle handle, void *data)   * gpio pins have acpi event methods and assigns interrupt handlers that calls   * the acpi event methods for those pins.   */ -void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) +static void acpi_gpiochip_request_interrupts(struct acpi_gpio_chip *acpi_gpio)  { -	struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; -	struct acpi_resource *res; -	acpi_handle handle, evt_handle; -	struct list_head *evt_pins = NULL; -	acpi_status status; -	unsigned int pin; -	int irq, ret; -	char ev_name[5]; +	struct gpio_chip *chip = acpi_gpio->chip; -	if (!chip->dev || !chip->to_irq) +	if (!chip->to_irq)  		return; -	handle = ACPI_HANDLE(chip->dev); -	if (!handle) -		return; - -	status = acpi_get_event_resources(handle, &buf); -	if (ACPI_FAILURE(status)) -		return; - -	status = acpi_get_handle(handle, "_EVT", &evt_handle); -	if (ACPI_SUCCESS(status)) { -		evt_pins = kzalloc(sizeof(*evt_pins), GFP_KERNEL); -		if (evt_pins) { -			INIT_LIST_HEAD(evt_pins); -			status = acpi_attach_data(handle, acpi_gpio_evt_dh, -						  evt_pins); -			if (ACPI_FAILURE(status)) { -				kfree(evt_pins); -				evt_pins = NULL; -			} -		} -	} - -	/* -	 * If a GPIO interrupt has an ACPI event handler method, or _EVT is -	 * present, set up an interrupt handler that calls the ACPI event -	 * handler. -	 */ -	for (res = buf.pointer; -	     res && (res->type != ACPI_RESOURCE_TYPE_END_TAG); -	     res = ACPI_NEXT_RESOURCE(res)) { -		irq_handler_t handler = NULL; -		void *data; - -		if (res->type != ACPI_RESOURCE_TYPE_GPIO || -		    res->data.gpio.connection_type != -		    ACPI_RESOURCE_GPIO_TYPE_INT) -			continue; - -		pin = res->data.gpio.pin_table[0]; -		if (pin > chip->ngpio) -			continue; - -		irq = chip->to_irq(chip, pin); -		if (irq < 0) -			continue; +	INIT_LIST_HEAD(&acpi_gpio->events); +	acpi_walk_resources(ACPI_HANDLE(chip->dev), "_AEI", +			    acpi_gpiochip_request_interrupt, acpi_gpio); +} -		if (pin <= 255) { -			acpi_handle ev_handle; +/** + * acpi_gpiochip_free_interrupts() - Free GPIO ACPI event interrupts. + * @acpi_gpio:      ACPI GPIO chip + * + * Free interrupts associated with GPIO ACPI event method for the given + * GPIO chip. + */ +static void acpi_gpiochip_free_interrupts(struct acpi_gpio_chip *acpi_gpio) +{ +	struct acpi_gpio_event *event, *ep; +	struct gpio_chip *chip = acpi_gpio->chip; -			sprintf(ev_name, "_%c%02X", -				res->data.gpio.triggering ? 'E' : 'L', pin); -			status = acpi_get_handle(handle, ev_name, &ev_handle); -			if (ACPI_SUCCESS(status)) { -				handler = acpi_gpio_irq_handler; -				data = ev_handle; -			} -		} -		if (!handler && evt_pins) { -			struct acpi_gpio_evt_pin *evt_pin; +	if (!chip->to_irq) +		return; -			evt_pin = kzalloc(sizeof(*evt_pin), GFP_KERNEL); -			if (!evt_pin) -				continue; +	list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) { +		struct gpio_desc *desc; -			list_add_tail(&evt_pin->node, evt_pins); -			evt_pin->evt_handle = evt_handle; -			evt_pin->pin = pin; -			evt_pin->irq = irq; -			handler = acpi_gpio_irq_handler_evt; -			data = evt_pin; -		} -		if (!handler) +		free_irq(event->irq, event); +		desc = gpiochip_get_desc(chip, event->pin); +		if (WARN_ON(IS_ERR(desc)))  			continue; - -		/* Assume BIOS sets the triggering, so no flags */ -		ret = devm_request_threaded_irq(chip->dev, irq, NULL, handler, -						0, "GPIO-signaled-ACPI-event", -						data); -		if (ret) -			dev_err(chip->dev, -				"Failed to request IRQ %d ACPI event handler\n", -				irq); +		gpiod_unlock_as_irq(desc); +		gpiochip_free_own_desc(desc); +		list_del(&event->node); +		kfree(event);  	}  } -EXPORT_SYMBOL(acpi_gpiochip_request_interrupts);  struct acpi_gpio_lookup {  	struct acpi_gpio_info info;  	int index; -	int gpio; +	struct gpio_desc *desc;  	int n;  }; @@ -215,37 +284,39 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)  	if (ares->type != ACPI_RESOURCE_TYPE_GPIO)  		return 1; -	if (lookup->n++ == lookup->index && lookup->gpio < 0) { +	if (lookup->n++ == lookup->index && !lookup->desc) {  		const struct acpi_resource_gpio *agpio = &ares->data.gpio; -		lookup->gpio = acpi_get_gpio(agpio->resource_source.string_ptr, -					     agpio->pin_table[0]); +		lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr, +					      agpio->pin_table[0]);  		lookup->info.gpioint =  			agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT; +		lookup->info.active_low = +			agpio->polarity == ACPI_ACTIVE_LOW;  	}  	return 1;  }  /** - * acpi_get_gpio_by_index() - get a GPIO number from device resources + * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources   * @dev: pointer to a device to get GPIO from   * @index: index of GpioIo/GpioInt resource (starting from %0)   * @info: info pointer to fill in (optional)   *   * Function goes through ACPI resources for @dev and based on @index looks - * up a GpioIo/GpioInt resource, translates it to the Linux GPIO number, + * up a GpioIo/GpioInt resource, translates it to the Linux GPIO descriptor,   * and returns it. @index matches GpioIo/GpioInt resources only so if there   * are total %3 GPIO resources, the index goes from %0 to %2.   * - * If the GPIO cannot be translated or there is an error, negative errno is + * If the GPIO cannot be translated or there is an error an ERR_PTR is   * returned.   *   * Note: if the GPIO resource has multiple entries in the pin list, this   * function only returns the first.   */ -int acpi_get_gpio_by_index(struct device *dev, int index, -			   struct acpi_gpio_info *info) +struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, +					  struct acpi_gpio_info *info)  {  	struct acpi_gpio_lookup lookup;  	struct list_head resource_list; @@ -254,65 +325,232 @@ int acpi_get_gpio_by_index(struct device *dev, int index,  	int ret;  	if (!dev) -		return -EINVAL; +		return ERR_PTR(-EINVAL);  	handle = ACPI_HANDLE(dev);  	if (!handle || acpi_bus_get_device(handle, &adev)) -		return -ENODEV; +		return ERR_PTR(-ENODEV);  	memset(&lookup, 0, sizeof(lookup));  	lookup.index = index; -	lookup.gpio = -ENODEV;  	INIT_LIST_HEAD(&resource_list);  	ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,  				     &lookup);  	if (ret < 0) -		return ret; +		return ERR_PTR(ret);  	acpi_dev_free_resource_list(&resource_list); -	if (lookup.gpio >= 0 && info) +	if (lookup.desc && info)  		*info = lookup.info; -	return lookup.gpio; +	return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT);  } -EXPORT_SYMBOL_GPL(acpi_get_gpio_by_index); -/** - * acpi_gpiochip_free_interrupts() - Free GPIO _EVT ACPI event interrupts. - * @chip:      gpio chip - * - * Free interrupts associated with the _EVT method for the given GPIO chip. - * - * The remaining ACPI event interrupts associated with the chip are freed - * automatically. - */ -void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) +static acpi_status +acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, +			    u32 bits, u64 *value, void *handler_context, +			    void *region_context) +{ +	struct acpi_gpio_chip *achip = region_context; +	struct gpio_chip *chip = achip->chip; +	struct acpi_resource_gpio *agpio; +	struct acpi_resource *ares; +	acpi_status status; +	bool pull_up; +	int i; + +	status = acpi_buffer_to_resource(achip->conn_info.connection, +					 achip->conn_info.length, &ares); +	if (ACPI_FAILURE(status)) +		return status; + +	if (WARN_ON(ares->type != ACPI_RESOURCE_TYPE_GPIO)) { +		ACPI_FREE(ares); +		return AE_BAD_PARAMETER; +	} + +	agpio = &ares->data.gpio; +	pull_up = agpio->pin_config == ACPI_PIN_CONFIG_PULLUP; + +	if (WARN_ON(agpio->io_restriction == ACPI_IO_RESTRICT_INPUT && +	    function == ACPI_WRITE)) { +		ACPI_FREE(ares); +		return AE_BAD_PARAMETER; +	} + +	for (i = 0; i < agpio->pin_table_length; i++) { +		unsigned pin = agpio->pin_table[i]; +		struct acpi_gpio_connection *conn; +		struct gpio_desc *desc; +		bool found; + +		desc = gpiochip_get_desc(chip, pin); +		if (IS_ERR(desc)) { +			status = AE_ERROR; +			goto out; +		} + +		mutex_lock(&achip->conn_lock); + +		found = false; +		list_for_each_entry(conn, &achip->conns, node) { +			if (conn->desc == desc) { +				found = true; +				break; +			} +		} +		if (!found) { +			int ret; + +			ret = gpiochip_request_own_desc(desc, "ACPI:OpRegion"); +			if (ret) { +				status = AE_ERROR; +				mutex_unlock(&achip->conn_lock); +				goto out; +			} + +			switch (agpio->io_restriction) { +			case ACPI_IO_RESTRICT_INPUT: +				gpiod_direction_input(desc); +				break; +			case ACPI_IO_RESTRICT_OUTPUT: +				/* +				 * ACPI GPIO resources don't contain an +				 * initial value for the GPIO. Therefore we +				 * deduce that value from the pull field +				 * instead. If the pin is pulled up we +				 * assume default to be high, otherwise +				 * low. +				 */ +				gpiod_direction_output(desc, pull_up); +				break; +			default: +				/* +				 * Assume that the BIOS has configured the +				 * direction and pull accordingly. +				 */ +				break; +			} + +			conn = kzalloc(sizeof(*conn), GFP_KERNEL); +			if (!conn) { +				status = AE_NO_MEMORY; +				gpiochip_free_own_desc(desc); +				mutex_unlock(&achip->conn_lock); +				goto out; +			} + +			conn->desc = desc; +			list_add_tail(&conn->node, &achip->conns); +		} + +		mutex_unlock(&achip->conn_lock); + +		if (function == ACPI_WRITE) +			gpiod_set_raw_value_cansleep(desc, +						     !!((1 << i) & *value)); +		else +			*value |= (u64)gpiod_get_raw_value_cansleep(desc) << i; +	} + +out: +	ACPI_FREE(ares); +	return status; +} + +static void acpi_gpiochip_request_regions(struct acpi_gpio_chip *achip)  { +	struct gpio_chip *chip = achip->chip; +	acpi_handle handle = ACPI_HANDLE(chip->dev); +	acpi_status status; + +	INIT_LIST_HEAD(&achip->conns); +	mutex_init(&achip->conn_lock); +	status = acpi_install_address_space_handler(handle, ACPI_ADR_SPACE_GPIO, +						    acpi_gpio_adr_space_handler, +						    NULL, achip); +	if (ACPI_FAILURE(status)) +		dev_err(chip->dev, "Failed to install GPIO OpRegion handler\n"); +} + +static void acpi_gpiochip_free_regions(struct acpi_gpio_chip *achip) +{ +	struct gpio_chip *chip = achip->chip; +	acpi_handle handle = ACPI_HANDLE(chip->dev); +	struct acpi_gpio_connection *conn, *tmp; +	acpi_status status; + +	status = acpi_remove_address_space_handler(handle, ACPI_ADR_SPACE_GPIO, +						   acpi_gpio_adr_space_handler); +	if (ACPI_FAILURE(status)) { +		dev_err(chip->dev, "Failed to remove GPIO OpRegion handler\n"); +		return; +	} + +	list_for_each_entry_safe_reverse(conn, tmp, &achip->conns, node) { +		gpiochip_free_own_desc(conn->desc); +		list_del(&conn->node); +		kfree(conn); +	} +} + +void acpi_gpiochip_add(struct gpio_chip *chip) +{ +	struct acpi_gpio_chip *acpi_gpio;  	acpi_handle handle;  	acpi_status status; -	struct list_head *evt_pins; -	struct acpi_gpio_evt_pin *evt_pin, *ep; -	if (!chip->dev || !chip->to_irq) +	if (!chip || !chip->dev)  		return;  	handle = ACPI_HANDLE(chip->dev);  	if (!handle)  		return; -	status = acpi_get_data(handle, acpi_gpio_evt_dh, (void **)&evt_pins); -	if (ACPI_FAILURE(status)) +	acpi_gpio = kzalloc(sizeof(*acpi_gpio), GFP_KERNEL); +	if (!acpi_gpio) { +		dev_err(chip->dev, +			"Failed to allocate memory for ACPI GPIO chip\n");  		return; +	} + +	acpi_gpio->chip = chip; -	list_for_each_entry_safe_reverse(evt_pin, ep, evt_pins, node) { -		devm_free_irq(chip->dev, evt_pin->irq, evt_pin); -		list_del(&evt_pin->node); -		kfree(evt_pin); +	status = acpi_attach_data(handle, acpi_gpio_chip_dh, acpi_gpio); +	if (ACPI_FAILURE(status)) { +		dev_err(chip->dev, "Failed to attach ACPI GPIO chip\n"); +		kfree(acpi_gpio); +		return;  	} -	acpi_detach_data(handle, acpi_gpio_evt_dh); -	kfree(evt_pins); +	acpi_gpiochip_request_interrupts(acpi_gpio); +	acpi_gpiochip_request_regions(acpi_gpio); +} + +void acpi_gpiochip_remove(struct gpio_chip *chip) +{ +	struct acpi_gpio_chip *acpi_gpio; +	acpi_handle handle; +	acpi_status status; + +	if (!chip || !chip->dev) +		return; + +	handle = ACPI_HANDLE(chip->dev); +	if (!handle) +		return; + +	status = acpi_get_data(handle, acpi_gpio_chip_dh, (void **)&acpi_gpio); +	if (ACPI_FAILURE(status)) { +		dev_warn(chip->dev, "Failed to retrieve ACPI GPIO chip\n"); +		return; +	} + +	acpi_gpiochip_free_regions(acpi_gpio); +	acpi_gpiochip_free_interrupts(acpi_gpio); + +	acpi_detach_data(handle, acpi_gpio_chip_dh); +	kfree(acpi_gpio);  } -EXPORT_SYMBOL(acpi_gpiochip_free_interrupts); diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 0dfaf20e4da..af7e25c9a9a 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -12,22 +12,25 @@   */  #include <linux/device.h> +#include <linux/err.h>  #include <linux/errno.h>  #include <linux/module.h>  #include <linux/io.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h>  #include <linux/of.h>  #include <linux/of_address.h>  #include <linux/of_gpio.h>  #include <linux/pinctrl/pinctrl.h>  #include <linux/slab.h> +struct gpio_desc; +  /* Private data structure for of_gpiochip_find_and_xlate */  struct gg_data {  	enum of_gpio_flags *flags;  	struct of_phandle_args gpiospec; -	int out_gpio; +	struct gpio_desc *out_gpio;  };  /* Private function for resolving node pointer to gpio_chip */ @@ -45,28 +48,31 @@ static int of_gpiochip_find_and_xlate(struct gpio_chip *gc, void *data)  	if (ret < 0)  		return false; -	gg_data->out_gpio = ret + gc->base; +	gg_data->out_gpio = gpiochip_get_desc(gc, ret);  	return true;  }  /** - * of_get_named_gpio_flags() - Get a GPIO number and flags to use with GPIO API + * of_get_named_gpiod_flags() - Get a GPIO descriptor and flags for GPIO API   * @np:		device node to get GPIO from   * @propname:	property name containing gpio specifier(s)   * @index:	index of the GPIO   * @flags:	a flags pointer to fill in   * - * Returns GPIO number to use with Linux generic GPIO API, or one of the errno + * Returns GPIO descriptor to use with Linux GPIO API, or one of the errno   * value on the error condition. If @flags is not NULL the function also fills   * in flags for the GPIO.   */ -int of_get_named_gpio_flags(struct device_node *np, const char *propname, -			   int index, enum of_gpio_flags *flags) +struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, +		     const char *propname, int index, enum of_gpio_flags *flags)  {  	/* Return -EPROBE_DEFER to support probe() functions to be called  	 * later when the GPIO actually becomes available  	 */ -	struct gg_data gg_data = { .flags = flags, .out_gpio = -EPROBE_DEFER }; +	struct gg_data gg_data = { +		.flags = flags, +		.out_gpio = ERR_PTR(-EPROBE_DEFER) +	};  	int ret;  	/* .of_xlate might decide to not fill in the flags, so clear it. */ @@ -78,15 +84,30 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname,  	if (ret) {  		pr_debug("%s: can't parse gpios property of node '%s[%d]'\n",  			__func__, np->full_name, index); -		return ret; +		return ERR_PTR(ret);  	}  	gpiochip_find(&gg_data, of_gpiochip_find_and_xlate);  	of_node_put(gg_data.gpiospec.np); -	pr_debug("%s exited with status %d\n", __func__, gg_data.out_gpio); +	pr_debug("%s exited with status %d\n", __func__, +		 PTR_ERR_OR_ZERO(gg_data.out_gpio));  	return gg_data.out_gpio;  } +EXPORT_SYMBOL(of_get_named_gpiod_flags); + +int of_get_named_gpio_flags(struct device_node *np, const char *list_name, +			    int index, enum of_gpio_flags *flags) +{ +	struct gpio_desc *desc; + +	desc = of_get_named_gpiod_flags(np, list_name, index, flags); + +	if (IS_ERR(desc)) +		return PTR_ERR(desc); +	else +		return desc_to_gpio(desc); +}  EXPORT_SYMBOL(of_get_named_gpio_flags);  /** @@ -190,10 +211,15 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)  	struct of_phandle_args pinspec;  	struct pinctrl_dev *pctldev;  	int index = 0, ret; +	const char *name; +	static const char group_names_propname[] = "gpio-ranges-group-names"; +	struct property *group_names;  	if (!np)  		return; +	group_names = of_find_property(np, group_names_propname, NULL); +  	for (;; index++) {  		ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3,  				index, &pinspec); @@ -204,14 +230,56 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)  		if (!pctldev)  			break; -		ret = gpiochip_add_pin_range(chip, -					     pinctrl_dev_get_devname(pctldev), -					     pinspec.args[0], -					     pinspec.args[1], -					     pinspec.args[2]); - -		if (ret) -			break; +		if (pinspec.args[2]) { +			if (group_names) { +				ret = of_property_read_string_index(np, +						group_names_propname, +						index, &name); +				if (strlen(name)) { +					pr_err("%s: Group name of numeric GPIO ranges must be the empty string.\n", +						np->full_name); +					break; +				} +			} +			/* npins != 0: linear range */ +			ret = gpiochip_add_pin_range(chip, +					pinctrl_dev_get_devname(pctldev), +					pinspec.args[0], +					pinspec.args[1], +					pinspec.args[2]); +			if (ret) +				break; +		} else { +			/* npins == 0: special range */ +			if (pinspec.args[1]) { +				pr_err("%s: Illegal gpio-range format.\n", +					np->full_name); +				break; +			} + +			if (!group_names) { +				pr_err("%s: GPIO group range requested but no %s property.\n", +					np->full_name, group_names_propname); +				break; +			} + +			ret = of_property_read_string_index(np, +						group_names_propname, +						index, &name); +			if (ret) +				break; + +			if (!strlen(name)) { +				pr_err("%s: Group name of GPIO group range cannot be the empty string.\n", +				np->full_name); +				break; +			} + +			ret = gpiochip_add_pingroup_range(chip, pctldev, +						pinspec.args[0], name); +			if (ret) +				break; +		}  	}  } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 86ef3461ec0..2ebc9071e35 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -12,20 +12,19 @@  #include <linux/of_gpio.h>  #include <linux/idr.h>  #include <linux/slab.h> +#include <linux/acpi.h> +#include <linux/gpio/driver.h> + +#include "gpiolib.h"  #define CREATE_TRACE_POINTS  #include <trace/events/gpio.h> -/* Optional implementation infrastructure for GPIO interfaces. - * - * Platforms may want to use this if they tend to use very many GPIOs - * that aren't part of a System-On-Chip core; or across I2C/SPI/etc. +/* Implementation infrastructure for GPIO interfaces.   * - * When kernel footprint or instruction count is an issue, simpler - * implementations may be preferred.  The GPIO programming interface - * allows for inlining speed-critical get/set operations for common - * cases, so that access to SOC-integrated GPIOs can sometimes cost - * only an instruction or two per bit. + * The GPIO programming interface allows for inlining speed-critical + * get/set operations for common cases, so that access to SOC-integrated + * GPIOs can sometimes cost only an instruction or two per bit.   */ @@ -57,9 +56,10 @@ struct gpio_desc {  #define FLAG_SYSFS	3	/* exported via /sys/class/gpio/control */  #define FLAG_TRIG_FALL	4	/* trigger on falling edge */  #define FLAG_TRIG_RISE	5	/* trigger on rising edge */ -#define FLAG_ACTIVE_LOW	6	/* sysfs value has active low */ +#define FLAG_ACTIVE_LOW	6	/* value has active low */  #define FLAG_OPEN_DRAIN	7	/* Gpio is open drain type */  #define FLAG_OPEN_SOURCE 8	/* Gpio is open source type */ +#define FLAG_USED_AS_IRQ 9	/* GPIO is connected to an IRQ */  #define ID_SHIFT	16	/* add new flags before this one */ @@ -74,34 +74,67 @@ static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];  #define GPIO_OFFSET_VALID(chip, offset) (offset >= 0 && offset < chip->ngpio) +static DEFINE_MUTEX(gpio_lookup_lock); +static LIST_HEAD(gpio_lookup_list);  static LIST_HEAD(gpio_chips);  #ifdef CONFIG_GPIO_SYSFS  static DEFINE_IDR(dirent_idr);  #endif -/* - * Internal gpiod_* API using descriptors instead of the integer namespace. - * Most of this should eventually go public. - */  static int gpiod_request(struct gpio_desc *desc, const char *label);  static void gpiod_free(struct gpio_desc *desc); -static int gpiod_direction_input(struct gpio_desc *desc); -static int gpiod_direction_output(struct gpio_desc *desc, int value); -static int gpiod_get_direction(const struct gpio_desc *desc); -static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce); -static int gpiod_get_value_cansleep(const struct gpio_desc *desc); -static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value); -static int gpiod_get_value(const struct gpio_desc *desc); -static void gpiod_set_value(struct gpio_desc *desc, int value); -static int gpiod_cansleep(const struct gpio_desc *desc); -static int gpiod_to_irq(const struct gpio_desc *desc); -static int gpiod_export(struct gpio_desc *desc, bool direction_may_change); -static int gpiod_export_link(struct device *dev, const char *name, -			     struct gpio_desc *desc); -static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value); -static void gpiod_unexport(struct gpio_desc *desc); +/* With descriptor prefix */ + +#ifdef CONFIG_DEBUG_FS +#define gpiod_emerg(desc, fmt, ...)					       \ +	pr_emerg("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\ +                 ##__VA_ARGS__) +#define gpiod_crit(desc, fmt, ...)					       \ +	pr_crit("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \ +                 ##__VA_ARGS__) +#define gpiod_err(desc, fmt, ...)					       \ +	pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",  \ +                 ##__VA_ARGS__) +#define gpiod_warn(desc, fmt, ...)					       \ +	pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \ +                 ##__VA_ARGS__) +#define gpiod_info(desc, fmt, ...)					       \ +	pr_info("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \ +                ##__VA_ARGS__) +#define gpiod_dbg(desc, fmt, ...)					       \ +	pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\ +                 ##__VA_ARGS__) +#else +#define gpiod_emerg(desc, fmt, ...)					\ +	pr_emerg("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) +#define gpiod_crit(desc, fmt, ...)					\ +	pr_crit("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) +#define gpiod_err(desc, fmt, ...)					\ +	pr_err("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) +#define gpiod_warn(desc, fmt, ...)					\ +	pr_warn("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) +#define gpiod_info(desc, fmt, ...)					\ +	pr_info("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) +#define gpiod_dbg(desc, fmt, ...)					\ +	pr_debug("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__) +#endif + +/* With chip prefix */ + +#define chip_emerg(chip, fmt, ...)					\ +	pr_emerg("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_crit(chip, fmt, ...)					\ +	pr_crit("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_err(chip, fmt, ...)					\ +	pr_err("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_warn(chip, fmt, ...)					\ +	pr_warn("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_info(chip, fmt, ...)					\ +	pr_info("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__) +#define chip_dbg(chip, fmt, ...)					\ +	pr_debug("GPIO chip %s: " fmt, chip->label, ##__VA_ARGS__)  static inline void desc_set_label(struct gpio_desc *d, const char *label)  { @@ -121,23 +154,38 @@ static int gpio_chip_hwgpio(const struct gpio_desc *desc)  /**   * Convert a GPIO number to its descriptor   */ -static struct gpio_desc *gpio_to_desc(unsigned gpio) +struct gpio_desc *gpio_to_desc(unsigned gpio)  {  	if (WARN(!gpio_is_valid(gpio), "invalid GPIO %d\n", gpio))  		return NULL;  	else  		return &gpio_desc[gpio];  } +EXPORT_SYMBOL_GPL(gpio_to_desc); + +/** + * Get the GPIO descriptor corresponding to the given hw number for this chip. + */ +struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, +				    u16 hwnum) +{ +	if (hwnum >= chip->ngpio) +		return ERR_PTR(-EINVAL); + +	return &chip->desc[hwnum]; +} +EXPORT_SYMBOL_GPL(gpiochip_get_desc);  /**   * Convert a GPIO descriptor to the integer namespace.   * This should disappear in the future but is needed since we still   * use GPIO numbers for error messages and sysfs nodes   */ -static int desc_to_gpio(const struct gpio_desc *desc) +int desc_to_gpio(const struct gpio_desc *desc)  { -	return desc->chip->base + gpio_chip_hwgpio(desc); +	return desc - &gpio_desc[0];  } +EXPORT_SYMBOL_GPL(desc_to_gpio);  /* Warn when drivers omit gpio_request() calls -- legal but ill-advised @@ -159,7 +207,8 @@ static int gpio_ensure_requested(struct gpio_desc *desc)  	if (WARN(test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0,  			"autorequest GPIO-%d\n", gpio)) {  		if (!try_module_get(chip->owner)) { -			pr_err("GPIO-%d: module can't be gotten \n", gpio); +			gpiod_err(desc, "%s: module can't be gotten\n", +					__func__);  			clear_bit(FLAG_REQUESTED, &desc->flags);  			/* lose */  			return -EIO; @@ -172,16 +221,15 @@ static int gpio_ensure_requested(struct gpio_desc *desc)  	return 0;  } -static struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) +/** + * gpiod_to_chip - Return the GPIO chip to which a GPIO descriptor belongs + * @desc:	descriptor to return the chip of + */ +struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)  {  	return desc ? desc->chip : NULL;  } - -/* caller holds gpio_lock *OR* gpio is marked as requested */ -struct gpio_chip *gpio_to_chip(unsigned gpio) -{ -	return gpiod_to_chip(gpio_to_desc(gpio)); -} +EXPORT_SYMBOL_GPL(gpiod_to_chip);  /* dynamic allocation of GPIOs, e.g. on a hotplugged device */  static int gpiochip_find_base(int ngpio) @@ -207,8 +255,15 @@ static int gpiochip_find_base(int ngpio)  	}  } -/* caller ensures gpio is valid and requested, chip->get_direction may sleep  */ -static int gpiod_get_direction(const struct gpio_desc *desc) +/** + * gpiod_get_direction - return the current direction of a GPIO + * @desc:	GPIO to get the direction of + * + * Return GPIOF_DIR_IN or GPIOF_DIR_OUT, or an error code in case of error. + * + * This function may sleep if gpiod_cansleep() is true. + */ +int gpiod_get_direction(const struct gpio_desc *desc)  {  	struct gpio_chip	*chip;  	unsigned		offset; @@ -234,6 +289,7 @@ static int gpiod_get_direction(const struct gpio_desc *desc)  	}  	return status;  } +EXPORT_SYMBOL_GPL(gpiod_get_direction);  #ifdef CONFIG_GPIO_SYSFS @@ -295,9 +351,9 @@ static ssize_t gpio_direction_store(struct device *dev,  	if (!test_bit(FLAG_EXPORT, &desc->flags))  		status = -EIO;  	else if (sysfs_streq(buf, "high")) -		status = gpiod_direction_output(desc, 1); +		status = gpiod_direction_output_raw(desc, 1);  	else if (sysfs_streq(buf, "out") || sysfs_streq(buf, "low")) -		status = gpiod_direction_output(desc, 0); +		status = gpiod_direction_output_raw(desc, 0);  	else if (sysfs_streq(buf, "in"))  		status = gpiod_direction_input(desc);  	else @@ -318,17 +374,10 @@ static ssize_t gpio_value_show(struct device *dev,  	mutex_lock(&sysfs_lock); -	if (!test_bit(FLAG_EXPORT, &desc->flags)) { +	if (!test_bit(FLAG_EXPORT, &desc->flags))  		status = -EIO; -	} else { -		int value; - -		value = !!gpiod_get_value_cansleep(desc); -		if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) -			value = !value; - -		status = sprintf(buf, "%d\n", value); -	} +	else +		status = sprintf(buf, "%d\n", gpiod_get_value_cansleep(desc));  	mutex_unlock(&sysfs_lock);  	return status; @@ -351,9 +400,7 @@ static ssize_t gpio_value_store(struct device *dev,  		status = kstrtol(buf, 0, &value);  		if (status == 0) { -			if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) -				value = !value; -			gpiod_set_value_cansleep(desc, value != 0); +			gpiod_set_value_cansleep(desc, value);  			status = size;  		}  	} @@ -367,7 +414,7 @@ static const DEVICE_ATTR(value, 0644,  static irqreturn_t gpio_sysfs_irq(int irq, void *priv)  { -	struct sysfs_dirent	*value_sd = priv; +	struct kernfs_node	*value_sd = priv;  	sysfs_notify_dirent(value_sd);  	return IRQ_HANDLED; @@ -376,7 +423,7 @@ static irqreturn_t gpio_sysfs_irq(int irq, void *priv)  static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,  		unsigned long gpio_flags)  { -	struct sysfs_dirent	*value_sd; +	struct kernfs_node	*value_sd;  	unsigned long		irq_flags;  	int			ret, irq, id; @@ -395,6 +442,7 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,  	desc->flags &= ~GPIO_TRIGGER_MASK;  	if (!gpio_flags) { +		gpiod_unlock_as_irq(desc);  		ret = 0;  		goto free_id;  	} @@ -408,7 +456,7 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,  			IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;  	if (!value_sd) { -		value_sd = sysfs_get_dirent(dev->kobj.sd, NULL, "value"); +		value_sd = sysfs_get_dirent(dev->kobj.sd, "value");  		if (!value_sd) {  			ret = -ENODEV;  			goto err_out; @@ -433,6 +481,12 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,  	if (ret < 0)  		goto free_id; +	ret = gpiod_lock_as_irq(desc); +	if (ret < 0) { +		gpiod_warn(desc, "failed to flag the GPIO for IRQ\n"); +		goto free_id; +	} +  	desc->flags |= gpio_flags;  	return 0; @@ -736,7 +790,7 @@ static struct class gpio_class = {  /** - * gpio_export - export a GPIO through sysfs + * gpiod_export - export a GPIO through sysfs   * @gpio: gpio to make available, already requested   * @direction_may_change: true if userspace may change gpio direction   * Context: arch_initcall or later @@ -750,7 +804,7 @@ static struct class gpio_class = {   *   * Returns zero on success, else an error.   */ -static int gpiod_export(struct gpio_desc *desc, bool direction_may_change) +int gpiod_export(struct gpio_desc *desc, bool direction_may_change)  {  	unsigned long		flags;  	int			status; @@ -775,8 +829,8 @@ static int gpiod_export(struct gpio_desc *desc, bool direction_may_change)  	if (!test_bit(FLAG_REQUESTED, &desc->flags) ||  	     test_bit(FLAG_EXPORT, &desc->flags)) {  		spin_unlock_irqrestore(&gpio_lock, flags); -		pr_debug("%s: gpio %d unavailable (requested=%d, exported=%d)\n", -				__func__, desc_to_gpio(desc), +		gpiod_dbg(desc, "%s: unavailable (requested=%d, exported=%d)\n", +				__func__,  				test_bit(FLAG_REQUESTED, &desc->flags),  				test_bit(FLAG_EXPORT, &desc->flags));  		status = -EPERM; @@ -824,16 +878,10 @@ fail_unregister_device:  	device_unregister(dev);  fail_unlock:  	mutex_unlock(&sysfs_lock); -	pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), -		 status); +	gpiod_dbg(desc, "%s: status %d\n", __func__, status);  	return status;  } - -int gpio_export(unsigned gpio, bool direction_may_change) -{ -	return gpiod_export(gpio_to_desc(gpio), direction_may_change); -} -EXPORT_SYMBOL_GPL(gpio_export); +EXPORT_SYMBOL_GPL(gpiod_export);  static int match_export(struct device *dev, const void *data)  { @@ -841,7 +889,7 @@ static int match_export(struct device *dev, const void *data)  }  /** - * gpio_export_link - create a sysfs link to an exported GPIO node + * gpiod_export_link - create a sysfs link to an exported GPIO node   * @dev: device under which to create symlink   * @name: name of the symlink   * @gpio: gpio to create symlink to, already exported @@ -851,8 +899,8 @@ static int match_export(struct device *dev, const void *data)   *   * Returns zero on success, else an error.   */ -static int gpiod_export_link(struct device *dev, const char *name, -			     struct gpio_desc *desc) +int gpiod_export_link(struct device *dev, const char *name, +		      struct gpio_desc *desc)  {  	int			status = -EINVAL; @@ -878,20 +926,14 @@ static int gpiod_export_link(struct device *dev, const char *name,  	mutex_unlock(&sysfs_lock);  	if (status) -		pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), -			 status); +		gpiod_dbg(desc, "%s: status %d\n", __func__, status);  	return status;  } - -int gpio_export_link(struct device *dev, const char *name, unsigned gpio) -{ -	return gpiod_export_link(dev, name, gpio_to_desc(gpio)); -} -EXPORT_SYMBOL_GPL(gpio_export_link); +EXPORT_SYMBOL_GPL(gpiod_export_link);  /** - * gpio_sysfs_set_active_low - set the polarity of gpio sysfs value + * gpiod_sysfs_set_active_low - set the polarity of gpio sysfs value   * @gpio: gpio to change   * @value: non-zero to use active low, i.e. inverted values   * @@ -902,7 +944,7 @@ EXPORT_SYMBOL_GPL(gpio_export_link);   *   * Returns zero on success, else an error.   */ -static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value) +int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)  {  	struct device		*dev = NULL;  	int			status = -EINVAL; @@ -928,25 +970,19 @@ unlock:  	mutex_unlock(&sysfs_lock);  	if (status) -		pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), -			 status); +		gpiod_dbg(desc, "%s: status %d\n", __func__, status);  	return status;  } - -int gpio_sysfs_set_active_low(unsigned gpio, int value) -{ -	return gpiod_sysfs_set_active_low(gpio_to_desc(gpio), value); -} -EXPORT_SYMBOL_GPL(gpio_sysfs_set_active_low); +EXPORT_SYMBOL_GPL(gpiod_sysfs_set_active_low);  /** - * gpio_unexport - reverse effect of gpio_export() + * gpiod_unexport - reverse effect of gpio_export()   * @gpio: gpio to make unavailable   *   * This is implicit on gpio_free().   */ -static void gpiod_unexport(struct gpio_desc *desc) +void gpiod_unexport(struct gpio_desc *desc)  {  	int			status = 0;  	struct device		*dev = NULL; @@ -976,15 +1012,9 @@ static void gpiod_unexport(struct gpio_desc *desc)  	}  	if (status) -		pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), -			 status); -} - -void gpio_unexport(unsigned gpio) -{ -	gpiod_unexport(gpio_to_desc(gpio)); +		gpiod_dbg(desc, "%s: status %d\n", __func__, status);  } -EXPORT_SYMBOL_GPL(gpio_unexport); +EXPORT_SYMBOL_GPL(gpiod_unexport);  static int gpiochip_export(struct gpio_chip *chip)  { @@ -1021,8 +1051,7 @@ static int gpiochip_export(struct gpio_chip *chip)  			chip->desc[gpio++].chip = NULL;  		spin_unlock_irqrestore(&gpio_lock, flags); -		pr_debug("%s: chip %s status %d\n", __func__, -				chip->label, status); +		chip_dbg(chip, "%s: status %d\n", __func__, status);  	}  	return status; @@ -1038,15 +1067,14 @@ static void gpiochip_unexport(struct gpio_chip *chip)  	if (dev) {  		put_device(dev);  		device_unregister(dev); -		chip->exported = 0; +		chip->exported = false;  		status = 0;  	} else  		status = -ENODEV;  	mutex_unlock(&sysfs_lock);  	if (status) -		pr_debug("%s: chip %s status %d\n", __func__, -				chip->label, status); +		chip_dbg(chip, "%s: status %d\n", __func__, status);  }  static int __init gpiolib_sysfs_init(void) @@ -1091,27 +1119,6 @@ static inline void gpiochip_unexport(struct gpio_chip *chip)  {  } -static inline int gpiod_export(struct gpio_desc *desc, -			       bool direction_may_change) -{ -	return -ENOSYS; -} - -static inline int gpiod_export_link(struct device *dev, const char *name, -				    struct gpio_desc *desc) -{ -	return -ENOSYS; -} - -static inline int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value) -{ -	return -ENOSYS; -} - -static inline void gpiod_unexport(struct gpio_desc *desc) -{ -} -  #endif /* CONFIG_GPIO_SYSFS */  /* @@ -1221,6 +1228,7 @@ int gpiochip_add(struct gpio_chip *chip)  #endif  	of_gpiochip_add(chip); +	acpi_gpiochip_add(chip);  	if (status)  		goto fail; @@ -1229,7 +1237,7 @@ int gpiochip_add(struct gpio_chip *chip)  	if (status)  		goto fail; -	pr_debug("gpiochip_add: registered GPIOs %d to %d on device: %s\n", +	pr_debug("%s: registered GPIOs %d to %d on device: %s\n", __func__,  		chip->base, chip->base + chip->ngpio - 1,  		chip->label ? : "generic"); @@ -1239,13 +1247,16 @@ unlock:  	spin_unlock_irqrestore(&gpio_lock, flags);  fail:  	/* failures here can mean systems won't boot... */ -	pr_err("gpiochip_add: gpios %d..%d (%s) failed to register\n", +	pr_err("%s: GPIOs %d..%d (%s) failed to register\n", __func__,  		chip->base, chip->base + chip->ngpio - 1,  		chip->label ? : "generic");  	return status;  }  EXPORT_SYMBOL_GPL(gpiochip_add); +/* Forward-declaration */ +static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip); +  /**   * gpiochip_remove() - unregister a gpio_chip   * @chip: the chip to unregister @@ -1258,8 +1269,11 @@ int gpiochip_remove(struct gpio_chip *chip)  	int		status = 0;  	unsigned	id; +	acpi_gpiochip_remove(chip); +  	spin_lock_irqsave(&gpio_lock, flags); +	gpiochip_irqchip_remove(chip);  	gpiochip_remove_pin_ranges(chip);  	of_gpiochip_remove(chip); @@ -1317,9 +1331,302 @@ struct gpio_chip *gpiochip_find(void *data,  }  EXPORT_SYMBOL_GPL(gpiochip_find); +static int gpiochip_match_name(struct gpio_chip *chip, void *data) +{ +	const char *name = data; + +	return !strcmp(chip->label, name); +} + +static struct gpio_chip *find_chip_by_name(const char *name) +{ +	return gpiochip_find((void *)name, gpiochip_match_name); +} + +#ifdef CONFIG_GPIOLIB_IRQCHIP + +/* + * The following is irqchip helper code for gpiochips. + */ + +/** + * gpiochip_add_chained_irqchip() - adds a chained irqchip to a gpiochip + * @gpiochip: the gpiochip to add the irqchip to + * @irqchip: the irqchip to add to the gpiochip + * @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 + */ +void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, +				  struct irq_chip *irqchip, +				  int parent_irq, +				  irq_flow_handler_t parent_handler) +{ +	if (gpiochip->can_sleep) { +		chip_err(gpiochip, "you cannot have chained interrupts on a chip that may sleep\n"); +		return; +	} + +	irq_set_chained_handler(parent_irq, parent_handler); +	/* +	 * The parent irqchip is already using the chip_data for this +	 * irqchip, so our callbacks simply use the handler_data. +	 */ +	irq_set_handler_data(parent_irq, gpiochip); +} +EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip); + +/* + * This lock class tells lockdep that GPIO irqs are in a different + * category than their parents, so it won't report false recursion. + */ +static struct lock_class_key gpiochip_irq_lock_class; + +/** + * gpiochip_irq_map() - maps an IRQ into a GPIO irqchip + * @d: the irqdomain used by this irqchip + * @irq: the global irq number used by this GPIO irqchip irq + * @hwirq: the local IRQ/GPIO line offset on this gpiochip + * + * This function will set up the mapping for a certain IRQ line on a + * gpiochip by assigning the gpiochip as chip data, and using the irqchip + * stored inside the gpiochip. + */ +static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, +			    irq_hw_number_t hwirq) +{ +	struct gpio_chip *chip = d->host_data; + +	irq_set_chip_data(irq, chip); +	irq_set_lockdep_class(irq, &gpiochip_irq_lock_class); +	irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler); +	/* Chips that can sleep need nested thread handlers */ +	if (chip->can_sleep) +		irq_set_nested_thread(irq, 1); +#ifdef CONFIG_ARM +	set_irq_flags(irq, IRQF_VALID); +#else +	irq_set_noprobe(irq); +#endif +	/* +	 * No set-up of the hardware will happen if IRQ_TYPE_NONE +	 * is passed as default type. +	 */ +	if (chip->irq_default_type != IRQ_TYPE_NONE) +		irq_set_irq_type(irq, chip->irq_default_type); + +	return 0; +} + +static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq) +{ +	struct gpio_chip *chip = d->host_data; + +#ifdef CONFIG_ARM +	set_irq_flags(irq, 0); +#endif +	if (chip->can_sleep) +		irq_set_nested_thread(irq, 0); +	irq_set_chip_and_handler(irq, NULL, NULL); +	irq_set_chip_data(irq, NULL); +} + +static const struct irq_domain_ops gpiochip_domain_ops = { +	.map	= gpiochip_irq_map, +	.unmap	= gpiochip_irq_unmap, +	/* Virtually all GPIO irqchips are twocell:ed */ +	.xlate	= irq_domain_xlate_twocell, +}; + +static int gpiochip_irq_reqres(struct irq_data *d) +{ +	struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + +	if (gpio_lock_as_irq(chip, d->hwirq)) { +		chip_err(chip, +			"unable to lock HW IRQ %lu for IRQ\n", +			d->hwirq); +		return -EINVAL; +	} +	return 0; +} + +static void gpiochip_irq_relres(struct irq_data *d) +{ +	struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + +	gpio_unlock_as_irq(chip, d->hwirq); +} + +static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset) +{ +	return irq_find_mapping(chip->irqdomain, offset); +} + +/** + * gpiochip_irqchip_remove() - removes an irqchip added to a gpiochip + * @gpiochip: the gpiochip to remove the irqchip from + * + * This is called only from gpiochip_remove() + */ +static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) +{ +	unsigned int offset; + +	/* Remove all IRQ mappings and delete the domain */ +	if (gpiochip->irqdomain) { +		for (offset = 0; offset < gpiochip->ngpio; offset++) +			irq_dispose_mapping(gpiochip->irq_base + offset); +		irq_domain_remove(gpiochip->irqdomain); +	} + +	if (gpiochip->irqchip) { +		gpiochip->irqchip->irq_request_resources = NULL; +		gpiochip->irqchip->irq_release_resources = NULL; +		gpiochip->irqchip = NULL; +	} +} + +/** + * gpiochip_irqchip_add() - adds an irqchip to a gpiochip + * @gpiochip: the gpiochip to add the irqchip to + * @irqchip: the irqchip to add to the gpiochip + * @first_irq: if not dynamically assigned, the base (first) IRQ to + * allocate gpiochip irqs from + * @handler: the irq handler to use (often a predefined irq core function) + * @type: the default type for IRQs on this irqchip, pass IRQ_TYPE_NONE + * to have the core avoid setting up any default type in the hardware. + * + * This function closely associates a certain irqchip with a certain + * gpiochip, providing an irq domain to translate the local IRQs to + * global irqs in the gpiolib core, and making sure that the gpiochip + * is passed as chip data to all related functions. Driver callbacks + * need to use container_of() to get their local state containers back + * from the gpiochip passed as chip data. An irqdomain will be stored + * in the gpiochip that shall be used by the driver to handle IRQ number + * translation. The gpiochip will need to be initialized and registered + * before calling this function. + * + * This function will handle two cell:ed simple IRQs and assumes all + * the pins on the gpiochip can generate a unique IRQ. Everything else + * need to be open coded. + */ +int gpiochip_irqchip_add(struct gpio_chip *gpiochip, +			 struct irq_chip *irqchip, +			 unsigned int first_irq, +			 irq_flow_handler_t handler, +			 unsigned int type) +{ +	struct device_node *of_node; +	unsigned int offset; +	unsigned irq_base = 0; + +	if (!gpiochip || !irqchip) +		return -EINVAL; + +	if (!gpiochip->dev) { +		pr_err("missing gpiochip .dev parent pointer\n"); +		return -EINVAL; +	} +	of_node = gpiochip->dev->of_node; +#ifdef CONFIG_OF_GPIO +	/* +	 * If the gpiochip has an assigned OF node this takes precendence +	 * FIXME: get rid of this and use gpiochip->dev->of_node everywhere +	 */ +	if (gpiochip->of_node) +		of_node = gpiochip->of_node; +#endif +	gpiochip->irqchip = irqchip; +	gpiochip->irq_handler = handler; +	gpiochip->irq_default_type = type; +	gpiochip->to_irq = gpiochip_to_irq; +	gpiochip->irqdomain = irq_domain_add_simple(of_node, +					gpiochip->ngpio, first_irq, +					&gpiochip_domain_ops, gpiochip); +	if (!gpiochip->irqdomain) { +		gpiochip->irqchip = NULL; +		return -EINVAL; +	} +	irqchip->irq_request_resources = gpiochip_irq_reqres; +	irqchip->irq_release_resources = gpiochip_irq_relres; + +	/* +	 * Prepare the mapping since the irqchip shall be orthogonal to +	 * any gpiochip calls. If the first_irq was zero, this is +	 * necessary to allocate descriptors for all IRQs. +	 */ +	for (offset = 0; offset < gpiochip->ngpio; offset++) { +		irq_base = irq_create_mapping(gpiochip->irqdomain, offset); +		if (offset == 0) +			/* +			 * Store the base into the gpiochip to be used when +			 * unmapping the irqs. +			 */ +			gpiochip->irq_base = irq_base; +	} + +	return 0; +} +EXPORT_SYMBOL_GPL(gpiochip_irqchip_add); + +#else /* CONFIG_GPIOLIB_IRQCHIP */ + +static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {} + +#endif /* CONFIG_GPIOLIB_IRQCHIP */ +  #ifdef CONFIG_PINCTRL  /** + * gpiochip_add_pingroup_range() - add a range for GPIO <-> pin mapping + * @chip: the gpiochip to add the range for + * @pinctrl: the dev_name() of the pin controller to map to + * @gpio_offset: the start offset in the current gpio_chip number space + * @pin_group: name of the pin group inside the pin controller + */ +int gpiochip_add_pingroup_range(struct gpio_chip *chip, +			struct pinctrl_dev *pctldev, +			unsigned int gpio_offset, const char *pin_group) +{ +	struct gpio_pin_range *pin_range; +	int ret; + +	pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL); +	if (!pin_range) { +		chip_err(chip, "failed to allocate pin ranges\n"); +		return -ENOMEM; +	} + +	/* Use local offset as range ID */ +	pin_range->range.id = gpio_offset; +	pin_range->range.gc = chip; +	pin_range->range.name = chip->label; +	pin_range->range.base = chip->base + gpio_offset; +	pin_range->pctldev = pctldev; + +	ret = pinctrl_get_group_pins(pctldev, pin_group, +					&pin_range->range.pins, +					&pin_range->range.npins); +	if (ret < 0) { +		kfree(pin_range); +		return ret; +	} + +	pinctrl_add_gpio_range(pctldev, &pin_range->range); + +	chip_dbg(chip, "created GPIO range %d->%d ==> %s PINGRP %s\n", +		 gpio_offset, gpio_offset + pin_range->range.npins - 1, +		 pinctrl_dev_get_devname(pctldev), pin_group); + +	list_add_tail(&pin_range->node, &chip->pin_ranges); + +	return 0; +} +EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range); + +/**   * gpiochip_add_pin_range() - add a range for GPIO <-> pin mapping   * @chip: the gpiochip to add the range for   * @pinctrl_name: the dev_name() of the pin controller to map to @@ -1337,8 +1644,7 @@ int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,  	pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL);  	if (!pin_range) { -		pr_err("%s: GPIO chip: failed to allocate pin ranges\n", -				chip->label); +		chip_err(chip, "failed to allocate pin ranges\n");  		return -ENOMEM;  	} @@ -1353,13 +1659,12 @@ int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,  			&pin_range->range);  	if (IS_ERR(pin_range->pctldev)) {  		ret = PTR_ERR(pin_range->pctldev); -		pr_err("%s: GPIO chip: could not create pin range\n", -		       chip->label); +		chip_err(chip, "could not create pin range\n");  		kfree(pin_range);  		return ret;  	} -	pr_debug("GPIO chip %s: created GPIO range %d->%d ==> %s PIN %d->%d\n", -		 chip->label, gpio_offset, gpio_offset + npins - 1, +	chip_dbg(chip, "created GPIO range %d->%d ==> %s PIN %d->%d\n", +		 gpio_offset, gpio_offset + npins - 1,  		 pinctl_name,  		 pin_offset, pin_offset + npins - 1); @@ -1392,24 +1697,14 @@ EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges);   * on each other, and help provide better diagnostics in debugfs.   * They're called even less than the "set direction" calls.   */ -static int gpiod_request(struct gpio_desc *desc, const char *label) +static int __gpiod_request(struct gpio_desc *desc, const char *label)  { -	struct gpio_chip	*chip; -	int			status = -EPROBE_DEFER; +	struct gpio_chip	*chip = desc->chip; +	int			status;  	unsigned long		flags; -	if (!desc || !desc->chip) { -		pr_warn("%s: invalid GPIO\n", __func__); -		return -EINVAL; -	} -  	spin_lock_irqsave(&gpio_lock, flags); -	chip = desc->chip; - -	if (!try_module_get(chip->owner)) -		goto done; -  	/* NOTE:  gpio_request() can be called in early boot,  	 * before IRQs are enabled, for non-sleeping (SOC) GPIOs.  	 */ @@ -1419,7 +1714,6 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)  		status = 0;  	} else {  		status = -EBUSY; -		module_put(chip->owner);  		goto done;  	} @@ -1431,7 +1725,6 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)  		if (status < 0) {  			desc_set_label(desc, NULL); -			module_put(chip->owner);  			clear_bit(FLAG_REQUESTED, &desc->flags);  			goto done;  		} @@ -1443,31 +1736,51 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)  		spin_lock_irqsave(&gpio_lock, flags);  	}  done: -	if (status) -		pr_debug("_gpio_request: gpio-%d (%s) status %d\n", -			 desc_to_gpio(desc), label ? : "?", status);  	spin_unlock_irqrestore(&gpio_lock, flags);  	return status;  } +static int gpiod_request(struct gpio_desc *desc, const char *label) +{ +	int status = -EPROBE_DEFER; +	struct gpio_chip *chip; + +	if (!desc) { +		pr_warn("%s: invalid GPIO\n", __func__); +		return -EINVAL; +	} + +	chip = desc->chip; +	if (!chip) +		goto done; + +	if (try_module_get(chip->owner)) { +		status = __gpiod_request(desc, label); +		if (status < 0) +			module_put(chip->owner); +	} + +done: +	if (status) +		gpiod_dbg(desc, "%s: status %d\n", __func__, status); + +	return status; +} +  int gpio_request(unsigned gpio, const char *label)  {  	return gpiod_request(gpio_to_desc(gpio), label);  }  EXPORT_SYMBOL_GPL(gpio_request); -static void gpiod_free(struct gpio_desc *desc) +static bool __gpiod_free(struct gpio_desc *desc)  { +	bool			ret = false;  	unsigned long		flags;  	struct gpio_chip	*chip;  	might_sleep(); -	if (!desc) { -		WARN_ON(extra_checks); -		return; -	} -  	gpiod_unexport(desc);  	spin_lock_irqsave(&gpio_lock, flags); @@ -1481,15 +1794,23 @@ static void gpiod_free(struct gpio_desc *desc)  			spin_lock_irqsave(&gpio_lock, flags);  		}  		desc_set_label(desc, NULL); -		module_put(desc->chip->owner);  		clear_bit(FLAG_ACTIVE_LOW, &desc->flags);  		clear_bit(FLAG_REQUESTED, &desc->flags);  		clear_bit(FLAG_OPEN_DRAIN, &desc->flags);  		clear_bit(FLAG_OPEN_SOURCE, &desc->flags); -	} else -		WARN_ON(extra_checks); +		ret = true; +	}  	spin_unlock_irqrestore(&gpio_lock, flags); +	return ret; +} + +static void gpiod_free(struct gpio_desc *desc) +{ +	if (desc && __gpiod_free(desc)) +		module_put(desc->chip->owner); +	else +		WARN_ON(extra_checks);  }  void gpio_free(unsigned gpio) @@ -1524,7 +1845,7 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)  	if (flags & GPIOF_DIR_IN)  		err = gpiod_direction_input(desc);  	else -		err = gpiod_direction_output(desc, +		err = gpiod_direction_output_raw(desc,  				(flags & GPIOF_INIT_HIGH) ? 1 : 0);  	if (err) @@ -1611,6 +1932,37 @@ const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset)  }  EXPORT_SYMBOL_GPL(gpiochip_is_requested); +/** + * gpiochip_request_own_desc - Allow GPIO chip to request its own descriptor + * @desc: GPIO descriptor to request + * @label: label for the GPIO + * + * Function allows GPIO chip drivers to request and use their own GPIO + * descriptors via gpiolib API. Difference to gpiod_request() is that this + * function will not increase reference count of the GPIO chip module. This + * allows the GPIO chip module to be unloaded as needed (we assume that the + * GPIO chip driver handles freeing the GPIOs it has requested). + */ +int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label) +{ +	if (!desc || !desc->chip) +		return -EINVAL; + +	return __gpiod_request(desc, label); +} + +/** + * gpiochip_free_own_desc - Free GPIO requested by the chip driver + * @desc: GPIO descriptor to free + * + * Function frees the given GPIO requested previously with + * gpiochip_request_own_desc(). + */ +void gpiochip_free_own_desc(struct gpio_desc *desc) +{ +	if (desc) +		__gpiod_free(desc); +}  /* Drivers MUST set GPIO direction before making get/set calls.  In   * some cases this is done in early boot, before IRQs are enabled. @@ -1621,7 +1973,16 @@ EXPORT_SYMBOL_GPL(gpiochip_is_requested);   * rely on gpio_request() having been called beforehand.   */ -static int gpiod_direction_input(struct gpio_desc *desc) +/** + * gpiod_direction_input - set the GPIO direction to input + * @desc:	GPIO to set to input + * + * Set the direction of the passed GPIO to input, such as gpiod_get_value() can + * be called safely on it. + * + * Return 0 in case of success, else an error code. + */ +int gpiod_direction_input(struct gpio_desc *desc)  {  	unsigned long		flags;  	struct gpio_chip	*chip; @@ -1635,7 +1996,8 @@ static int gpiod_direction_input(struct gpio_desc *desc)  	chip = desc->chip;  	if (!chip->get || !chip->direction_input) { -		pr_warn("%s: missing get() or direction_input() operations\n", +		gpiod_warn(desc, +			"%s: missing get() or direction_input() operations\n",  			__func__);  		return -EIO;  	} @@ -1656,8 +2018,8 @@ static int gpiod_direction_input(struct gpio_desc *desc)  	if (status) {  		status = chip->request(chip, offset);  		if (status < 0) { -			pr_debug("GPIO-%d: chip request fail, %d\n", -				desc_to_gpio(desc), status); +			gpiod_dbg(desc, "%s: chip request fail, %d\n", +					__func__, status);  			/* and it's not available to anyone else ...  			 * gpio_request() is the fully clean solution.  			 */ @@ -1675,27 +2037,24 @@ lose:  fail:  	spin_unlock_irqrestore(&gpio_lock, flags);  	if (status) -		pr_debug("%s: gpio-%d status %d\n", __func__, -			 desc_to_gpio(desc), status); +		gpiod_dbg(desc, "%s: status %d\n", __func__, status);  	return status;  } +EXPORT_SYMBOL_GPL(gpiod_direction_input); -int gpio_direction_input(unsigned gpio) -{ -	return gpiod_direction_input(gpio_to_desc(gpio)); -} -EXPORT_SYMBOL_GPL(gpio_direction_input); - -static int gpiod_direction_output(struct gpio_desc *desc, int value) +static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)  {  	unsigned long		flags;  	struct gpio_chip	*chip;  	int			status = -EINVAL;  	int offset; -	if (!desc || !desc->chip) { -		pr_warn("%s: invalid GPIO\n", __func__); -		return -EINVAL; +	/* GPIOs used for IRQs shall not be set as output */ +	if (test_bit(FLAG_USED_AS_IRQ, &desc->flags)) { +		gpiod_err(desc, +			  "%s: tried to set a GPIO tied to an IRQ as output\n", +			  __func__); +		return -EIO;  	}  	/* Open drain pin should not be driven to 1 */ @@ -1708,8 +2067,9 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value)  	chip = desc->chip;  	if (!chip->set || !chip->direction_output) { -		pr_warn("%s: missing set() or direction_output() operations\n", -			__func__); +		gpiod_warn(desc, +		       "%s: missing set() or direction_output() operations\n", +		       __func__);  		return -EIO;  	} @@ -1729,8 +2089,8 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value)  	if (status) {  		status = chip->request(chip, offset);  		if (status < 0) { -			pr_debug("GPIO-%d: chip request fail, %d\n", -				desc_to_gpio(desc), status); +			gpiod_dbg(desc, "%s: chip request fail, %d\n", +					__func__, status);  			/* and it's not available to anyone else ...  			 * gpio_request() is the fully clean solution.  			 */ @@ -1748,26 +2108,64 @@ lose:  fail:  	spin_unlock_irqrestore(&gpio_lock, flags);  	if (status) -		pr_debug("%s: gpio-%d status %d\n", __func__, -			 desc_to_gpio(desc), status); +		gpiod_dbg(desc, "%s: gpio status %d\n", __func__, status);  	return status;  } -int gpio_direction_output(unsigned gpio, int value) +/** + * gpiod_direction_output_raw - set the GPIO direction to output + * @desc:	GPIO to set to output + * @value:	initial output value of the GPIO + * + * Set the direction of the passed GPIO to output, such as gpiod_set_value() can + * be called safely on it. The initial value of the output must be specified + * as raw value on the physical line without regard for the ACTIVE_LOW status. + * + * Return 0 in case of success, else an error code. + */ +int gpiod_direction_output_raw(struct gpio_desc *desc, int value) +{ +	if (!desc || !desc->chip) { +		pr_warn("%s: invalid GPIO\n", __func__); +		return -EINVAL; +	} +	return _gpiod_direction_output_raw(desc, value); +} +EXPORT_SYMBOL_GPL(gpiod_direction_output_raw); + +/** + * gpiod_direction_output - set the GPIO direction to output + * @desc:	GPIO to set to output + * @value:	initial output value of the GPIO + * + * Set the direction of the passed GPIO to output, such as gpiod_set_value() can + * be called safely on it. The initial value of the output must be specified + * as the logical value of the GPIO, i.e. taking its ACTIVE_LOW status into + * account. + * + * Return 0 in case of success, else an error code. + */ +int gpiod_direction_output(struct gpio_desc *desc, int value)  { -	return gpiod_direction_output(gpio_to_desc(gpio), value); +	if (!desc || !desc->chip) { +		pr_warn("%s: invalid GPIO\n", __func__); +		return -EINVAL; +	} +	if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) +		value = !value; +	return _gpiod_direction_output_raw(desc, value);  } -EXPORT_SYMBOL_GPL(gpio_direction_output); +EXPORT_SYMBOL_GPL(gpiod_direction_output);  /** - * gpio_set_debounce - sets @debounce time for a @gpio + * gpiod_set_debounce - sets @debounce time for a @gpio   * @gpio: the gpio to set debounce time   * @debounce: debounce time is microseconds   *   * returns -ENOTSUPP if the controller does not support setting   * debounce.   */ -static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) +int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)  {  	unsigned long		flags;  	struct gpio_chip	*chip; @@ -1781,8 +2179,9 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)  	chip = desc->chip;  	if (!chip->set || !chip->set_debounce) { -		pr_debug("%s: missing set() or set_debounce() operations\n", -			__func__); +		gpiod_dbg(desc, +			  "%s: missing set() or set_debounce() operations\n", +			  __func__);  		return -ENOTSUPP;  	} @@ -1804,17 +2203,23 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)  fail:  	spin_unlock_irqrestore(&gpio_lock, flags);  	if (status) -		pr_debug("%s: gpio-%d status %d\n", __func__, -			 desc_to_gpio(desc), status); +		gpiod_dbg(desc, "%s: status %d\n", __func__, status);  	return status;  } +EXPORT_SYMBOL_GPL(gpiod_set_debounce); -int gpio_set_debounce(unsigned gpio, unsigned debounce) +/** + * gpiod_is_active_low - test whether a GPIO is active-low or not + * @desc: the gpio descriptor to test + * + * Returns 1 if the GPIO is active-low, 0 otherwise. + */ +int gpiod_is_active_low(const struct gpio_desc *desc)  { -	return gpiod_set_debounce(gpio_to_desc(gpio), debounce); +	return test_bit(FLAG_ACTIVE_LOW, &desc->flags);  } -EXPORT_SYMBOL_GPL(gpio_set_debounce); +EXPORT_SYMBOL_GPL(gpiod_is_active_low);  /* I/O calls are only valid after configuration completed; the relevant   * "is this a valid GPIO" error checks should already have been done. @@ -1838,45 +2243,71 @@ EXPORT_SYMBOL_GPL(gpio_set_debounce);   * that the GPIO was actually requested.   */ -/** - * __gpio_get_value() - return a gpio's value - * @gpio: gpio whose value will be returned - * Context: any - * - * This is used directly or indirectly to implement gpio_get_value(). - * It returns the zero or nonzero value provided by the associated - * gpio_chip.get() method; or zero if no such method is provided. - */ -static int gpiod_get_value(const struct gpio_desc *desc) +static bool _gpiod_get_raw_value(const struct gpio_desc *desc)  {  	struct gpio_chip	*chip; -	int value; +	bool value;  	int offset; -	if (!desc) -		return 0;  	chip = desc->chip;  	offset = gpio_chip_hwgpio(desc); -	/* Should be using gpio_get_value_cansleep() */ -	WARN_ON(chip->can_sleep); -	value = chip->get ? chip->get(chip, offset) : 0; +	value = chip->get ? chip->get(chip, offset) : false;  	trace_gpio_value(desc_to_gpio(desc), 1, value);  	return value;  } -int __gpio_get_value(unsigned gpio) +/** + * gpiod_get_raw_value() - return a gpio's raw value + * @desc: gpio whose value will be returned + * + * Return the GPIO's raw value, i.e. the value of the physical line disregarding + * its ACTIVE_LOW status. + * + * This function should 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) +{ +	if (!desc) +		return 0; +	/* Should be using gpio_get_value_cansleep() */ +	WARN_ON(desc->chip->can_sleep); +	return _gpiod_get_raw_value(desc); +} +EXPORT_SYMBOL_GPL(gpiod_get_raw_value); + +/** + * gpiod_get_value() - return a gpio's value + * @desc: gpio whose value will be returned + * + * Return the GPIO's logical value, i.e. taking the ACTIVE_LOW status into + * account. + * + * This function should 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)  { -	return gpiod_get_value(gpio_to_desc(gpio)); +	int value; +	if (!desc) +		return 0; +	/* Should be using gpio_get_value_cansleep() */ +	WARN_ON(desc->chip->can_sleep); + +	value = _gpiod_get_raw_value(desc); +	if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) +		value = !value; + +	return value;  } -EXPORT_SYMBOL_GPL(__gpio_get_value); +EXPORT_SYMBOL_GPL(gpiod_get_value);  /*   *  _gpio_set_open_drain_value() - Set the open drain gpio's value. - * @gpio: Gpio whose state need to be set. - * @chip: Gpio chip. + * @desc: gpio descriptor whose state need to be set.   * @value: Non-zero for setting it HIGH otherise it will set to LOW.   */ -static void _gpio_set_open_drain_value(struct gpio_desc *desc, int value) +static void _gpio_set_open_drain_value(struct gpio_desc *desc, bool value)  {  	int err = 0;  	struct gpio_chip *chip = desc->chip; @@ -1893,17 +2324,17 @@ static void _gpio_set_open_drain_value(struct gpio_desc *desc, int value)  	}  	trace_gpio_direction(desc_to_gpio(desc), value, err);  	if (err < 0) -		pr_err("%s: Error in set_value for open drain gpio%d err %d\n", -					__func__, desc_to_gpio(desc), err); +		gpiod_err(desc, +			  "%s: Error in set_value for open drain err %d\n", +			  __func__, err);  }  /* - *  _gpio_set_open_source() - Set the open source gpio's value. - * @gpio: Gpio whose state need to be set. - * @chip: Gpio chip. + *  _gpio_set_open_source_value() - Set the open source gpio's value. + * @desc: gpio descriptor whose state need to be set.   * @value: Non-zero for setting it HIGH otherise it will set to LOW.   */ -static void _gpio_set_open_source_value(struct gpio_desc *desc, int value) +static void _gpio_set_open_source_value(struct gpio_desc *desc, bool value)  {  	int err = 0;  	struct gpio_chip *chip = desc->chip; @@ -1920,28 +2351,16 @@ static void _gpio_set_open_source_value(struct gpio_desc *desc, int value)  	}  	trace_gpio_direction(desc_to_gpio(desc), !value, err);  	if (err < 0) -		pr_err("%s: Error in set_value for open source gpio%d err %d\n", -					__func__, desc_to_gpio(desc), err); +		gpiod_err(desc, +			  "%s: Error in set_value for open source err %d\n", +			  __func__, err);  } -/** - * __gpio_set_value() - assign a gpio's value - * @gpio: gpio whose value will be assigned - * @value: value to assign - * Context: any - * - * This is used directly or indirectly to implement gpio_set_value(). - * It invokes the associated gpio_chip.set() method. - */ -static void gpiod_set_value(struct gpio_desc *desc, int value) +static void _gpiod_set_raw_value(struct gpio_desc *desc, bool value)  {  	struct gpio_chip	*chip; -	if (!desc) -		return;  	chip = desc->chip; -	/* Should be using gpio_set_value_cansleep() */ -	WARN_ON(chip->can_sleep);  	trace_gpio_value(desc_to_gpio(desc), 0, value);  	if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))  		_gpio_set_open_drain_value(desc, value); @@ -1951,44 +2370,71 @@ static void gpiod_set_value(struct gpio_desc *desc, int value)  		chip->set(chip, gpio_chip_hwgpio(desc), value);  } -void __gpio_set_value(unsigned gpio, int value) +/** + * gpiod_set_raw_value() - assign a gpio's raw value + * @desc: gpio whose value will be assigned + * @value: value to assign + * + * 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 + * complain if the GPIO chip functions potentially sleep. + */ +void gpiod_set_raw_value(struct gpio_desc *desc, int value)  { -	return gpiod_set_value(gpio_to_desc(gpio), value); +	if (!desc) +		return; +	/* Should be using gpio_set_value_cansleep() */ +	WARN_ON(desc->chip->can_sleep); +	_gpiod_set_raw_value(desc, value);  } -EXPORT_SYMBOL_GPL(__gpio_set_value); +EXPORT_SYMBOL_GPL(gpiod_set_raw_value);  /** - * __gpio_cansleep() - report whether gpio value access will sleep - * @gpio: gpio in question - * Context: any + * gpiod_set_value() - assign a gpio's value + * @desc: gpio whose value will be assigned + * @value: value to assign + * + * Set the logical value of the GPIO, i.e. taking its ACTIVE_LOW status into + * account   * - * This is used directly or indirectly to implement gpio_cansleep().  It - * returns nonzero if access reading or writing the GPIO value can sleep. + * This function should be called from contexts where we cannot sleep, and will + * complain if the GPIO chip functions potentially sleep.   */ -static int gpiod_cansleep(const struct gpio_desc *desc) +void gpiod_set_value(struct gpio_desc *desc, int value)  {  	if (!desc) -		return 0; -	/* only call this on GPIOs that are valid! */ -	return desc->chip->can_sleep; +		return; +	/* Should be using gpio_set_value_cansleep() */ +	WARN_ON(desc->chip->can_sleep); +	if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) +		value = !value; +	_gpiod_set_raw_value(desc, value);  } +EXPORT_SYMBOL_GPL(gpiod_set_value); -int __gpio_cansleep(unsigned gpio) +/** + * gpiod_cansleep() - report whether gpio value access may sleep + * @desc: gpio to check + * + */ +int gpiod_cansleep(const struct gpio_desc *desc)  { -	return gpiod_cansleep(gpio_to_desc(gpio)); +	if (!desc) +		return 0; +	return desc->chip->can_sleep;  } -EXPORT_SYMBOL_GPL(__gpio_cansleep); +EXPORT_SYMBOL_GPL(gpiod_cansleep);  /** - * __gpio_to_irq() - return the IRQ corresponding to a GPIO - * @gpio: gpio whose IRQ will be returned (already requested) - * Context: any + * gpiod_to_irq() - return the IRQ corresponding to a GPIO + * @desc: gpio whose IRQ will be returned (already requested)   * - * This is used directly or indirectly to implement gpio_to_irq(). - * It returns the number of the IRQ signaled by this (input) GPIO, - * or a negative errno. + * Return the IRQ corresponding to the passed GPIO, or an error code in case of + * error.   */ -static int gpiod_to_irq(const struct gpio_desc *desc) +int gpiod_to_irq(const struct gpio_desc *desc)  {  	struct gpio_chip	*chip;  	int			offset; @@ -1999,62 +2445,414 @@ static int gpiod_to_irq(const struct gpio_desc *desc)  	offset = gpio_chip_hwgpio(desc);  	return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO;  } +EXPORT_SYMBOL_GPL(gpiod_to_irq); -int __gpio_to_irq(unsigned gpio) +/** + * gpiod_lock_as_irq() - lock a GPIO to be used as IRQ + * @gpio: the GPIO line to lock as used for IRQ + * + * This is used directly by GPIO drivers that want to lock down + * a certain GPIO line to be used for IRQs. + */ +int gpiod_lock_as_irq(struct gpio_desc *desc)  { -	return gpiod_to_irq(gpio_to_desc(gpio)); +	if (!desc) +		return -EINVAL; + +	if (test_bit(FLAG_IS_OUT, &desc->flags)) { +		gpiod_err(desc, +			  "%s: tried to flag a GPIO set as output for IRQ\n", +			  __func__); +		return -EIO; +	} + +	set_bit(FLAG_USED_AS_IRQ, &desc->flags); +	return 0;  } -EXPORT_SYMBOL_GPL(__gpio_to_irq); +EXPORT_SYMBOL_GPL(gpiod_lock_as_irq); +int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset) +{ +	return gpiod_lock_as_irq(gpiochip_get_desc(chip, offset)); +} +EXPORT_SYMBOL_GPL(gpio_lock_as_irq); -/* There's no value in making it easy to inline GPIO calls that may sleep. - * Common examples include ones connected to I2C or SPI chips. +/** + * gpiod_unlock_as_irq() - unlock a GPIO used as IRQ + * @gpio: the GPIO line to unlock from IRQ usage + * + * This is used directly by GPIO drivers that want to indicate + * that a certain GPIO is no longer used exclusively for IRQ.   */ +void gpiod_unlock_as_irq(struct gpio_desc *desc) +{ +	if (!desc) +		return; + +	clear_bit(FLAG_USED_AS_IRQ, &desc->flags); +} +EXPORT_SYMBOL_GPL(gpiod_unlock_as_irq); -static int gpiod_get_value_cansleep(const struct gpio_desc *desc) +void gpio_unlock_as_irq(struct gpio_chip *chip, unsigned int offset) +{ +	return gpiod_unlock_as_irq(gpiochip_get_desc(chip, offset)); +} +EXPORT_SYMBOL_GPL(gpio_unlock_as_irq); + +/** + * gpiod_get_raw_value_cansleep() - return a gpio's raw value + * @desc: gpio whose value will be returned + * + * Return the GPIO's raw value, i.e. the value of the physical line disregarding + * its ACTIVE_LOW status. + * + * This function is to be called from contexts that can sleep. + */ +int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc) +{ +	might_sleep_if(extra_checks); +	if (!desc) +		return 0; +	return _gpiod_get_raw_value(desc); +} +EXPORT_SYMBOL_GPL(gpiod_get_raw_value_cansleep); + +/** + * gpiod_get_value_cansleep() - return a gpio's value + * @desc: gpio whose value will be returned + * + * Return the GPIO's logical value, i.e. taking the ACTIVE_LOW status into + * account. + * + * This function is to be called from contexts that can sleep. + */ +int gpiod_get_value_cansleep(const struct gpio_desc *desc)  { -	struct gpio_chip	*chip;  	int value; -	int offset;  	might_sleep_if(extra_checks);  	if (!desc)  		return 0; -	chip = desc->chip; -	offset = gpio_chip_hwgpio(desc); -	value = chip->get ? chip->get(chip, offset) : 0; -	trace_gpio_value(desc_to_gpio(desc), 1, value); + +	value = _gpiod_get_raw_value(desc); +	if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) +		value = !value; +  	return value;  } +EXPORT_SYMBOL_GPL(gpiod_get_value_cansleep); -int gpio_get_value_cansleep(unsigned gpio) +/** + * gpiod_set_raw_value_cansleep() - assign a gpio's raw value + * @desc: gpio whose value will be assigned + * @value: value to assign + * + * Set the raw value of the GPIO, i.e. the value of its physical line without + * regard for its ACTIVE_LOW status. + * + * This function is to be called from contexts that can sleep. + */ +void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value)  { -	return gpiod_get_value_cansleep(gpio_to_desc(gpio)); +	might_sleep_if(extra_checks); +	if (!desc) +		return; +	_gpiod_set_raw_value(desc, value);  } -EXPORT_SYMBOL_GPL(gpio_get_value_cansleep); +EXPORT_SYMBOL_GPL(gpiod_set_raw_value_cansleep); -static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value) +/** + * gpiod_set_value_cansleep() - assign a gpio's value + * @desc: gpio whose value will be assigned + * @value: value to assign + * + * Set the logical value of the GPIO, i.e. taking its ACTIVE_LOW status into + * account + * + * This function is to be called from contexts that can sleep. + */ +void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)  { -	struct gpio_chip	*chip; -  	might_sleep_if(extra_checks);  	if (!desc)  		return; -	chip = desc->chip; -	trace_gpio_value(desc_to_gpio(desc), 0, value); -	if (test_bit(FLAG_OPEN_DRAIN,  &desc->flags)) -		_gpio_set_open_drain_value(desc, value); -	else if (test_bit(FLAG_OPEN_SOURCE,  &desc->flags)) -		_gpio_set_open_source_value(desc, value); -	else -		chip->set(chip, gpio_chip_hwgpio(desc), value); + +	if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) +		value = !value; +	_gpiod_set_raw_value(desc, value); +} +EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep); + +/** + * gpiod_add_lookup_table() - register GPIO device consumers + * @table: table of consumers to register + */ +void gpiod_add_lookup_table(struct gpiod_lookup_table *table) +{ +	mutex_lock(&gpio_lookup_lock); + +	list_add_tail(&table->list, &gpio_lookup_list); + +	mutex_unlock(&gpio_lookup_lock); +} + +static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, +				      unsigned int idx, +				      enum gpio_lookup_flags *flags) +{ +	static const char *suffixes[] = { "gpios", "gpio" }; +	char prop_name[32]; /* 32 is max size of property name */ +	enum of_gpio_flags of_flags; +	struct gpio_desc *desc; +	unsigned int i; + +	for (i = 0; i < ARRAY_SIZE(suffixes); i++) { +		if (con_id) +			snprintf(prop_name, 32, "%s-%s", con_id, suffixes[i]); +		else +			snprintf(prop_name, 32, "%s", suffixes[i]); + +		desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx, +						&of_flags); +		if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER)) +			break; +	} + +	if (IS_ERR(desc)) +		return desc; + +	if (of_flags & OF_GPIO_ACTIVE_LOW) +		*flags |= GPIO_ACTIVE_LOW; + +	return desc; +} + +static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id, +					unsigned int idx, +					enum gpio_lookup_flags *flags) +{ +	struct acpi_gpio_info info; +	struct gpio_desc *desc; + +	desc = acpi_get_gpiod_by_index(dev, idx, &info); +	if (IS_ERR(desc)) +		return desc; + +	if (info.gpioint && info.active_low) +		*flags |= GPIO_ACTIVE_LOW; + +	return desc; +} + +static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev) +{ +	const char *dev_id = dev ? dev_name(dev) : NULL; +	struct gpiod_lookup_table *table; + +	mutex_lock(&gpio_lookup_lock); + +	list_for_each_entry(table, &gpio_lookup_list, list) { +		if (table->dev_id && dev_id) { +			/* +			 * Valid strings on both ends, must be identical to have +			 * a match +			 */ +			if (!strcmp(table->dev_id, dev_id)) +				goto found; +		} else { +			/* +			 * One of the pointers is NULL, so both must be to have +			 * a match +			 */ +			if (dev_id == table->dev_id) +				goto found; +		} +	} +	table = NULL; + +found: +	mutex_unlock(&gpio_lookup_lock); +	return table; +} + +static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, +				    unsigned int idx, +				    enum gpio_lookup_flags *flags) +{ +	struct gpio_desc *desc = ERR_PTR(-ENOENT); +	struct gpiod_lookup_table *table; +	struct gpiod_lookup *p; + +	table = gpiod_find_lookup_table(dev); +	if (!table) +		return desc; + +	for (p = &table->table[0]; p->chip_label; p++) { +		struct gpio_chip *chip; + +		/* idx must always match exactly */ +		if (p->idx != idx) +			continue; + +		/* If the lookup entry has a con_id, require exact match */ +		if (p->con_id && (!con_id || strcmp(p->con_id, con_id))) +			continue; + +		chip = find_chip_by_name(p->chip_label); + +		if (!chip) { +			dev_err(dev, "cannot find GPIO chip %s\n", +				p->chip_label); +			return ERR_PTR(-ENODEV); +		} + +		if (chip->ngpio <= p->chip_hwnum) { +			dev_err(dev, +				"requested GPIO %d is out of range [0..%d] for chip %s\n", +				idx, chip->ngpio, chip->label); +			return ERR_PTR(-EINVAL); +		} + +		desc = gpiochip_get_desc(chip, p->chip_hwnum); +		*flags = p->flags; + +		return desc; +	} + +	return desc; +} + +/** + * gpiod_get - obtain a GPIO for a given GPIO function + * @dev:	GPIO consumer, can be NULL for system-global GPIOs + * @con_id:	function within the GPIO consumer + * + * Return the GPIO descriptor corresponding to the function con_id of device + * dev, -ENOENT if no GPIO has been assigned to the requested function, or + * another IS_ERR() code if an error occured while trying to acquire the GPIO. + */ +struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id) +{ +	return gpiod_get_index(dev, con_id, 0);  } +EXPORT_SYMBOL_GPL(gpiod_get); -void gpio_set_value_cansleep(unsigned gpio, int value) +/** + * gpiod_get_optional - obtain an optional GPIO for a given GPIO function + * @dev: GPIO consumer, can be NULL for system-global GPIOs + * @con_id: function within the GPIO consumer + * + * This is equivalent to gpiod_get(), except that when no GPIO was assigned to + * the requested function it will return NULL. This is convenient for drivers + * that need to handle optional GPIOs. + */ +struct gpio_desc *__must_check gpiod_get_optional(struct device *dev, +						  const char *con_id)  { -	return gpiod_set_value_cansleep(gpio_to_desc(gpio), value); +	return gpiod_get_index_optional(dev, con_id, 0); +} +EXPORT_SYMBOL_GPL(gpiod_get_optional); + +/** + * gpiod_get_index - obtain a GPIO from a multi-index GPIO function + * @dev:	GPIO consumer, can be NULL for system-global GPIOs + * @con_id:	function within the GPIO consumer + * @idx:	index of the GPIO to obtain in the consumer + * + * This variant of gpiod_get() allows to access GPIOs other than the first + * defined one for functions that define several GPIOs. + * + * Return a valid GPIO descriptor, -ENOENT if no GPIO has been assigned to the + * requested function and/or index, or another IS_ERR() code if an error + * occured while trying to acquire the GPIO. + */ +struct gpio_desc *__must_check gpiod_get_index(struct device *dev, +					       const char *con_id, +					       unsigned int idx) +{ +	struct gpio_desc *desc = NULL; +	int status; +	enum gpio_lookup_flags flags = 0; + +	dev_dbg(dev, "GPIO lookup for consumer %s\n", con_id); + +	/* Using device tree? */ +	if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) { +		dev_dbg(dev, "using device tree for GPIO lookup\n"); +		desc = of_find_gpio(dev, con_id, idx, &flags); +	} else if (IS_ENABLED(CONFIG_ACPI) && dev && ACPI_HANDLE(dev)) { +		dev_dbg(dev, "using ACPI for GPIO lookup\n"); +		desc = acpi_find_gpio(dev, con_id, idx, &flags); +	} + +	/* +	 * Either we are not using DT or ACPI, or their lookup did not return +	 * a result. In that case, use platform lookup as a fallback. +	 */ +	if (!desc || desc == ERR_PTR(-ENOENT)) { +		dev_dbg(dev, "using lookup tables for GPIO lookup"); +		desc = gpiod_find(dev, con_id, idx, &flags); +	} + +	if (IS_ERR(desc)) { +		dev_dbg(dev, "lookup for GPIO %s failed\n", con_id); +		return desc; +	} + +	status = gpiod_request(desc, con_id); + +	if (status < 0) +		return ERR_PTR(status); + +	if (flags & GPIO_ACTIVE_LOW) +		set_bit(FLAG_ACTIVE_LOW, &desc->flags); +	if (flags & GPIO_OPEN_DRAIN) +		set_bit(FLAG_OPEN_DRAIN, &desc->flags); +	if (flags & GPIO_OPEN_SOURCE) +		set_bit(FLAG_OPEN_SOURCE, &desc->flags); + +	return desc; +} +EXPORT_SYMBOL_GPL(gpiod_get_index); + +/** + * gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO + *                            function + * @dev: GPIO consumer, can be NULL for system-global GPIOs + * @con_id: function within the GPIO consumer + * @index: index of the GPIO to obtain in the consumer + * + * This is equivalent to gpiod_get_index(), except that when no GPIO with the + * specified index was assigned to the requested function it will return NULL. + * This is convenient for drivers that need to handle optional GPIOs. + */ +struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev, +							const char *con_id, +							unsigned int index) +{ +	struct gpio_desc *desc; + +	desc = gpiod_get_index(dev, con_id, index); +	if (IS_ERR(desc)) { +		if (PTR_ERR(desc) == -ENOENT) +			return NULL; +	} + +	return desc; +} +EXPORT_SYMBOL_GPL(gpiod_get_index_optional); + +/** + * gpiod_put - dispose of a GPIO descriptor + * @desc:	GPIO descriptor to dispose of + * + * No descriptor can be used after gpiod_put() has been called on it. + */ +void gpiod_put(struct gpio_desc *desc) +{ +	gpiod_free(desc);  } -EXPORT_SYMBOL_GPL(gpio_set_value_cansleep); +EXPORT_SYMBOL_GPL(gpiod_put);  #ifdef CONFIG_DEBUG_FS @@ -2064,6 +2862,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)  	unsigned		gpio = chip->base;  	struct gpio_desc	*gdesc = &chip->desc[0];  	int			is_out; +	int			is_irq;  	for (i = 0; i < chip->ngpio; i++, gpio++, gdesc++) {  		if (!test_bit(FLAG_REQUESTED, &gdesc->flags)) @@ -2071,12 +2870,14 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)  		gpiod_get_direction(gdesc);  		is_out = test_bit(FLAG_IS_OUT, &gdesc->flags); -		seq_printf(s, " gpio-%-3d (%-20.20s) %s %s", +		is_irq = test_bit(FLAG_USED_AS_IRQ, &gdesc->flags); +		seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s",  			gpio, gdesc->label,  			is_out ? "out" : "in ",  			chip->get  				? (chip->get(chip, i) ? "hi" : "lo") -				: "?  "); +				: "?  ", +			is_irq ? "IRQ" : "   ");  		seq_printf(s, "\n");  	}  } diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h new file mode 100644 index 00000000000..1a4103dd38d --- /dev/null +++ b/drivers/gpio/gpiolib.h @@ -0,0 +1,54 @@ +/* + * Internal GPIO functions. + * + * Copyright (C) 2013, Intel Corporation + * Author: Mika Westerberg <mika.westerberg@linux.intel.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. + */ + +#ifndef GPIOLIB_H +#define GPIOLIB_H + +#include <linux/err.h> +#include <linux/device.h> + +enum of_gpio_flags; + +/** + * struct acpi_gpio_info - ACPI GPIO specific information + * @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo + * @active_low: in case of @gpioint, the pin is active low + */ +struct acpi_gpio_info { +	bool gpioint; +	bool active_low; +}; + +#ifdef CONFIG_ACPI +void acpi_gpiochip_add(struct gpio_chip *chip); +void acpi_gpiochip_remove(struct gpio_chip *chip); + +struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, +					  struct acpi_gpio_info *info); +#else +static inline void acpi_gpiochip_add(struct gpio_chip *chip) { } +static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { } + +static inline struct gpio_desc * +acpi_get_gpiod_by_index(struct device *dev, int index, +			struct acpi_gpio_info *info) +{ +	return ERR_PTR(-ENOSYS); +} +#endif + +int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label); +void gpiochip_free_own_desc(struct gpio_desc *desc); + +struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, +		   const char *list_name, int index, enum of_gpio_flags *flags); + +#endif /* GPIOLIB_H */  | 
