diff options
| author | 2018-08-28 09:58:03 -0700 | |
|---|---|---|
| committer | 2018-08-28 09:58:03 -0700 | |
| commit | ea4d65f14f6aaa53e379b93c5544245ef081b3e7 (patch) | |
| tree | a15485f4f1cf547a52b31fa8e16e14b9579b7200 /drivers/gpio | |
| parent | arm: dts: am4372: setup rtc as system-power-controller (diff) | |
| parent | ARM: dts: Fix file permission for am335x-osd3358-sm-red.dts (diff) | |
| download | wireguard-linux-ea4d65f14f6aaa53e379b93c5544245ef081b3e7.tar.xz wireguard-linux-ea4d65f14f6aaa53e379b93c5544245ef081b3e7.zip  | |
Merge branch 'perm-fix' into omap-for-v4.19/fixes-v2
Diffstat (limited to 'drivers/gpio')
44 files changed, 1594 insertions, 269 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 71c0ab46f216..4f52c3a8ec99 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -359,6 +359,15 @@ config GPIO_MPC8XXX  	  Say Y here if you're going to use hardware that connects to the  	  MPC512x/831x/834x/837x/8572/8610/QorIQ GPIOs. +config GPIO_MT7621 +	bool "Mediatek MT7621 GPIO Support" +	depends on SOC_MT7620 || SOC_MT7621 || COMPILE_TEST +	depends on OF_GPIO +	select GPIO_GENERIC +	select GPIOLIB_IRQCHIP +	help +	  Say yes here to support the Mediatek MT7621 SoC GPIO device +  config GPIO_MVEBU  	def_bool y  	depends on PLAT_ORION || ARCH_MVEBU @@ -684,7 +693,8 @@ config GPIO_IT87  	  Say yes here to support GPIO functionality of IT87xx Super I/O chips.  	  This driver is tested with ITE IT8728 and IT8732 Super I/O chips, and -	  supports the IT8761E, IT8620E and IT8628E Super I/O chip as well. +	  supports the IT8761E, IT8613, IT8620E, and IT8628E Super I/O chips as +	  well.  	  To compile this driver as a module, choose M here: the module will  	  be called gpio_it87 @@ -1039,6 +1049,12 @@ config GPIO_LP87565  	  This driver can also be built as a module. If so, the module will be  	  called gpio-lp87565. +config GPIO_MADERA +	tristate "Cirrus Logic Madera class codecs" +	depends on PINCTRL_MADERA +	help +	  Support for GPIOs on Cirrus Logic Madera class codecs. +  config GPIO_MAX77620  	tristate "GPIO support for PMIC MAX77620 and MAX20024"  	depends on MFD_MAX77620 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 1324c8f966a7..c256aff66a65 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -71,6 +71,7 @@ obj-$(CONFIG_ARCH_LPC32XX)	+= gpio-lpc32xx.o  obj-$(CONFIG_GPIO_LP873X)	+= gpio-lp873x.o  obj-$(CONFIG_GPIO_LP87565)	+= gpio-lp87565.o  obj-$(CONFIG_GPIO_LYNXPOINT)	+= gpio-lynxpoint.o +obj-$(CONFIG_GPIO_MADERA)	+= gpio-madera.o  obj-$(CONFIG_GPIO_MAX3191X)	+= gpio-max3191x.o  obj-$(CONFIG_GPIO_MAX730X)	+= gpio-max730x.o  obj-$(CONFIG_GPIO_MAX7300)	+= gpio-max7300.o @@ -88,6 +89,7 @@ obj-$(CONFIG_GPIO_MOCKUP)      += gpio-mockup.o  obj-$(CONFIG_GPIO_MPC5200)	+= gpio-mpc5200.o  obj-$(CONFIG_GPIO_MPC8XXX)	+= gpio-mpc8xxx.o  obj-$(CONFIG_GPIO_MSIC)		+= gpio-msic.o +obj-$(CONFIG_GPIO_MT7621)		+= gpio-mt7621.o  obj-$(CONFIG_GPIO_MVEBU)        += gpio-mvebu.o  obj-$(CONFIG_GPIO_MXC)		+= gpio-mxc.o  obj-$(CONFIG_GPIO_MXS)		+= gpio-mxs.o diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index b31ae16170e7..2342e154029b 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -12,6 +12,7 @@  #include <asm/div64.h>  #include <linux/clk.h>  #include <linux/gpio/driver.h> +#include <linux/gpio/aspeed.h>  #include <linux/hashtable.h>  #include <linux/init.h>  #include <linux/io.h> @@ -22,6 +23,15 @@  #include <linux/spinlock.h>  #include <linux/string.h> +/* + * These two headers aren't meant to be used by GPIO drivers. We need + * them in order to access gpio_chip_hwgpio() which we need to implement + * the aspeed specific API which allows the coprocessor to request + * access to some GPIOs and to arbitrate between coprocessor and ARM. + */ +#include <linux/gpio/consumer.h> +#include "gpiolib.h" +  struct aspeed_bank_props {  	unsigned int bank;  	u32 input; @@ -56,83 +66,130 @@ struct aspeed_gpio {  	struct clk *clk;  	u32 *dcache; +	u8 *cf_copro_bankmap;  };  struct aspeed_gpio_bank { -	uint16_t	val_regs; +	uint16_t	val_regs;	/* +0: Rd: read input value, Wr: set write latch +					 * +4: Rd/Wr: Direction (0=in, 1=out) +					 */ +	uint16_t	rdata_reg;	/*     Rd: read write latch, Wr: <none>  */  	uint16_t	irq_regs;  	uint16_t	debounce_regs;  	uint16_t	tolerance_regs; +	uint16_t	cmdsrc_regs;  	const char	names[4][3];  }; +/* + * Note: The "value" register returns the input value sampled on the + *       line even when the GPIO is configured as an output. Since + *       that input goes through synchronizers, writing, then reading + *       back may not return the written value right away. + * + *       The "rdata" register returns the content of the write latch + *       and thus can be used to read back what was last written + *       reliably. + */ +  static const int debounce_timers[4] = { 0x00, 0x50, 0x54, 0x58 }; +static const struct aspeed_gpio_copro_ops *copro_ops; +static void *copro_data; +  static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {  	{  		.val_regs = 0x0000, +		.rdata_reg = 0x00c0,  		.irq_regs = 0x0008,  		.debounce_regs = 0x0040,  		.tolerance_regs = 0x001c, +		.cmdsrc_regs = 0x0060,  		.names = { "A", "B", "C", "D" },  	},  	{  		.val_regs = 0x0020, +		.rdata_reg = 0x00c4,  		.irq_regs = 0x0028,  		.debounce_regs = 0x0048,  		.tolerance_regs = 0x003c, +		.cmdsrc_regs = 0x0068,  		.names = { "E", "F", "G", "H" },  	},  	{  		.val_regs = 0x0070, +		.rdata_reg = 0x00c8,  		.irq_regs = 0x0098,  		.debounce_regs = 0x00b0,  		.tolerance_regs = 0x00ac, +		.cmdsrc_regs = 0x0090,  		.names = { "I", "J", "K", "L" },  	},  	{  		.val_regs = 0x0078, +		.rdata_reg = 0x00cc,  		.irq_regs = 0x00e8,  		.debounce_regs = 0x0100,  		.tolerance_regs = 0x00fc, +		.cmdsrc_regs = 0x00e0,  		.names = { "M", "N", "O", "P" },  	},  	{  		.val_regs = 0x0080, +		.rdata_reg = 0x00d0,  		.irq_regs = 0x0118,  		.debounce_regs = 0x0130,  		.tolerance_regs = 0x012c, +		.cmdsrc_regs = 0x0110,  		.names = { "Q", "R", "S", "T" },  	},  	{  		.val_regs = 0x0088, +		.rdata_reg = 0x00d4,  		.irq_regs = 0x0148,  		.debounce_regs = 0x0160,  		.tolerance_regs = 0x015c, +		.cmdsrc_regs = 0x0140,  		.names = { "U", "V", "W", "X" },  	},  	{  		.val_regs = 0x01E0, +		.rdata_reg = 0x00d8,  		.irq_regs = 0x0178,  		.debounce_regs = 0x0190,  		.tolerance_regs = 0x018c, +		.cmdsrc_regs = 0x0170,  		.names = { "Y", "Z", "AA", "AB" },  	},  	{  		.val_regs = 0x01e8, +		.rdata_reg = 0x00dc,  		.irq_regs = 0x01a8,  		.debounce_regs = 0x01c0,  		.tolerance_regs = 0x01bc, +		.cmdsrc_regs = 0x01a0,  		.names = { "AC", "", "", "" },  	},  }; -#define GPIO_BANK(x)	((x) >> 5) -#define GPIO_OFFSET(x)	((x) & 0x1f) -#define GPIO_BIT(x)	BIT(GPIO_OFFSET(x)) +enum aspeed_gpio_reg { +	reg_val, +	reg_rdata, +	reg_dir, +	reg_irq_enable, +	reg_irq_type0, +	reg_irq_type1, +	reg_irq_type2, +	reg_irq_status, +	reg_debounce_sel1, +	reg_debounce_sel2, +	reg_tolerance, +	reg_cmdsrc0, +	reg_cmdsrc1, +}; -#define GPIO_DATA	0x00 -#define GPIO_DIR	0x04 +#define GPIO_VAL_VALUE	0x00 +#define GPIO_VAL_DIR	0x04  #define GPIO_IRQ_ENABLE	0x00  #define GPIO_IRQ_TYPE0	0x04 @@ -143,6 +200,53 @@ static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {  #define GPIO_DEBOUNCE_SEL1 0x00  #define GPIO_DEBOUNCE_SEL2 0x04 +#define GPIO_CMDSRC_0	0x00 +#define GPIO_CMDSRC_1	0x04 +#define  GPIO_CMDSRC_ARM		0 +#define  GPIO_CMDSRC_LPC		1 +#define  GPIO_CMDSRC_COLDFIRE		2 +#define  GPIO_CMDSRC_RESERVED		3 + +/* This will be resolved at compile time */ +static inline void __iomem *bank_reg(struct aspeed_gpio *gpio, +				     const struct aspeed_gpio_bank *bank, +				     const enum aspeed_gpio_reg reg) +{ +	switch (reg) { +	case reg_val: +		return gpio->base + bank->val_regs + GPIO_VAL_VALUE; +	case reg_rdata: +		return gpio->base + bank->rdata_reg; +	case reg_dir: +		return gpio->base + bank->val_regs + GPIO_VAL_DIR; +	case reg_irq_enable: +		return gpio->base + bank->irq_regs + GPIO_IRQ_ENABLE; +	case reg_irq_type0: +		return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE0; +	case reg_irq_type1: +		return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE1; +	case reg_irq_type2: +		return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE2; +	case reg_irq_status: +		return gpio->base + bank->irq_regs + GPIO_IRQ_STATUS; +	case reg_debounce_sel1: +		return gpio->base + bank->debounce_regs + GPIO_DEBOUNCE_SEL1; +	case reg_debounce_sel2: +		return gpio->base + bank->debounce_regs + GPIO_DEBOUNCE_SEL2; +	case reg_tolerance: +		return gpio->base + bank->tolerance_regs; +	case reg_cmdsrc0: +		return gpio->base + bank->cmdsrc_regs + GPIO_CMDSRC_0; +	case reg_cmdsrc1: +		return gpio->base + bank->cmdsrc_regs + GPIO_CMDSRC_1; +	} +	BUG(); +} + +#define GPIO_BANK(x)	((x) >> 5) +#define GPIO_OFFSET(x)	((x) & 0x1f) +#define GPIO_BIT(x)	BIT(GPIO_OFFSET(x)) +  #define _GPIO_SET_DEBOUNCE(t, o, i) ((!!((t) & BIT(i))) << GPIO_OFFSET(o))  #define GPIO_SET_DEBOUNCE1(t, o) _GPIO_SET_DEBOUNCE(t, o, 1)  #define GPIO_SET_DEBOUNCE2(t, o) _GPIO_SET_DEBOUNCE(t, o, 0) @@ -201,18 +305,80 @@ static inline bool have_output(struct aspeed_gpio *gpio, unsigned int offset)  	return !props || (props->output & GPIO_BIT(offset));  } -static void __iomem *bank_val_reg(struct aspeed_gpio *gpio, -		const struct aspeed_gpio_bank *bank, -		unsigned int reg) +static void aspeed_gpio_change_cmd_source(struct aspeed_gpio *gpio, +					  const struct aspeed_gpio_bank *bank, +					  int bindex, int cmdsrc)  { -	return gpio->base + bank->val_regs + reg; +	void __iomem *c0 = bank_reg(gpio, bank, reg_cmdsrc0); +	void __iomem *c1 = bank_reg(gpio, bank, reg_cmdsrc1); +	u32 bit, reg; + +	/* +	 * Each register controls 4 banks, so take the bottom 2 +	 * bits of the bank index, and use them to select the +	 * right control bit (0, 8, 16 or 24). +	 */ +	bit = BIT((bindex & 3) << 3); + +	/* Source 1 first to avoid illegal 11 combination */ +	reg = ioread32(c1); +	if (cmdsrc & 2) +		reg |= bit; +	else +		reg &= ~bit; +	iowrite32(reg, c1); + +	/* Then Source 0 */ +	reg = ioread32(c0); +	if (cmdsrc & 1) +		reg |= bit; +	else +		reg &= ~bit; +	iowrite32(reg, c0);  } -static void __iomem *bank_irq_reg(struct aspeed_gpio *gpio, -		const struct aspeed_gpio_bank *bank, -		unsigned int reg) +static bool aspeed_gpio_copro_request(struct aspeed_gpio *gpio, +				      unsigned int offset)  { -	return gpio->base + bank->irq_regs + reg; +	const struct aspeed_gpio_bank *bank = to_bank(offset); + +	if (!copro_ops || !gpio->cf_copro_bankmap) +		return false; +	if (!gpio->cf_copro_bankmap[offset >> 3]) +		return false; +	if (!copro_ops->request_access) +		return false; + +	/* Pause the coprocessor */ +	copro_ops->request_access(copro_data); + +	/* Change command source back to ARM */ +	aspeed_gpio_change_cmd_source(gpio, bank, offset >> 3, GPIO_CMDSRC_ARM); + +	/* Update cache */ +	gpio->dcache[GPIO_BANK(offset)] = ioread32(bank_reg(gpio, bank, reg_rdata)); + +	return true; +} + +static void aspeed_gpio_copro_release(struct aspeed_gpio *gpio, +				      unsigned int offset) +{ +	const struct aspeed_gpio_bank *bank = to_bank(offset); + +	if (!copro_ops || !gpio->cf_copro_bankmap) +		return; +	if (!gpio->cf_copro_bankmap[offset >> 3]) +		return; +	if (!copro_ops->release_access) +		return; + +	/* Change command source back to ColdFire */ +	aspeed_gpio_change_cmd_source(gpio, bank, offset >> 3, +				      GPIO_CMDSRC_COLDFIRE); + +	/* Restart the coprocessor */ +	copro_ops->release_access(copro_data);  }  static int aspeed_gpio_get(struct gpio_chip *gc, unsigned int offset) @@ -220,8 +386,7 @@ static int aspeed_gpio_get(struct gpio_chip *gc, unsigned int offset)  	struct aspeed_gpio *gpio = gpiochip_get_data(gc);  	const struct aspeed_gpio_bank *bank = to_bank(offset); -	return !!(ioread32(bank_val_reg(gpio, bank, GPIO_DATA)) -			& GPIO_BIT(offset)); +	return !!(ioread32(bank_reg(gpio, bank, reg_val)) & GPIO_BIT(offset));  }  static void __aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset, @@ -232,7 +397,7 @@ static void __aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,  	void __iomem *addr;  	u32 reg; -	addr = bank_val_reg(gpio, bank, GPIO_DATA); +	addr = bank_reg(gpio, bank, reg_val);  	reg = gpio->dcache[GPIO_BANK(offset)];  	if (val) @@ -249,11 +414,15 @@ static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,  {  	struct aspeed_gpio *gpio = gpiochip_get_data(gc);  	unsigned long flags; +	bool copro;  	spin_lock_irqsave(&gpio->lock, flags); +	copro = aspeed_gpio_copro_request(gpio, offset);  	__aspeed_gpio_set(gc, offset, val); +	if (copro) +		aspeed_gpio_copro_release(gpio, offset);  	spin_unlock_irqrestore(&gpio->lock, flags);  } @@ -261,7 +430,9 @@ static int aspeed_gpio_dir_in(struct gpio_chip *gc, unsigned int offset)  {  	struct aspeed_gpio *gpio = gpiochip_get_data(gc);  	const struct aspeed_gpio_bank *bank = to_bank(offset); +	void __iomem *addr = bank_reg(gpio, bank, reg_dir);  	unsigned long flags; +	bool copro;  	u32 reg;  	if (!have_input(gpio, offset)) @@ -269,8 +440,13 @@ static int aspeed_gpio_dir_in(struct gpio_chip *gc, unsigned int offset)  	spin_lock_irqsave(&gpio->lock, flags); -	reg = ioread32(bank_val_reg(gpio, bank, GPIO_DIR)); -	iowrite32(reg & ~GPIO_BIT(offset), bank_val_reg(gpio, bank, GPIO_DIR)); +	reg = ioread32(addr); +	reg &= ~GPIO_BIT(offset); + +	copro = aspeed_gpio_copro_request(gpio, offset); +	iowrite32(reg, addr); +	if (copro) +		aspeed_gpio_copro_release(gpio, offset);  	spin_unlock_irqrestore(&gpio->lock, flags); @@ -282,7 +458,9 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc,  {  	struct aspeed_gpio *gpio = gpiochip_get_data(gc);  	const struct aspeed_gpio_bank *bank = to_bank(offset); +	void __iomem *addr = bank_reg(gpio, bank, reg_dir);  	unsigned long flags; +	bool copro;  	u32 reg;  	if (!have_output(gpio, offset)) @@ -290,10 +468,15 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc,  	spin_lock_irqsave(&gpio->lock, flags); +	reg = ioread32(addr); +	reg |= GPIO_BIT(offset); + +	copro = aspeed_gpio_copro_request(gpio, offset);  	__aspeed_gpio_set(gc, offset, val); -	reg = ioread32(bank_val_reg(gpio, bank, GPIO_DIR)); -	iowrite32(reg | GPIO_BIT(offset), bank_val_reg(gpio, bank, GPIO_DIR)); +	iowrite32(reg, addr); +	if (copro) +		aspeed_gpio_copro_release(gpio, offset);  	spin_unlock_irqrestore(&gpio->lock, flags);  	return 0; @@ -314,7 +497,7 @@ static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)  	spin_lock_irqsave(&gpio->lock, flags); -	val = ioread32(bank_val_reg(gpio, bank, GPIO_DIR)) & GPIO_BIT(offset); +	val = ioread32(bank_reg(gpio, bank, reg_dir)) & GPIO_BIT(offset);  	spin_unlock_irqrestore(&gpio->lock, flags); @@ -323,24 +506,23 @@ static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)  }  static inline int irqd_to_aspeed_gpio_data(struct irq_data *d, -		struct aspeed_gpio **gpio, -		const struct aspeed_gpio_bank **bank, -		u32 *bit) +					   struct aspeed_gpio **gpio, +					   const struct aspeed_gpio_bank **bank, +					   u32 *bit, int *offset)  { -	int offset;  	struct aspeed_gpio *internal; -	offset = irqd_to_hwirq(d); +	*offset = irqd_to_hwirq(d);  	internal = irq_data_get_irq_chip_data(d);  	/* This might be a bit of a questionable place to check */ -	if (!have_irq(internal, offset)) +	if (!have_irq(internal, *offset))  		return -ENOTSUPP;  	*gpio = internal; -	*bank = to_bank(offset); -	*bit = GPIO_BIT(offset); +	*bank = to_bank(*offset); +	*bit = GPIO_BIT(*offset);  	return 0;  } @@ -351,17 +533,23 @@ static void aspeed_gpio_irq_ack(struct irq_data *d)  	struct aspeed_gpio *gpio;  	unsigned long flags;  	void __iomem *status_addr; +	int rc, offset; +	bool copro;  	u32 bit; -	int rc; -	rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit); +	rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit, &offset);  	if (rc)  		return; -	status_addr = bank_irq_reg(gpio, bank, GPIO_IRQ_STATUS); +	status_addr = bank_reg(gpio, bank, reg_irq_status);  	spin_lock_irqsave(&gpio->lock, flags); +	copro = aspeed_gpio_copro_request(gpio, offset); +  	iowrite32(bit, status_addr); + +	if (copro) +		aspeed_gpio_copro_release(gpio, offset);  	spin_unlock_irqrestore(&gpio->lock, flags);  } @@ -372,15 +560,17 @@ static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set)  	unsigned long flags;  	u32 reg, bit;  	void __iomem *addr; -	int rc; +	int rc, offset; +	bool copro; -	rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit); +	rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit, &offset);  	if (rc)  		return; -	addr = bank_irq_reg(gpio, bank, GPIO_IRQ_ENABLE); +	addr = bank_reg(gpio, bank, reg_irq_enable);  	spin_lock_irqsave(&gpio->lock, flags); +	copro = aspeed_gpio_copro_request(gpio, offset);  	reg = ioread32(addr);  	if (set) @@ -389,6 +579,8 @@ static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set)  		reg &= ~bit;  	iowrite32(reg, addr); +	if (copro) +		aspeed_gpio_copro_release(gpio, offset);  	spin_unlock_irqrestore(&gpio->lock, flags);  } @@ -413,9 +605,10 @@ static int aspeed_gpio_set_type(struct irq_data *d, unsigned int type)  	struct aspeed_gpio *gpio;  	unsigned long flags;  	void __iomem *addr; -	int rc; +	int rc, offset; +	bool copro; -	rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit); +	rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit, &offset);  	if (rc)  		return -EINVAL; @@ -441,22 +634,25 @@ static int aspeed_gpio_set_type(struct irq_data *d, unsigned int type)  	}  	spin_lock_irqsave(&gpio->lock, flags); +	copro = aspeed_gpio_copro_request(gpio, offset); -	addr = bank_irq_reg(gpio, bank, GPIO_IRQ_TYPE0); +	addr = bank_reg(gpio, bank, reg_irq_type0);  	reg = ioread32(addr);  	reg = (reg & ~bit) | type0;  	iowrite32(reg, addr); -	addr = bank_irq_reg(gpio, bank, GPIO_IRQ_TYPE1); +	addr = bank_reg(gpio, bank, reg_irq_type1);  	reg = ioread32(addr);  	reg = (reg & ~bit) | type1;  	iowrite32(reg, addr); -	addr = bank_irq_reg(gpio, bank, GPIO_IRQ_TYPE2); +	addr = bank_reg(gpio, bank, reg_irq_type2);  	reg = ioread32(addr);  	reg = (reg & ~bit) | type2;  	iowrite32(reg, addr); +	if (copro) +		aspeed_gpio_copro_release(gpio, offset);  	spin_unlock_irqrestore(&gpio->lock, flags);  	irq_set_handler_locked(d, handler); @@ -477,7 +673,7 @@ static void aspeed_gpio_irq_handler(struct irq_desc *desc)  	for (i = 0; i < ARRAY_SIZE(aspeed_gpio_banks); i++) {  		const struct aspeed_gpio_bank *bank = &aspeed_gpio_banks[i]; -		reg = ioread32(bank_irq_reg(data, bank, GPIO_IRQ_STATUS)); +		reg = ioread32(bank_reg(data, bank, reg_irq_status));  		for_each_set_bit(p, ®, 32) {  			girq = irq_find_mapping(gc->irq.domain, i * 32 + p); @@ -549,21 +745,27 @@ static int aspeed_gpio_reset_tolerance(struct gpio_chip *chip,  					unsigned int offset, bool enable)  {  	struct aspeed_gpio *gpio = gpiochip_get_data(chip); -	const struct aspeed_gpio_bank *bank;  	unsigned long flags; +	void __iomem *treg; +	bool copro;  	u32 val; -	bank = to_bank(offset); +	treg = bank_reg(gpio, to_bank(offset), reg_tolerance);  	spin_lock_irqsave(&gpio->lock, flags); -	val = readl(gpio->base + bank->tolerance_regs); +	copro = aspeed_gpio_copro_request(gpio, offset); + +	val = readl(treg);  	if (enable)  		val |= GPIO_BIT(offset);  	else  		val &= ~GPIO_BIT(offset); -	writel(val, gpio->base + bank->tolerance_regs); +	writel(val, treg); + +	if (copro) +		aspeed_gpio_copro_release(gpio, offset);  	spin_unlock_irqrestore(&gpio->lock, flags);  	return 0; @@ -582,13 +784,6 @@ static void aspeed_gpio_free(struct gpio_chip *chip, unsigned int offset)  	pinctrl_gpio_free(chip->base + offset);  } -static inline void __iomem *bank_debounce_reg(struct aspeed_gpio *gpio, -		const struct aspeed_gpio_bank *bank, -		unsigned int reg) -{ -	return gpio->base + bank->debounce_regs + reg; -} -  static int usecs_to_cycles(struct aspeed_gpio *gpio, unsigned long usecs,  		u32 *cycles)  { @@ -666,11 +861,14 @@ static void configure_timer(struct aspeed_gpio *gpio, unsigned int offset,  	void __iomem *addr;  	u32 val; -	addr = bank_debounce_reg(gpio, bank, GPIO_DEBOUNCE_SEL1); +	/* Note: Debounce timer isn't under control of the command +	 * source registers, so no need to sync with the coprocessor +	 */ +	addr = bank_reg(gpio, bank, reg_debounce_sel1);  	val = ioread32(addr);  	iowrite32((val & ~mask) | GPIO_SET_DEBOUNCE1(timer, offset), addr); -	addr = bank_debounce_reg(gpio, bank, GPIO_DEBOUNCE_SEL2); +	addr = bank_reg(gpio, bank, reg_debounce_sel2);  	val = ioread32(addr);  	iowrite32((val & ~mask) | GPIO_SET_DEBOUNCE2(timer, offset), addr);  } @@ -812,6 +1010,111 @@ static int aspeed_gpio_set_config(struct gpio_chip *chip, unsigned int offset,  	return -ENOTSUPP;  } +/** + * aspeed_gpio_copro_set_ops - Sets the callbacks used for handhsaking with + *                             the coprocessor for shared GPIO banks + * @ops: The callbacks + * @data: Pointer passed back to the callbacks + */ +int aspeed_gpio_copro_set_ops(const struct aspeed_gpio_copro_ops *ops, void *data) +{ +	copro_data = data; +	copro_ops = ops; + +	return 0; +} +EXPORT_SYMBOL_GPL(aspeed_gpio_copro_set_ops); + +/** + * aspeed_gpio_copro_grab_gpio - Mark a GPIO used by the coprocessor. The entire + *                               bank gets marked and any access from the ARM will + *                               result in handshaking via callbacks. + * @desc: The GPIO to be marked + * @vreg_offset: If non-NULL, returns the value register offset in the GPIO space + * @dreg_offset: If non-NULL, returns the data latch register offset in the GPIO space + * @bit: If non-NULL, returns the bit number of the GPIO in the registers + */ +int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc, +				u16 *vreg_offset, u16 *dreg_offset, u8 *bit) +{ +	struct gpio_chip *chip = gpiod_to_chip(desc); +	struct aspeed_gpio *gpio = gpiochip_get_data(chip); +	int rc = 0, bindex, offset = gpio_chip_hwgpio(desc); +	const struct aspeed_gpio_bank *bank = to_bank(offset); +	unsigned long flags; + +	if (!gpio->cf_copro_bankmap) +		gpio->cf_copro_bankmap = kzalloc(gpio->config->nr_gpios >> 3, GFP_KERNEL); +	if (!gpio->cf_copro_bankmap) +		return -ENOMEM; +	if (offset < 0 || offset > gpio->config->nr_gpios) +		return -EINVAL; +	bindex = offset >> 3; + +	spin_lock_irqsave(&gpio->lock, flags); + +	/* Sanity check, this shouldn't happen */ +	if (gpio->cf_copro_bankmap[bindex] == 0xff) { +		rc = -EIO; +		goto bail; +	} +	gpio->cf_copro_bankmap[bindex]++; + +	/* Switch command source */ +	if (gpio->cf_copro_bankmap[bindex] == 1) +		aspeed_gpio_change_cmd_source(gpio, bank, bindex, +					      GPIO_CMDSRC_COLDFIRE); + +	if (vreg_offset) +		*vreg_offset = bank->val_regs; +	if (dreg_offset) +		*dreg_offset = bank->rdata_reg; +	if (bit) +		*bit = GPIO_OFFSET(offset); + bail: +	spin_unlock_irqrestore(&gpio->lock, flags); +	return rc; +} +EXPORT_SYMBOL_GPL(aspeed_gpio_copro_grab_gpio); + +/** + * aspeed_gpio_copro_release_gpio - Unmark a GPIO used by the coprocessor. + * @desc: The GPIO to be marked + */ +int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc) +{ +	struct gpio_chip *chip = gpiod_to_chip(desc); +	struct aspeed_gpio *gpio = gpiochip_get_data(chip); +	int rc = 0, bindex, offset = gpio_chip_hwgpio(desc); +	const struct aspeed_gpio_bank *bank = to_bank(offset); +	unsigned long flags; + +	if (!gpio->cf_copro_bankmap) +		return -ENXIO; + +	if (offset < 0 || offset > gpio->config->nr_gpios) +		return -EINVAL; +	bindex = offset >> 3; + +	spin_lock_irqsave(&gpio->lock, flags); + +	/* Sanity check, this shouldn't happen */ +	if (gpio->cf_copro_bankmap[bindex] == 0) { +		rc = -EIO; +		goto bail; +	} +	gpio->cf_copro_bankmap[bindex]--; + +	/* Switch command source */ +	if (gpio->cf_copro_bankmap[bindex] == 0) +		aspeed_gpio_change_cmd_source(gpio, bank, bindex, +					      GPIO_CMDSRC_ARM); + bail: +	spin_unlock_irqrestore(&gpio->lock, flags); +	return rc; +} +EXPORT_SYMBOL_GPL(aspeed_gpio_copro_release_gpio); +  /*   * Any banks not specified in a struct aspeed_bank_props array are assumed to   * have the properties: @@ -902,11 +1205,18 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)  	if (!gpio->dcache)  		return -ENOMEM; -	/* Populate it with initial values read from the HW */ +	/* +	 * Populate it with initial values read from the HW and switch +	 * all command sources to the ARM by default +	 */  	for (i = 0; i < banks; i++) {  		const struct aspeed_gpio_bank *bank = &aspeed_gpio_banks[i]; -		gpio->dcache[i] = ioread32(gpio->base + bank->val_regs + -					   GPIO_DATA); +		void __iomem *addr = bank_reg(gpio, bank, reg_rdata); +		gpio->dcache[i] = ioread32(addr); +		aspeed_gpio_change_cmd_source(gpio, bank, 0, GPIO_CMDSRC_ARM); +		aspeed_gpio_change_cmd_source(gpio, bank, 1, GPIO_CMDSRC_ARM); +		aspeed_gpio_change_cmd_source(gpio, bank, 2, GPIO_CMDSRC_ARM); +		aspeed_gpio_change_cmd_source(gpio, bank, 3, GPIO_CMDSRC_ARM);  	}  	rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c index 684e9d6d6623..0a553d676042 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c @@ -51,7 +51,7 @@ static u32 ath79_gpio_read(struct ath79_gpio_ctrl *ctrl, unsigned reg)  static void ath79_gpio_write(struct ath79_gpio_ctrl *ctrl,  			unsigned reg, u32 val)  { -	return writel(val, ctrl->base + reg); +	writel(val, ctrl->base + reg);  }  static bool ath79_gpio_update_bits( diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c index 00272fa7cc4f..d0707fc23afd 100644 --- a/drivers/gpio/gpio-bcm-kona.c +++ b/drivers/gpio/gpio-bcm-kona.c @@ -485,12 +485,14 @@ static void bcm_kona_gpio_irq_handler(struct irq_desc *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); +	int ret; -	if (gpiochip_lock_as_irq(&kona_gpio->gpio_chip, d->hwirq)) { +	ret = gpiochip_lock_as_irq(&kona_gpio->gpio_chip, d->hwirq); +	if (ret) {  		dev_err(kona_gpio->gpio_chip.parent,  			"unable to lock HW IRQ %lu for IRQ\n",  			d->hwirq); -		return -EINVAL; +		return ret;  	}  	return 0;  } diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 035a454eca43..a5ece8ea79bc 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -167,8 +167,8 @@ of_err:  static int davinci_gpio_probe(struct platform_device *pdev)  {  	static int ctrl_num, bank_base; -	int gpio, bank, ret = 0; -	unsigned ngpio, nbank; +	int gpio, bank, i, ret = 0; +	unsigned int ngpio, nbank, nirq;  	struct davinci_gpio_controller *chips;  	struct davinci_gpio_platform_data *pdata;  	struct device *dev = &pdev->dev; @@ -197,6 +197,16 @@ static int davinci_gpio_probe(struct platform_device *pdev)  	if (WARN_ON(ARCH_NR_GPIOS < ngpio))  		ngpio = ARCH_NR_GPIOS; +	/* +	 * If there are unbanked interrupts then the number of +	 * interrupts is equal to number of gpios else all are banked so +	 * number of interrupts is equal to number of banks(each with 16 gpios) +	 */ +	if (pdata->gpio_unbanked) +		nirq = pdata->gpio_unbanked; +	else +		nirq = DIV_ROUND_UP(ngpio, 16); +  	nbank = DIV_ROUND_UP(ngpio, 32);  	chips = devm_kcalloc(dev,  			     nbank, sizeof(struct davinci_gpio_controller), @@ -209,6 +219,15 @@ static int davinci_gpio_probe(struct platform_device *pdev)  	if (IS_ERR(gpio_base))  		return PTR_ERR(gpio_base); +	for (i = 0; i < nirq; i++) { +		chips->irqs[i] = platform_get_irq(pdev, i); +		if (chips->irqs[i] < 0) { +			dev_info(dev, "IRQ not populated, err = %d\n", +				 chips->irqs[i]); +			return chips->irqs[i]; +		} +	} +  	snprintf(label, MAX_LABEL_SIZE, "davinci_gpio.%d", ctrl_num++);  	chips->chip.label = devm_kstrdup(dev, label, GFP_KERNEL);  		if (!chips->chip.label) @@ -377,7 +396,7 @@ static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset)  	 * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs).  	 */  	if (offset < d->gpio_unbanked) -		return d->base_irq + offset; +		return d->irqs[offset];  	else  		return -ENODEV;  } @@ -386,11 +405,18 @@ static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger)  {  	struct davinci_gpio_controller *d;  	struct davinci_gpio_regs __iomem *g; -	u32 mask; +	u32 mask, i;  	d = (struct davinci_gpio_controller *)irq_data_get_irq_handler_data(data);  	g = (struct davinci_gpio_regs __iomem *)d->regs[0]; -	mask = __gpio_mask(data->irq - d->base_irq); +	for (i = 0; i < MAX_INT_PER_BANK; i++) +		if (data->irq == d->irqs[i]) +			break; + +	if (i == MAX_INT_PER_BANK) +		return -EINVAL; + +	mask = __gpio_mask(i);  	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))  		return -EINVAL; @@ -459,9 +485,8 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)  	int		ret;  	struct clk	*clk;  	u32		binten = 0; -	unsigned	ngpio, bank_irq; +	unsigned	ngpio;  	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; @@ -481,24 +506,13 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)  		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; -	} - -	bank_irq = res->start; - -	if (!bank_irq) { -		dev_err(dev, "Invalid IRQ resource\n"); -		return -ENODEV; -	}  	clk = devm_clk_get(dev, "gpio");  	if (IS_ERR(clk)) {  		dev_err(dev, "Error %ld getting gpio clock\n", PTR_ERR(clk));  		return PTR_ERR(clk);  	} +  	ret = clk_prepare_enable(clk);  	if (ret)  		return ret; @@ -538,12 +552,11 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)  	if (pdata->gpio_unbanked) {  		/* pass "bank 0" GPIO IRQs to AINTC */  		chips->chip.to_irq = gpio_to_irq_unbanked; -		chips->base_irq = bank_irq;  		chips->gpio_unbanked = pdata->gpio_unbanked;  		binten = GENMASK(pdata->gpio_unbanked / 16, 0);  		/* AINTC handles mask/unmask; GPIO handles triggering */ -		irq = bank_irq; +		irq = chips->irqs[0];  		irq_chip = gpio_get_irq_chip(irq);  		irq_chip->name = "GPIO-AINTC";  		irq_chip->irq_set_type = gpio_irq_type_unbanked; @@ -554,10 +567,11 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)  		writel_relaxed(~0, &g->set_rising);  		/* set the direct IRQs up to use that irqchip */ -		for (gpio = 0; gpio < pdata->gpio_unbanked; gpio++, irq++) { -			irq_set_chip(irq, irq_chip); -			irq_set_handler_data(irq, chips); -			irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH); +		for (gpio = 0; gpio < pdata->gpio_unbanked; gpio++) { +			irq_set_chip(chips->irqs[gpio], irq_chip); +			irq_set_handler_data(chips->irqs[gpio], chips); +			irq_set_status_flags(chips->irqs[gpio], +					     IRQ_TYPE_EDGE_BOTH);  		}  		goto done; @@ -567,7 +581,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)  	 * Or, AINTC can handle IRQs for banks of 16 GPIO IRQs, which we  	 * then chain through our own handler.  	 */ -	for (gpio = 0, bank = 0; gpio < ngpio; bank++, bank_irq++, gpio += 16) { +	for (gpio = 0, bank = 0; gpio < ngpio; bank++, gpio += 16) {  		/* disabled by default, enabled only as needed  		 * There are register sets for 32 GPIOs. 2 banks of 16  		 * GPIOs are covered by each set of registers hence divide by 2 @@ -594,8 +608,8 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)  		irqdata->bank_num = bank;  		irqdata->chip = chips; -		irq_set_chained_handler_and_data(bank_irq, gpio_irq_handler, -						 irqdata); +		irq_set_chained_handler_and_data(chips->irqs[bank], +						 gpio_irq_handler, irqdata);  		binten |= BIT(bank);  	} diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 7a2de3de6571..28da700f5f52 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -255,11 +255,13 @@ 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 gpio_chip *gc = &gpio->ports[0].gc; +	int ret; -	if (gpiochip_lock_as_irq(gc, irqd_to_hwirq(d))) { +	ret = gpiochip_lock_as_irq(gc, irqd_to_hwirq(d)); +	if (ret) {  		dev_err(gpio->dev, "unable to lock HW IRQ %lu for IRQ\n",  			irqd_to_hwirq(d)); -		return -EINVAL; +		return ret;  	}  	return 0;  } diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index 2b466b80e70a..982e699a5b81 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -101,12 +101,14 @@ static void em_gio_irq_enable(struct irq_data *d)  static int em_gio_irq_reqres(struct irq_data *d)  {  	struct em_gio_priv *p = irq_data_get_irq_chip_data(d); +	int ret; -	if (gpiochip_lock_as_irq(&p->gpio_chip, irqd_to_hwirq(d))) { +	ret = gpiochip_lock_as_irq(&p->gpio_chip, irqd_to_hwirq(d)); +	if (ret) {  		dev_err(p->gpio_chip.parent,  			"unable to lock HW IRQ %lu for IRQ\n",  			irqd_to_hwirq(d)); -		return -EINVAL; +		return ret;  	}  	return 0;  } diff --git a/drivers/gpio/gpio-it87.c b/drivers/gpio/gpio-it87.c index 7cad14d3f127..389ecd8b7d26 100644 --- a/drivers/gpio/gpio-it87.c +++ b/drivers/gpio/gpio-it87.c @@ -35,12 +35,15 @@  /* Chip Id numbers */  #define NO_DEV_ID	0xffff +#define IT8613_ID	0x8613  #define IT8620_ID	0x8620  #define IT8628_ID	0x8628 +#define IT8718_ID       0x8718  #define IT8728_ID	0x8728  #define IT8732_ID	0x8732  #define IT8761_ID	0x8761  #define IT8772_ID	0x8772 +#define IT8786_ID	0x8786  /* IO Ports */  #define REG		0x2e @@ -306,6 +309,14 @@ static int __init it87_gpio_init(void)  	it87_gpio->chip = it87_template_chip;  	switch (chip_type) { +	case IT8613_ID: +		gpio_ba_reg = 0x62; +		it87_gpio->io_size = 8;  /* it8613 only needs 6, use 8 for alignment */ +		it87_gpio->output_base = 0xc8; +		it87_gpio->simple_base = 0xc0; +		it87_gpio->simple_size = 6; +		it87_gpio->chip.ngpio = 64;  /* has 48, use 64 for convenient calc */ +		break;  	case IT8620_ID:  	case IT8628_ID:  		gpio_ba_reg = 0x62; @@ -314,9 +325,11 @@ static int __init it87_gpio_init(void)  		it87_gpio->simple_size = 0;  		it87_gpio->chip.ngpio = 64;  		break; +	case IT8718_ID:  	case IT8728_ID:  	case IT8732_ID:  	case IT8772_ID: +	case IT8786_ID:  		gpio_ba_reg = 0x62;  		it87_gpio->io_size = 8;  		it87_gpio->output_base = 0xc8; diff --git a/drivers/gpio/gpio-madera.c b/drivers/gpio/gpio-madera.c new file mode 100644 index 000000000000..7ba68d1a0932 --- /dev/null +++ b/drivers/gpio/gpio-madera.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * GPIO support for Cirrus Logic Madera codecs + * + * Copyright (C) 2015-2018 Cirrus Logic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; version 2. + */ + +#include <linux/gpio/driver.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#include <linux/mfd/madera/core.h> +#include <linux/mfd/madera/pdata.h> +#include <linux/mfd/madera/registers.h> + +struct madera_gpio { +	struct madera *madera; +	/* storage space for the gpio_chip we're using */ +	struct gpio_chip gpio_chip; +}; + +static int madera_gpio_get_direction(struct gpio_chip *chip, +				     unsigned int offset) +{ +	struct madera_gpio *madera_gpio = gpiochip_get_data(chip); +	struct madera *madera = madera_gpio->madera; +	unsigned int reg_offset = 2 * offset; +	unsigned int val; +	int ret; + +	ret = regmap_read(madera->regmap, MADERA_GPIO1_CTRL_2 + reg_offset, +			  &val); +	if (ret < 0) +		return ret; + +	return !!(val & MADERA_GP1_DIR_MASK); +} + +static int madera_gpio_direction_in(struct gpio_chip *chip, unsigned int offset) +{ +	struct madera_gpio *madera_gpio = gpiochip_get_data(chip); +	struct madera *madera = madera_gpio->madera; +	unsigned int reg_offset = 2 * offset; + +	return regmap_update_bits(madera->regmap, +				  MADERA_GPIO1_CTRL_2 + reg_offset, +				  MADERA_GP1_DIR_MASK, MADERA_GP1_DIR); +} + +static int madera_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ +	struct madera_gpio *madera_gpio = gpiochip_get_data(chip); +	struct madera *madera = madera_gpio->madera; +	unsigned int reg_offset = 2 * offset; +	unsigned int val; +	int ret; + +	ret = regmap_read(madera->regmap, MADERA_GPIO1_CTRL_1 + reg_offset, +			  &val); +	if (ret < 0) +		return ret; + +	return !!(val & MADERA_GP1_LVL_MASK); +} + +static int madera_gpio_direction_out(struct gpio_chip *chip, +				     unsigned int offset, int value) +{ +	struct madera_gpio *madera_gpio = gpiochip_get_data(chip); +	struct madera *madera = madera_gpio->madera; +	unsigned int reg_offset = 2 * offset; +	unsigned int reg_val = value ? MADERA_GP1_LVL : 0; +	int ret; + +	ret = regmap_update_bits(madera->regmap, +				 MADERA_GPIO1_CTRL_2 + reg_offset, +				 MADERA_GP1_DIR_MASK, 0); +	if (ret < 0) +		return ret; + +	return regmap_update_bits(madera->regmap, +				  MADERA_GPIO1_CTRL_1 + reg_offset, +				  MADERA_GP1_LVL_MASK, reg_val); +} + +static void madera_gpio_set(struct gpio_chip *chip, unsigned int offset, +			    int value) +{ +	struct madera_gpio *madera_gpio = gpiochip_get_data(chip); +	struct madera *madera = madera_gpio->madera; +	unsigned int reg_offset = 2 * offset; +	unsigned int reg_val = value ? MADERA_GP1_LVL : 0; +	int ret; + +	ret = regmap_update_bits(madera->regmap, +				 MADERA_GPIO1_CTRL_1 + reg_offset, +				 MADERA_GP1_LVL_MASK, reg_val); + +	/* set() doesn't return an error so log a warning */ +	if (ret) +		dev_warn(madera->dev, "Failed to write to 0x%x (%d)\n", +			 MADERA_GPIO1_CTRL_1 + reg_offset, ret); +} + +static struct gpio_chip madera_gpio_chip = { +	.label			= "madera", +	.owner			= THIS_MODULE, +	.request		= gpiochip_generic_request, +	.free			= gpiochip_generic_free, +	.get_direction		= madera_gpio_get_direction, +	.direction_input	= madera_gpio_direction_in, +	.get			= madera_gpio_get, +	.direction_output	= madera_gpio_direction_out, +	.set			= madera_gpio_set, +	.set_config		= gpiochip_generic_config, +	.can_sleep		= true, +}; + +static int madera_gpio_probe(struct platform_device *pdev) +{ +	struct madera *madera = dev_get_drvdata(pdev->dev.parent); +	struct madera_pdata *pdata = dev_get_platdata(madera->dev); +	struct madera_gpio *madera_gpio; +	int ret; + +	madera_gpio = devm_kzalloc(&pdev->dev, sizeof(*madera_gpio), +				   GFP_KERNEL); +	if (!madera_gpio) +		return -ENOMEM; + +	madera_gpio->madera = madera; + +	/* Construct suitable gpio_chip from the template in madera_gpio_chip */ +	madera_gpio->gpio_chip = madera_gpio_chip; +	madera_gpio->gpio_chip.parent = pdev->dev.parent; + +	switch (madera->type) { +	case CS47L35: +		madera_gpio->gpio_chip.ngpio = CS47L35_NUM_GPIOS; +		break; +	case CS47L85: +	case WM1840: +		madera_gpio->gpio_chip.ngpio = CS47L85_NUM_GPIOS; +		break; +	case CS47L90: +	case CS47L91: +		madera_gpio->gpio_chip.ngpio = CS47L90_NUM_GPIOS; +		break; +	default: +		dev_err(&pdev->dev, "Unknown chip variant %d\n", madera->type); +		return -EINVAL; +	} + +	/* We want to be usable on systems that don't use devicetree or acpi */ +	if (pdata && pdata->gpio_base) +		madera_gpio->gpio_chip.base = pdata->gpio_base; +	else +		madera_gpio->gpio_chip.base = -1; + +	ret = devm_gpiochip_add_data(&pdev->dev, +				     &madera_gpio->gpio_chip, +				     madera_gpio); +	if (ret < 0) { +		dev_dbg(&pdev->dev, "Could not register gpiochip, %d\n", ret); +		return ret; +	} + +	/* +	 * This is part of a composite MFD device which can only be used with +	 * the corresponding pinctrl driver. On all supported silicon the GPIO +	 * to pinctrl mapping is fixed in the silicon, so we register it +	 * explicitly instead of requiring a redundant gpio-ranges in the +	 * devicetree. +	 * In any case we also want to work on systems that don't use devicetree +	 * or acpi. +	 */ +	ret = gpiochip_add_pin_range(&madera_gpio->gpio_chip, "madera-pinctrl", +				     0, 0, madera_gpio->gpio_chip.ngpio); +	if (ret) { +		dev_dbg(&pdev->dev, "Failed to add pin range (%d)\n", ret); +		return ret; +	} + +	return 0; +} + +static struct platform_driver madera_gpio_driver = { +	.driver = { +		.name	= "madera-gpio", +	}, +	.probe		= madera_gpio_probe, +}; + +module_platform_driver(madera_gpio_driver); + +MODULE_SOFTDEP("pre: pinctrl-madera"); +MODULE_DESCRIPTION("GPIO interface for Madera codecs"); +MODULE_AUTHOR("Nariman Poushin <nariman@opensource.cirrus.com>"); +MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:madera-gpio"); diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c index 9d8bcc69f245..f03cb0ba7726 100644 --- a/drivers/gpio/gpio-max732x.c +++ b/drivers/gpio/gpio-max732x.c @@ -653,6 +653,12 @@ static int max732x_probe(struct i2c_client *client,  		chip->client_group_a = client;  		if (nr_port > 8) {  			c = i2c_new_dummy(client->adapter, addr_b); +			if (!c) { +				dev_err(&client->dev, +					"Failed to allocate I2C device\n"); +				ret = -ENODEV; +				goto out_failed; +			}  			chip->client_group_b = chip->client_dummy = c;  		}  		break; @@ -660,6 +666,12 @@ static int max732x_probe(struct i2c_client *client,  		chip->client_group_b = client;  		if (nr_port > 8) {  			c = i2c_new_dummy(client->adapter, addr_a); +			if (!c) { +				dev_err(&client->dev, +					"Failed to allocate I2C device\n"); +				ret = -ENODEV; +				goto out_failed; +			}  			chip->client_group_a = chip->client_dummy = c;  		}  		break; diff --git a/drivers/gpio/gpio-menz127.c b/drivers/gpio/gpio-menz127.c index e1037582e34d..b2635326546e 100644 --- a/drivers/gpio/gpio-menz127.c +++ b/drivers/gpio/gpio-menz127.c @@ -56,9 +56,9 @@ static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio,  		rnd = fls(debounce) - 1;  		if (rnd && (debounce & BIT(rnd - 1))) -			debounce = round_up(debounce, MEN_Z127_DB_MIN_US); +			debounce = roundup(debounce, MEN_Z127_DB_MIN_US);  		else -			debounce = round_down(debounce, MEN_Z127_DB_MIN_US); +			debounce = rounddown(debounce, MEN_Z127_DB_MIN_US);  		if (debounce > MEN_Z127_DB_MAX_US)  			debounce = MEN_Z127_DB_MAX_US; diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index b23d9a36be1f..51c7d1b84c2e 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -496,9 +496,10 @@ static int ioh_gpio_probe(struct pci_dev *pdev,  	return 0;  err_gpiochip_add: +	chip = chip_save;  	while (--i >= 0) { -		chip--;  		gpiochip_remove(&chip->gpio); +		chip++;  	}  	kfree(chip_save); diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c index 7b14d6280e44..935292a30c99 100644 --- a/drivers/gpio/gpio-mmio.c +++ b/drivers/gpio/gpio-mmio.c @@ -136,8 +136,20 @@ static unsigned long bgpio_line2mask(struct gpio_chip *gc, unsigned int line)  static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio)  {  	unsigned long pinmask = bgpio_line2mask(gc, gpio); +	bool dir = !!(gc->bgpio_dir & pinmask); -	if (gc->bgpio_dir & pinmask) +	/* +	 * If the direction is OUT we read the value from the SET +	 * register, and if the direction is IN we read the value +	 * from the DAT register. +	 * +	 * If the direction bits are inverted, naturally this gets +	 * inverted too. +	 */ +	if (gc->bgpio_dir_inverted) +		dir = !dir; + +	if (dir)  		return !!(gc->read_reg(gc->reg_set) & pinmask);  	else  		return !!(gc->read_reg(gc->reg_dat) & pinmask); @@ -157,8 +169,13 @@ static int bgpio_get_set_multiple(struct gpio_chip *gc, unsigned long *mask,  	*bits &= ~*mask;  	/* Exploit the fact that we know which directions are set */ -	set_mask = *mask & gc->bgpio_dir; -	get_mask = *mask & ~gc->bgpio_dir; +	if (gc->bgpio_dir_inverted) { +		set_mask = *mask & ~gc->bgpio_dir; +		get_mask = *mask & gc->bgpio_dir; +	} else { +		set_mask = *mask & gc->bgpio_dir; +		get_mask = *mask & ~gc->bgpio_dir; +	}  	if (set_mask)  		*bits |= gc->read_reg(gc->reg_set) & set_mask; @@ -359,7 +376,10 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)  	spin_lock_irqsave(&gc->bgpio_lock, flags); -	gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio); +	if (gc->bgpio_dir_inverted) +		gc->bgpio_dir |= bgpio_line2mask(gc, gpio); +	else +		gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio);  	gc->write_reg(gc->reg_dir, gc->bgpio_dir);  	spin_unlock_irqrestore(&gc->bgpio_lock, flags); @@ -370,7 +390,10 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)  static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio)  {  	/* Return 0 if output, 1 of input */ -	return !(gc->read_reg(gc->reg_dir) & bgpio_line2mask(gc, gpio)); +	if (gc->bgpio_dir_inverted) +		return !!(gc->read_reg(gc->reg_dir) & bgpio_line2mask(gc, gpio)); +	else +		return !(gc->read_reg(gc->reg_dir) & bgpio_line2mask(gc, gpio));  }  static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) @@ -381,37 +404,10 @@ static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)  	spin_lock_irqsave(&gc->bgpio_lock, flags); -	gc->bgpio_dir |= bgpio_line2mask(gc, gpio); -	gc->write_reg(gc->reg_dir, gc->bgpio_dir); - -	spin_unlock_irqrestore(&gc->bgpio_lock, flags); - -	return 0; -} - -static int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio) -{ -	unsigned long flags; - -	spin_lock_irqsave(&gc->bgpio_lock, flags); - -	gc->bgpio_dir |= bgpio_line2mask(gc, gpio); -	gc->write_reg(gc->reg_dir, gc->bgpio_dir); - -	spin_unlock_irqrestore(&gc->bgpio_lock, flags); - -	return 0; -} - -static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val) -{ -	unsigned long flags; - -	gc->set(gc, gpio, val); - -	spin_lock_irqsave(&gc->bgpio_lock, flags); - -	gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio); +	if (gc->bgpio_dir_inverted) +		gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio); +	else +		gc->bgpio_dir |= bgpio_line2mask(gc, gpio);  	gc->write_reg(gc->reg_dir, gc->bgpio_dir);  	spin_unlock_irqrestore(&gc->bgpio_lock, flags); @@ -419,12 +415,6 @@ static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val)  	return 0;  } -static int bgpio_get_dir_inv(struct gpio_chip *gc, unsigned int gpio) -{ -	/* Return 0 if output, 1 if input */ -	return !!(gc->read_reg(gc->reg_dir) & bgpio_line2mask(gc, gpio)); -} -  static int bgpio_setup_accessors(struct device *dev,  				 struct gpio_chip *gc,  				 bool byte_be) @@ -560,9 +550,10 @@ static int bgpio_setup_direction(struct gpio_chip *gc,  		gc->get_direction = bgpio_get_dir;  	} else if (dirin) {  		gc->reg_dir = dirin; -		gc->direction_output = bgpio_dir_out_inv; -		gc->direction_input = bgpio_dir_in_inv; -		gc->get_direction = bgpio_get_dir_inv; +		gc->direction_output = bgpio_dir_out; +		gc->direction_input = bgpio_dir_in; +		gc->get_direction = bgpio_get_dir; +		gc->bgpio_dir_inverted = true;  	} else {  		if (flags & BGPIOF_NO_OUTPUT)  			gc->direction_output = bgpio_dir_out_err; @@ -582,6 +573,33 @@ static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin)  	return -EINVAL;  } +/** + * bgpio_init() - Initialize generic GPIO accessor functions + * @gc: the GPIO chip to set up + * @dev: the parent device of the new GPIO chip (compulsory) + * @sz: the size (width) of the MMIO registers in bytes, typically 1, 2 or 4 + * @dat: MMIO address for the register to READ the value of the GPIO lines, it + *	is expected that a 1 in the corresponding bit in this register means the + *	line is asserted + * @set: MMIO address for the register to SET the value of the GPIO lines, it is + *	expected that we write the line with 1 in this register to drive the GPIO line + *	high. + * @clr: MMIO address for the register to CLEAR the value of the GPIO lines, it is + *	expected that we write the line with 1 in this register to drive the GPIO line + *	low. It is allowed to leave this address as NULL, in that case the SET register + *	will be assumed to also clear the GPIO lines, by actively writing the line + *	with 0. + * @dirout: MMIO address for the register to set the line as OUTPUT. It is assumed + *	that setting a line to 1 in this register will turn that line into an + *	output line. Conversely, setting the line to 0 will turn that line into + *	an input. Either this or @dirin can be defined, but never both. + * @dirin: MMIO address for the register to set this line as INPUT. It is assumed + *	that setting a line to 1 in this register will turn that line into an + *	input line. Conversely, setting the line to 0 will turn that line into + *	an output. Either this or @dirout can be defined, but never both. + * @flags: Different flags that will affect the behaviour of the device, such as + *	endianness etc. + */  int bgpio_init(struct gpio_chip *gc, struct device *dev,  	       unsigned long sz, void __iomem *dat, void __iomem *set,  	       void __iomem *clr, void __iomem *dirout, void __iomem *dirin, diff --git a/drivers/gpio/gpio-mt7621.c b/drivers/gpio/gpio-mt7621.c new file mode 100644 index 000000000000..d72af6f6cdbd --- /dev/null +++ b/drivers/gpio/gpio-mt7621.c @@ -0,0 +1,332 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/err.h> +#include <linux/gpio/driver.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of_irq.h> +#include <linux/platform_device.h> +#include <linux/spinlock.h> + +#define MTK_BANK_CNT	3 +#define MTK_BANK_WIDTH	32 + +#define GPIO_BANK_STRIDE	0x04 +#define GPIO_REG_CTRL		0x00 +#define GPIO_REG_POL		0x10 +#define GPIO_REG_DATA		0x20 +#define GPIO_REG_DSET		0x30 +#define GPIO_REG_DCLR		0x40 +#define GPIO_REG_REDGE		0x50 +#define GPIO_REG_FEDGE		0x60 +#define GPIO_REG_HLVL		0x70 +#define GPIO_REG_LLVL		0x80 +#define GPIO_REG_STAT		0x90 +#define GPIO_REG_EDGE		0xA0 + +struct mtk_gc { +	struct gpio_chip chip; +	spinlock_t lock; +	int bank; +	u32 rising; +	u32 falling; +	u32 hlevel; +	u32 llevel; +}; + +/** + * struct mtk - state container for + * data of the platform driver. It is 3 + * separate gpio-chip each one with its + * own irq_chip. + * @dev: device instance + * @base: memory base address + * @gpio_irq: irq number from the device tree + * @gc_map: array of the gpio chips + */ +struct mtk { +	struct device *dev; +	void __iomem *base; +	int gpio_irq; +	struct mtk_gc gc_map[MTK_BANK_CNT]; +}; + +static inline struct mtk_gc * +to_mediatek_gpio(struct gpio_chip *chip) +{ +	return container_of(chip, struct mtk_gc, chip); +} + +static inline void +mtk_gpio_w32(struct mtk_gc *rg, u32 offset, u32 val) +{ +	struct gpio_chip *gc = &rg->chip; +	struct mtk *mtk = gpiochip_get_data(gc); + +	offset = (rg->bank * GPIO_BANK_STRIDE) + offset; +	gc->write_reg(mtk->base + offset, val); +} + +static inline u32 +mtk_gpio_r32(struct mtk_gc *rg, u32 offset) +{ +	struct gpio_chip *gc = &rg->chip; +	struct mtk *mtk = gpiochip_get_data(gc); + +	offset = (rg->bank * GPIO_BANK_STRIDE) + offset; +	return gc->read_reg(mtk->base + offset); +} + +static irqreturn_t +mediatek_gpio_irq_handler(int irq, void *data) +{ +	struct gpio_chip *gc = data; +	struct mtk_gc *rg = to_mediatek_gpio(gc); +	irqreturn_t ret = IRQ_NONE; +	unsigned long pending; +	int bit; + +	pending = mtk_gpio_r32(rg, GPIO_REG_STAT); + +	for_each_set_bit(bit, &pending, MTK_BANK_WIDTH) { +		u32 map = irq_find_mapping(gc->irq.domain, bit); + +		generic_handle_irq(map); +		mtk_gpio_w32(rg, GPIO_REG_STAT, BIT(bit)); +		ret |= IRQ_HANDLED; +	} + +	return ret; +} + +static void +mediatek_gpio_irq_unmask(struct irq_data *d) +{ +	struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +	struct mtk_gc *rg = to_mediatek_gpio(gc); +	int pin = d->hwirq; +	unsigned long flags; +	u32 rise, fall, high, low; + +	spin_lock_irqsave(&rg->lock, flags); +	rise = mtk_gpio_r32(rg, GPIO_REG_REDGE); +	fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE); +	high = mtk_gpio_r32(rg, GPIO_REG_HLVL); +	low = mtk_gpio_r32(rg, GPIO_REG_LLVL); +	mtk_gpio_w32(rg, GPIO_REG_REDGE, rise | (BIT(pin) & rg->rising)); +	mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall | (BIT(pin) & rg->falling)); +	mtk_gpio_w32(rg, GPIO_REG_HLVL, high | (BIT(pin) & rg->hlevel)); +	mtk_gpio_w32(rg, GPIO_REG_LLVL, low | (BIT(pin) & rg->llevel)); +	spin_unlock_irqrestore(&rg->lock, flags); +} + +static void +mediatek_gpio_irq_mask(struct irq_data *d) +{ +	struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +	struct mtk_gc *rg = to_mediatek_gpio(gc); +	int pin = d->hwirq; +	unsigned long flags; +	u32 rise, fall, high, low; + +	spin_lock_irqsave(&rg->lock, flags); +	rise = mtk_gpio_r32(rg, GPIO_REG_REDGE); +	fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE); +	high = mtk_gpio_r32(rg, GPIO_REG_HLVL); +	low = mtk_gpio_r32(rg, GPIO_REG_LLVL); +	mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall & ~BIT(pin)); +	mtk_gpio_w32(rg, GPIO_REG_REDGE, rise & ~BIT(pin)); +	mtk_gpio_w32(rg, GPIO_REG_HLVL, high & ~BIT(pin)); +	mtk_gpio_w32(rg, GPIO_REG_LLVL, low & ~BIT(pin)); +	spin_unlock_irqrestore(&rg->lock, flags); +} + +static int +mediatek_gpio_irq_type(struct irq_data *d, unsigned int type) +{ +	struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +	struct mtk_gc *rg = to_mediatek_gpio(gc); +	int pin = d->hwirq; +	u32 mask = BIT(pin); + +	if (type == IRQ_TYPE_PROBE) { +		if ((rg->rising | rg->falling | +		     rg->hlevel | rg->llevel) & mask) +			return 0; + +		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; +	} + +	rg->rising &= ~mask; +	rg->falling &= ~mask; +	rg->hlevel &= ~mask; +	rg->llevel &= ~mask; + +	switch (type & IRQ_TYPE_SENSE_MASK) { +	case IRQ_TYPE_EDGE_BOTH: +		rg->rising |= mask; +		rg->falling |= mask; +		break; +	case IRQ_TYPE_EDGE_RISING: +		rg->rising |= mask; +		break; +	case IRQ_TYPE_EDGE_FALLING: +		rg->falling |= mask; +		break; +	case IRQ_TYPE_LEVEL_HIGH: +		rg->hlevel |= mask; +		break; +	case IRQ_TYPE_LEVEL_LOW: +		rg->llevel |= mask; +		break; +	} + +	return 0; +} + +static struct irq_chip mediatek_gpio_irq_chip = { +	.irq_unmask		= mediatek_gpio_irq_unmask, +	.irq_mask		= mediatek_gpio_irq_mask, +	.irq_mask_ack		= mediatek_gpio_irq_mask, +	.irq_set_type		= mediatek_gpio_irq_type, +}; + +static int +mediatek_gpio_xlate(struct gpio_chip *chip, +		    const struct of_phandle_args *spec, u32 *flags) +{ +	int gpio = spec->args[0]; +	struct mtk_gc *rg = to_mediatek_gpio(chip); + +	if (rg->bank != gpio / MTK_BANK_WIDTH) +		return -EINVAL; + +	if (flags) +		*flags = spec->args[1]; + +	return gpio % MTK_BANK_WIDTH; +} + +static int +mediatek_gpio_bank_probe(struct device *dev, +			 struct device_node *node, int bank) +{ +	struct mtk *mtk = dev_get_drvdata(dev); +	struct mtk_gc *rg; +	void __iomem *dat, *set, *ctrl, *diro; +	int ret; + +	rg = &mtk->gc_map[bank]; +	memset(rg, 0, sizeof(*rg)); + +	spin_lock_init(&rg->lock); +	rg->chip.of_node = node; +	rg->bank = bank; + +	dat = mtk->base + GPIO_REG_DATA + (rg->bank * GPIO_BANK_STRIDE); +	set = mtk->base + GPIO_REG_DSET + (rg->bank * GPIO_BANK_STRIDE); +	ctrl = mtk->base + GPIO_REG_DCLR + (rg->bank * GPIO_BANK_STRIDE); +	diro = mtk->base + GPIO_REG_CTRL + (rg->bank * GPIO_BANK_STRIDE); + +	ret = bgpio_init(&rg->chip, dev, 4, +			 dat, set, ctrl, diro, NULL, 0); +	if (ret) { +		dev_err(dev, "bgpio_init() failed\n"); +		return ret; +	} + +	rg->chip.of_gpio_n_cells = 2; +	rg->chip.of_xlate = mediatek_gpio_xlate; +	rg->chip.label = devm_kasprintf(dev, GFP_KERNEL, "%s-bank%d", +					dev_name(dev), bank); + +	ret = devm_gpiochip_add_data(dev, &rg->chip, mtk); +	if (ret < 0) { +		dev_err(dev, "Could not register gpio %d, ret=%d\n", +			rg->chip.ngpio, ret); +		return ret; +	} + +	if (mtk->gpio_irq) { +		/* +		 * Manually request the irq here instead of passing +		 * a flow-handler to gpiochip_set_chained_irqchip, +		 * because the irq is shared. +		 */ +		ret = devm_request_irq(dev, mtk->gpio_irq, +				       mediatek_gpio_irq_handler, IRQF_SHARED, +				       rg->chip.label, &rg->chip); + +		if (ret) { +			dev_err(dev, "Error requesting IRQ %d: %d\n", +				mtk->gpio_irq, ret); +			return ret; +		} + +		ret = gpiochip_irqchip_add(&rg->chip, &mediatek_gpio_irq_chip, +					   0, handle_simple_irq, IRQ_TYPE_NONE); +		if (ret) { +			dev_err(dev, "failed to add gpiochip_irqchip\n"); +			return ret; +		} + +		gpiochip_set_chained_irqchip(&rg->chip, &mediatek_gpio_irq_chip, +					     mtk->gpio_irq, NULL); +	} + +	/* set polarity to low for all gpios */ +	mtk_gpio_w32(rg, GPIO_REG_POL, 0); + +	dev_info(dev, "registering %d gpios\n", rg->chip.ngpio); + +	return 0; +} + +static int +mediatek_gpio_probe(struct platform_device *pdev) +{ +	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	struct device *dev = &pdev->dev; +	struct device_node *np = dev->of_node; +	struct mtk *mtk; +	int i; + +	mtk = devm_kzalloc(dev, sizeof(*mtk), GFP_KERNEL); +	if (!mtk) +		return -ENOMEM; + +	mtk->base = devm_ioremap_resource(dev, res); +	if (IS_ERR(mtk->base)) +		return PTR_ERR(mtk->base); + +	mtk->gpio_irq = irq_of_parse_and_map(np, 0); +	mtk->dev = dev; +	platform_set_drvdata(pdev, mtk); +	mediatek_gpio_irq_chip.name = dev_name(dev); + +	for (i = 0; i < MTK_BANK_CNT; i++) +		mediatek_gpio_bank_probe(dev, np, i); + +	return 0; +} + +static const struct of_device_id mediatek_gpio_match[] = { +	{ .compatible = "mediatek,mt7621-gpio" }, +	{}, +}; +MODULE_DEVICE_TABLE(of, mediatek_gpio_match); + +static struct platform_driver mediatek_gpio_driver = { +	.probe = mediatek_gpio_probe, +	.driver = { +		.name = "mt7621_gpio", +		.of_match_table = mediatek_gpio_match, +	}, +}; + +builtin_platform_driver(mediatek_gpio_driver); diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 2f2829966d4c..995cf0b9e0b1 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -45,6 +45,15 @@ struct mxc_gpio_hwdata {  	unsigned fall_edge;  }; +struct mxc_gpio_reg_saved { +	u32 icr1; +	u32 icr2; +	u32 imr; +	u32 gdir; +	u32 edge_sel; +	u32 dr; +}; +  struct mxc_gpio_port {  	struct list_head node;  	void __iomem *base; @@ -55,6 +64,8 @@ struct mxc_gpio_port {  	struct gpio_chip gc;  	struct device *dev;  	u32 both_edges; +	struct mxc_gpio_reg_saved gpio_saved_reg; +	bool power_off;  };  static struct mxc_gpio_hwdata imx1_imx21_gpio_hwdata = { @@ -143,6 +154,7 @@ static const struct of_device_id mxc_gpio_dt_ids[] = {  	{ .compatible = "fsl,imx21-gpio", .data = &mxc_gpio_devtype[IMX21_GPIO], },  	{ .compatible = "fsl,imx31-gpio", .data = &mxc_gpio_devtype[IMX31_GPIO], },  	{ .compatible = "fsl,imx35-gpio", .data = &mxc_gpio_devtype[IMX35_GPIO], }, +	{ .compatible = "fsl,imx7d-gpio", .data = &mxc_gpio_devtype[IMX35_GPIO], },  	{ /* sentinel */ }  }; @@ -434,6 +446,9 @@ static int mxc_gpio_probe(struct platform_device *pdev)  		return err;  	} +	if (of_device_is_compatible(np, "fsl,imx7d-gpio")) +		port->power_off = true; +  	/* disable the interrupt and clear the status */  	writel(0, port->base + GPIO_IMR);  	writel(~0, port->base + GPIO_ISR); @@ -497,6 +512,8 @@ static int mxc_gpio_probe(struct platform_device *pdev)  	list_add_tail(&port->node, &mxc_gpio_ports); +	platform_set_drvdata(pdev, port); +  	return 0;  out_irqdomain_remove: @@ -507,11 +524,67 @@ out_bgio:  	return err;  } +static void mxc_gpio_save_regs(struct mxc_gpio_port *port) +{ +	if (!port->power_off) +		return; + +	port->gpio_saved_reg.icr1 = readl(port->base + GPIO_ICR1); +	port->gpio_saved_reg.icr2 = readl(port->base + GPIO_ICR2); +	port->gpio_saved_reg.imr = readl(port->base + GPIO_IMR); +	port->gpio_saved_reg.gdir = readl(port->base + GPIO_GDIR); +	port->gpio_saved_reg.edge_sel = readl(port->base + GPIO_EDGE_SEL); +	port->gpio_saved_reg.dr = readl(port->base + GPIO_DR); +} + +static void mxc_gpio_restore_regs(struct mxc_gpio_port *port) +{ +	if (!port->power_off) +		return; + +	writel(port->gpio_saved_reg.icr1, port->base + GPIO_ICR1); +	writel(port->gpio_saved_reg.icr2, port->base + GPIO_ICR2); +	writel(port->gpio_saved_reg.imr, port->base + GPIO_IMR); +	writel(port->gpio_saved_reg.gdir, port->base + GPIO_GDIR); +	writel(port->gpio_saved_reg.edge_sel, port->base + GPIO_EDGE_SEL); +	writel(port->gpio_saved_reg.dr, port->base + GPIO_DR); +} + +static int __maybe_unused mxc_gpio_noirq_suspend(struct device *dev) +{ +	struct platform_device *pdev = to_platform_device(dev); +	struct mxc_gpio_port *port = platform_get_drvdata(pdev); + +	mxc_gpio_save_regs(port); +	clk_disable_unprepare(port->clk); + +	return 0; +} + +static int __maybe_unused mxc_gpio_noirq_resume(struct device *dev) +{ +	struct platform_device *pdev = to_platform_device(dev); +	struct mxc_gpio_port *port = platform_get_drvdata(pdev); +	int ret; + +	ret = clk_prepare_enable(port->clk); +	if (ret) +		return ret; +	mxc_gpio_restore_regs(port); + +	return 0; +} + +static const struct dev_pm_ops mxc_gpio_dev_pm_ops = { +	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mxc_gpio_noirq_suspend, mxc_gpio_noirq_resume) +}; +  static struct platform_driver mxc_gpio_driver = {  	.driver		= {  		.name	= "gpio-mxc",  		.of_match_table = mxc_gpio_dt_ids,  		.suppress_bind_attrs = true, +		.pm = &mxc_gpio_dev_pm_ops,  	},  	.probe		= mxc_gpio_probe,  	.id_table	= mxc_gpio_devtype, diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index e2831ee70cdc..df30490da820 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -126,8 +126,7 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)  	else  		writel(pin_mask, pin_addr + MXS_CLR); -	writel(pin_mask, -	       port->base + PINCTRL_IRQSTAT(port) + MXS_CLR); +	writel(pin_mask, port->base + PINCTRL_IRQSTAT(port) + MXS_CLR);  	return 0;  } diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index d1afedf4dcbf..e81008678a38 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -77,6 +77,8 @@ struct gpio_bank {  	bool workaround_enabled;  	void (*set_dataout)(struct gpio_bank *bank, unsigned gpio, int enable); +	void (*set_dataout_multiple)(struct gpio_bank *bank, +				     unsigned long *mask, unsigned long *bits);  	int (*get_context_loss_count)(struct device *dev);  	struct omap_gpio_reg_offs *regs; @@ -161,6 +163,51 @@ static int omap_get_gpio_dataout(struct gpio_bank *bank, int offset)  	return (readl_relaxed(reg) & (BIT(offset))) != 0;  } +/* set multiple data out values using dedicate set/clear register */ +static void omap_set_gpio_dataout_reg_multiple(struct gpio_bank *bank, +					       unsigned long *mask, +					       unsigned long *bits) +{ +	void __iomem *reg = bank->base; +	u32 l; + +	l = *bits & *mask; +	writel_relaxed(l, reg + bank->regs->set_dataout); +	bank->context.dataout |= l; + +	l = ~*bits & *mask; +	writel_relaxed(l, reg + bank->regs->clr_dataout); +	bank->context.dataout &= ~l; +} + +/* set multiple data out values using mask register */ +static void omap_set_gpio_dataout_mask_multiple(struct gpio_bank *bank, +						unsigned long *mask, +						unsigned long *bits) +{ +	void __iomem *reg = bank->base + bank->regs->dataout; +	u32 l = (readl_relaxed(reg) & ~*mask) | (*bits & *mask); + +	writel_relaxed(l, reg); +	bank->context.dataout = l; +} + +static unsigned long omap_get_gpio_datain_multiple(struct gpio_bank *bank, +					      unsigned long *mask) +{ +	void __iomem *reg = bank->base + bank->regs->datain; + +	return readl_relaxed(reg) & *mask; +} + +static unsigned long omap_get_gpio_dataout_multiple(struct gpio_bank *bank, +					       unsigned long *mask) +{ +	void __iomem *reg = bank->base + bank->regs->dataout; + +	return readl_relaxed(reg) & *mask; +} +  static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)  {  	int l = readl_relaxed(base + reg); @@ -968,6 +1015,26 @@ static int omap_gpio_output(struct gpio_chip *chip, unsigned offset, int value)  	return 0;  } +static int omap_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask, +				  unsigned long *bits) +{ +	struct gpio_bank *bank = gpiochip_get_data(chip); +	void __iomem *reg = bank->base + bank->regs->direction; +	unsigned long in = readl_relaxed(reg), l; + +	*bits = 0; + +	l = in & *mask; +	if (l) +		*bits |= omap_get_gpio_datain_multiple(bank, &l); + +	l = ~in & *mask; +	if (l) +		*bits |= omap_get_gpio_dataout_multiple(bank, &l); + +	return 0; +} +  static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,  			      unsigned debounce)  { @@ -1012,6 +1079,17 @@ static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value)  	raw_spin_unlock_irqrestore(&bank->lock, flags);  } +static void omap_gpio_set_multiple(struct gpio_chip *chip, unsigned long *mask, +				   unsigned long *bits) +{ +	struct gpio_bank *bank = gpiochip_get_data(chip); +	unsigned long flags; + +	raw_spin_lock_irqsave(&bank->lock, flags); +	bank->set_dataout_multiple(bank, mask, bits); +	raw_spin_unlock_irqrestore(&bank->lock, flags); +} +  /*---------------------------------------------------------------------*/  static void omap_gpio_show_rev(struct gpio_bank *bank) @@ -1073,9 +1151,11 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)  	bank->chip.get_direction = omap_gpio_get_direction;  	bank->chip.direction_input = omap_gpio_input;  	bank->chip.get = omap_gpio_get; +	bank->chip.get_multiple = omap_gpio_get_multiple;  	bank->chip.direction_output = omap_gpio_output;  	bank->chip.set_config = omap_gpio_set_config;  	bank->chip.set = omap_gpio_set; +	bank->chip.set_multiple = omap_gpio_set_multiple;  	if (bank->is_mpuio) {  		bank->chip.label = "mpuio";  		if (bank->regs->wkup_en) @@ -1209,10 +1289,14 @@ static int omap_gpio_probe(struct platform_device *pdev)  				pdata->get_context_loss_count;  	} -	if (bank->regs->set_dataout && bank->regs->clr_dataout) +	if (bank->regs->set_dataout && bank->regs->clr_dataout) {  		bank->set_dataout = omap_set_gpio_dataout_reg; -	else +		bank->set_dataout_multiple = omap_set_gpio_dataout_reg_multiple; +	} else {  		bank->set_dataout = omap_set_gpio_dataout_mask; +		bank->set_dataout_multiple = +				omap_set_gpio_dataout_mask_multiple; +	}  	raw_spin_lock_init(&bank->lock);  	raw_spin_lock_init(&bank->wa_lock); diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index c55ad157e820..023a32cfac42 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -708,7 +708,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,  {  	struct i2c_client *client = chip->client; -	if (irq_base != -1 && (chip->driver_data & PCA_INT)) +	if (client->irq && irq_base != -1 && (chip->driver_data & PCA_INT))  		dev_warn(&client->dev, "interrupt support not compiled in\n");  	return 0; diff --git a/drivers/gpio/gpio-pisosr.c b/drivers/gpio/gpio-pisosr.c index f5545049c187..f809a5a8e9eb 100644 --- a/drivers/gpio/gpio-pisosr.c +++ b/drivers/gpio/gpio-pisosr.c @@ -12,6 +12,8 @@   * GNU General Public License version 2 for more details.   */ +#include <linux/bitmap.h> +#include <linux/bitops.h>  #include <linux/delay.h>  #include <linux/gpio/consumer.h>  #include <linux/gpio/driver.h> @@ -90,6 +92,25 @@ static int pisosr_gpio_get(struct gpio_chip *chip, unsigned offset)  	return (gpio->buffer[offset / 8] >> (offset % 8)) & 0x1;  } +static int pisosr_gpio_get_multiple(struct gpio_chip *chip, +				    unsigned long *mask, unsigned long *bits) +{ +	struct pisosr_gpio *gpio = gpiochip_get_data(chip); +	unsigned int nbytes = DIV_ROUND_UP(chip->ngpio, 8); +	unsigned int i, j; + +	pisosr_gpio_refresh(gpio); + +	bitmap_zero(bits, chip->ngpio); +	for (i = 0; i < nbytes; i++) { +		j = i / sizeof(unsigned long); +		bits[j] |= ((unsigned long) gpio->buffer[i]) +			   << (8 * (i % sizeof(unsigned long))); +	} + +	return 0; +} +  static const struct gpio_chip template_chip = {  	.label			= "pisosr-gpio",  	.owner			= THIS_MODULE, @@ -97,6 +118,7 @@ static const struct gpio_chip template_chip = {  	.direction_input	= pisosr_gpio_direction_input,  	.direction_output	= pisosr_gpio_direction_output,  	.get			= pisosr_gpio_get, +	.get_multiple		= pisosr_gpio_get_multiple,  	.base			= -1,  	.ngpio			= DEFAULT_NGPIO,  	.can_sleep		= true, diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 1e66f808051c..c18712dabf93 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -241,6 +241,17 @@ int pxa_irq_to_gpio(int irq)  	return irq_gpio0;  } +static bool pxa_gpio_has_pinctrl(void) +{ +	switch (gpio_type) { +	case PXA3XX_GPIO: +		return false; + +	default: +		return true; +	} +} +  static int pxa_gpio_to_irq(struct gpio_chip *chip, unsigned offset)  {  	struct pxa_gpio_chip *pchip = chip_to_pxachip(chip); @@ -255,9 +266,11 @@ static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)  	unsigned long flags;  	int ret; -	ret = pinctrl_gpio_direction_input(chip->base + offset); -	if (!ret) -		return 0; +	if (pxa_gpio_has_pinctrl()) { +		ret = pinctrl_gpio_direction_input(chip->base + offset); +		if (!ret) +			return 0; +	}  	spin_lock_irqsave(&gpio_lock, flags); @@ -282,9 +295,11 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip,  	writel_relaxed(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET)); -	ret = pinctrl_gpio_direction_output(chip->base + offset); -	if (ret) -		return ret; +	if (pxa_gpio_has_pinctrl()) { +		ret = pinctrl_gpio_direction_output(chip->base + offset); +		if (ret) +			return ret; +	}  	spin_lock_irqsave(&gpio_lock, flags); @@ -348,8 +363,12 @@ static int pxa_init_gpio_chip(struct pxa_gpio_chip *pchip, int ngpio,  	pchip->chip.set = pxa_gpio_set;  	pchip->chip.to_irq = pxa_gpio_to_irq;  	pchip->chip.ngpio = ngpio; -	pchip->chip.request = gpiochip_generic_request; -	pchip->chip.free = gpiochip_generic_free; + +	if (pxa_gpio_has_pinctrl()) { +		pchip->chip.request = gpiochip_generic_request; +		pchip->chip.free = gpiochip_generic_free; +	} +  #ifdef CONFIG_OF_GPIO  	pchip->chip.of_node = np;  	pchip->chip.of_xlate = pxa_gpio_of_xlate; @@ -607,7 +626,7 @@ static int pxa_gpio_probe(struct platform_device *pdev)  	struct pxa_gpio_platform_data *info;  	void __iomem *gpio_reg_base;  	int gpio, ret; -	int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0; +	int irq0 = 0, irq1 = 0, irq_mux;  	pchip = devm_kzalloc(&pdev->dev, sizeof(*pchip), GFP_KERNEL);  	if (!pchip) @@ -646,14 +665,13 @@ static int pxa_gpio_probe(struct platform_device *pdev)  	pchip->irq0 = irq0;  	pchip->irq1 = irq1;  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	if (!res) +		return -EINVAL;  	gpio_reg_base = devm_ioremap(&pdev->dev, res->start,  				     resource_size(res));  	if (!gpio_reg_base)  		return -EINVAL; -	if (irq0 > 0) -		gpio_offset = 2; -  	clk = clk_get(&pdev->dev, NULL);  	if (IS_ERR(clk)) {  		dev_err(&pdev->dev, "Error %ld to get gpio clock\n", diff --git a/drivers/gpio/gpio-rc5t583.c b/drivers/gpio/gpio-rc5t583.c index 3b4dc1a9a68d..a499c633a6c5 100644 --- a/drivers/gpio/gpio-rc5t583.c +++ b/drivers/gpio/gpio-rc5t583.c @@ -25,7 +25,7 @@  #include <linux/slab.h>  #include <linux/platform_device.h>  #include <linux/device.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h>  #include <linux/mfd/rc5t583.h>  struct rc5t583_gpio { diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index 350390c0b290..55cc61086d99 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -15,7 +15,7 @@   */  #include <linux/err.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h>  #include <linux/init.h>  #include <linux/interrupt.h>  #include <linux/io.h> @@ -278,6 +278,13 @@ static void gpio_rcar_free(struct gpio_chip *chip, unsigned offset)  	pm_runtime_put(&p->pdev->dev);  } +static int gpio_rcar_get_direction(struct gpio_chip *chip, unsigned int offset) +{ +	struct gpio_rcar_priv *p = gpiochip_get_data(chip); + +	return !(gpio_rcar_read(p, INOUTSEL) & BIT(offset)); +} +  static int gpio_rcar_direction_input(struct gpio_chip *chip, unsigned offset)  {  	gpio_rcar_config_general_input_output_mode(chip, offset, false); @@ -461,6 +468,7 @@ static int gpio_rcar_probe(struct platform_device *pdev)  	gpio_chip = &p->gpio_chip;  	gpio_chip->request = gpio_rcar_request;  	gpio_chip->free = gpio_rcar_free; +	gpio_chip->get_direction = gpio_rcar_get_direction;  	gpio_chip->direction_input = gpio_rcar_direction_input;  	gpio_chip->get = gpio_rcar_get;  	gpio_chip->direction_output = gpio_rcar_direction_output; diff --git a/drivers/gpio/gpio-rdc321x.c b/drivers/gpio/gpio-rdc321x.c index cbf0f9e6465b..2938217566d3 100644 --- a/drivers/gpio/gpio-rdc321x.c +++ b/drivers/gpio/gpio-rdc321x.c @@ -25,7 +25,7 @@  #include <linux/spinlock.h>  #include <linux/platform_device.h>  #include <linux/pci.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h>  #include <linux/mfd/rdc321x.h>  #include <linux/slab.h> diff --git a/drivers/gpio/gpio-sa1100.c b/drivers/gpio/gpio-sa1100.c index 249f433aa62d..986eb3b231ac 100644 --- a/drivers/gpio/gpio-sa1100.c +++ b/drivers/gpio/gpio-sa1100.c @@ -7,7 +7,7 @@   * it under the terms of the GNU General Public License version 2 as   * published by the Free Software Foundation.   */ -#include <linux/gpio.h> +#include <linux/gpio/driver.h>  #include <linux/init.h>  #include <linux/module.h>  #include <linux/io.h> diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c index 545004445846..e9878f6ede67 100644 --- a/drivers/gpio/gpio-sch.c +++ b/drivers/gpio/gpio-sch.c @@ -26,8 +26,7 @@  #include <linux/acpi.h>  #include <linux/platform_device.h>  #include <linux/pci_ids.h> - -#include <linux/gpio.h> +#include <linux/gpio/driver.h>  #define GEN	0x00  #define GIO	0x04 @@ -138,6 +137,13 @@ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,  	return 0;  } +static int sch_gpio_get_direction(struct gpio_chip *gc, unsigned gpio_num) +{ +	struct sch_gpio *sch = gpiochip_get_data(gc); + +	return sch_gpio_reg_get(sch, gpio_num, GIO); +} +  static const struct gpio_chip sch_gpio_chip = {  	.label			= "sch_gpio",  	.owner			= THIS_MODULE, @@ -145,6 +151,7 @@ static const struct gpio_chip sch_gpio_chip = {  	.get			= sch_gpio_get,  	.direction_output	= sch_gpio_direction_out,  	.set			= sch_gpio_set, +	.get_direction		= sch_gpio_get_direction,  };  static int sch_gpio_probe(struct platform_device *pdev) diff --git a/drivers/gpio/gpio-sch311x.c b/drivers/gpio/gpio-sch311x.c index b96990c262a1..5497f0a88cf0 100644 --- a/drivers/gpio/gpio-sch311x.c +++ b/drivers/gpio/gpio-sch311x.c @@ -17,16 +17,15 @@  #include <linux/kernel.h>  #include <linux/init.h>  #include <linux/platform_device.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.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 SCH311X_GPIO_CONF_DIR		BIT(0) +#define SCH311X_GPIO_CONF_INVERT	BIT(1) +#define SCH311X_GPIO_CONF_OPEN_DRAIN	BIT(7)  #define SIO_CONFIG_KEY_ENTER		0x55  #define SIO_CONFIG_KEY_EXIT		0xaa @@ -163,7 +162,7 @@ static void sch311x_gpio_free(struct gpio_chip *chip, unsigned offset)  static int sch311x_gpio_get(struct gpio_chip *chip, unsigned offset)  {  	struct sch311x_gpio_block *block = gpiochip_get_data(chip); -	unsigned char data; +	u8 data;  	spin_lock(&block->lock);  	data = inb(block->runtime_reg + block->data_reg); @@ -175,7 +174,7 @@ static int sch311x_gpio_get(struct gpio_chip *chip, unsigned 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); +	u8 data = inb(block->runtime_reg + block->data_reg);  	if (value)  		data |= BIT(offset);  	else @@ -196,10 +195,12 @@ static void sch311x_gpio_set(struct gpio_chip *chip, unsigned offset,  static int sch311x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)  {  	struct sch311x_gpio_block *block = gpiochip_get_data(chip); +	u8 data;  	spin_lock(&block->lock); -	outb(SCH311X_GPIO_CONF_IN, block->runtime_reg + -	     block->config_regs[offset]); +	data = inb(block->runtime_reg + block->config_regs[offset]); +	data |= SCH311X_GPIO_CONF_DIR; +	outb(data, block->runtime_reg + block->config_regs[offset]);  	spin_unlock(&block->lock);  	return 0; @@ -209,18 +210,59 @@ static int sch311x_gpio_direction_out(struct gpio_chip *chip, unsigned offset,  				      int value)  {  	struct sch311x_gpio_block *block = gpiochip_get_data(chip); +	u8 data;  	spin_lock(&block->lock); -	outb(SCH311X_GPIO_CONF_OUT, block->runtime_reg + -	     block->config_regs[offset]); - +	data = inb(block->runtime_reg + block->config_regs[offset]); +	data &= ~SCH311X_GPIO_CONF_DIR; +	outb(data, block->runtime_reg + block->config_regs[offset]);  	__sch311x_gpio_set(block, offset, value);  	spin_unlock(&block->lock);  	return 0;  } +static int sch311x_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +{ +	struct sch311x_gpio_block *block = gpiochip_get_data(chip); +	u8 data; + +	spin_lock(&block->lock); +	data = inb(block->runtime_reg + block->config_regs[offset]); +	spin_unlock(&block->lock); + +	return !!(data & SCH311X_GPIO_CONF_DIR); +} + +static int sch311x_gpio_set_config(struct gpio_chip *chip, unsigned offset, +				   unsigned long config) +{ +	struct sch311x_gpio_block *block = gpiochip_get_data(chip); +	enum pin_config_param param = pinconf_to_config_param(config); +	u8 data; + +	switch (param) { +	case PIN_CONFIG_DRIVE_OPEN_DRAIN: +		spin_lock(&block->lock); +		data = inb(block->runtime_reg + block->config_regs[offset]); +		data |= SCH311X_GPIO_CONF_OPEN_DRAIN; +		outb(data, block->runtime_reg + block->config_regs[offset]); +		spin_unlock(&block->lock); +		return 0; +	case PIN_CONFIG_DRIVE_PUSH_PULL: +		spin_lock(&block->lock); +		data = inb(block->runtime_reg + block->config_regs[offset]); +		data &= ~SCH311X_GPIO_CONF_OPEN_DRAIN; +		outb(data, block->runtime_reg + block->config_regs[offset]); +		spin_unlock(&block->lock); +		return 0; +	default: +		break; +	} +	return -ENOTSUPP; +} +  static int sch311x_gpio_probe(struct platform_device *pdev)  {  	struct sch311x_pdev_data *pdata = dev_get_platdata(&pdev->dev); @@ -253,6 +295,8 @@ static int sch311x_gpio_probe(struct platform_device *pdev)  		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_direction = sch311x_gpio_get_direction; +		block->chip.set_config = sch311x_gpio_set_config;  		block->chip.get = sch311x_gpio_get;  		block->chip.set = sch311x_gpio_set;  		block->chip.ngpio = 8; @@ -309,7 +353,7 @@ static int __init sch311x_detect(int sio_config_port, unsigned short *addr)  {  	int err = 0, reg;  	unsigned short base_addr; -	unsigned char dev_id; +	u8 dev_id;  	err = sch311x_sio_enter(sio_config_port);  	if (err) diff --git a/drivers/gpio/gpio-spear-spics.c b/drivers/gpio/gpio-spear-spics.c index 22267479ba68..ee3039f091f4 100644 --- a/drivers/gpio/gpio-spear-spics.c +++ b/drivers/gpio/gpio-spear-spics.c @@ -10,7 +10,7 @@   */  #include <linux/err.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h>  #include <linux/io.h>  #include <linux/init.h>  #include <linux/of.h> diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c index 407359da08f9..2283c869ad5d 100644 --- a/drivers/gpio/gpio-sta2x11.c +++ b/drivers/gpio/gpio-sta2x11.c @@ -23,7 +23,8 @@  #include <linux/init.h>  #include <linux/kernel.h>  #include <linux/slab.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h> +#include <linux/bitops.h>  #include <linux/interrupt.h>  #include <linux/irq.h>  #include <linux/pci.h> @@ -58,16 +59,6 @@ struct gsta_gpio {  	unsigned			irq_type[GSTA_NR_GPIO];  }; -static inline struct gsta_regs __iomem *__regs(struct gsta_gpio *chip, int nr) -{ -	return chip->regs[nr / GSTA_GPIO_PER_BLOCK]; -} - -static inline u32 __bit(int nr) -{ -	return 1U << (nr % GSTA_GPIO_PER_BLOCK); -} -  /*   * gpio methods   */ @@ -75,8 +66,8 @@ static inline u32 __bit(int nr)  static void gsta_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)  {  	struct gsta_gpio *chip = gpiochip_get_data(gpio); -	struct gsta_regs __iomem *regs = __regs(chip, nr); -	u32 bit = __bit(nr); +	struct gsta_regs __iomem *regs = chip->regs[nr / GSTA_GPIO_PER_BLOCK]; +	u32 bit = BIT(nr % GSTA_GPIO_PER_BLOCK);  	if (val)  		writel(bit, ®s->dats); @@ -87,8 +78,8 @@ static void gsta_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)  static int gsta_gpio_get(struct gpio_chip *gpio, unsigned nr)  {  	struct gsta_gpio *chip = gpiochip_get_data(gpio); -	struct gsta_regs __iomem *regs = __regs(chip, nr); -	u32 bit = __bit(nr); +	struct gsta_regs __iomem *regs = chip->regs[nr / GSTA_GPIO_PER_BLOCK]; +	u32 bit = BIT(nr % GSTA_GPIO_PER_BLOCK);  	return !!(readl(®s->dat) & bit);  } @@ -97,8 +88,8 @@ static int gsta_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,  				      int val)  {  	struct gsta_gpio *chip = gpiochip_get_data(gpio); -	struct gsta_regs __iomem *regs = __regs(chip, nr); -	u32 bit = __bit(nr); +	struct gsta_regs __iomem *regs = chip->regs[nr / GSTA_GPIO_PER_BLOCK]; +	u32 bit = BIT(nr % GSTA_GPIO_PER_BLOCK);  	writel(bit, ®s->dirs);  	/* Data register after direction, otherwise pullup/down is selected */ @@ -112,8 +103,8 @@ static int gsta_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,  static int gsta_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)  {  	struct gsta_gpio *chip = gpiochip_get_data(gpio); -	struct gsta_regs __iomem *regs = __regs(chip, nr); -	u32 bit = __bit(nr); +	struct gsta_regs __iomem *regs = chip->regs[nr / GSTA_GPIO_PER_BLOCK]; +	u32 bit = BIT(nr % GSTA_GPIO_PER_BLOCK);  	writel(bit, ®s->dirc);  	return 0; @@ -165,9 +156,9 @@ static void gsta_gpio_setup(struct gsta_gpio *chip) /* called from probe */   */  static void gsta_set_config(struct gsta_gpio *chip, int nr, unsigned cfg)  { -	struct gsta_regs __iomem *regs = __regs(chip, nr); +	struct gsta_regs __iomem *regs = chip->regs[nr / GSTA_GPIO_PER_BLOCK];  	unsigned long flags; -	u32 bit = __bit(nr); +	u32 bit = BIT(nr % GSTA_GPIO_PER_BLOCK);  	u32 val;  	int err = 0; @@ -234,8 +225,8 @@ static void gsta_irq_disable(struct irq_data *data)  	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);  	struct gsta_gpio *chip = gc->private;  	int nr = data->irq - chip->irq_base; -	struct gsta_regs __iomem *regs = __regs(chip, nr); -	u32 bit = __bit(nr); +	struct gsta_regs __iomem *regs = chip->regs[nr / GSTA_GPIO_PER_BLOCK]; +	u32 bit = BIT(nr % GSTA_GPIO_PER_BLOCK);  	u32 val;  	unsigned long flags; @@ -257,8 +248,8 @@ static void gsta_irq_enable(struct irq_data *data)  	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);  	struct gsta_gpio *chip = gc->private;  	int nr = data->irq - chip->irq_base; -	struct gsta_regs __iomem *regs = __regs(chip, nr); -	u32 bit = __bit(nr); +	struct gsta_regs __iomem *regs = chip->regs[nr / GSTA_GPIO_PER_BLOCK]; +	u32 bit = BIT(nr % GSTA_GPIO_PER_BLOCK);  	u32 val;  	int type;  	unsigned long flags; diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index 8d6a5a7e612d..65a2315f1673 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c @@ -8,7 +8,7 @@  #include <linux/init.h>  #include <linux/platform_device.h>  #include <linux/slab.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h>  #include <linux/interrupt.h>  #include <linux/of.h>  #include <linux/mfd/stmpe.h> diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c index c07385b71403..19972084c45b 100644 --- a/drivers/gpio/gpio-stp-xway.c +++ b/drivers/gpio/gpio-stp-xway.c @@ -13,9 +13,8 @@  #include <linux/types.h>  #include <linux/of_platform.h>  #include <linux/mutex.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h>  #include <linux/io.h> -#include <linux/of_gpio.h>  #include <linux/clk.h>  #include <linux/err.h> @@ -91,6 +90,20 @@ struct xway_stp {  };  /** + * xway_stp_get() - gpio_chip->get - get gpios. + * @gc:     Pointer to gpio_chip device structure. + * @gpio:   GPIO signal number. + * + * Gets the shadow value. + */ +static int xway_stp_get(struct gpio_chip *gc, unsigned int gpio) +{ +	struct xway_stp *chip = gpiochip_get_data(gc); + +	return (xway_stp_r32(chip->virt, XWAY_STP_CPU0) & BIT(gpio)); +} + +/**   * xway_stp_set() - gpio_chip->set - set gpios.   * @gc:     Pointer to gpio_chip device structure.   * @gpio:   GPIO signal number. @@ -215,6 +228,7 @@ static int xway_stp_probe(struct platform_device *pdev)  	chip->gc.parent = &pdev->dev;  	chip->gc.label = "stp-xway";  	chip->gc.direction_output = xway_stp_dir_out; +	chip->gc.get = xway_stp_get;  	chip->gc.set = xway_stp_set;  	chip->gc.request = xway_stp_request;  	chip->gc.base = -1; diff --git a/drivers/gpio/gpio-syscon.c b/drivers/gpio/gpio-syscon.c index 8b0a69c5ba88..87c18a544513 100644 --- a/drivers/gpio/gpio-syscon.c +++ b/drivers/gpio/gpio-syscon.c @@ -10,7 +10,7 @@   */  #include <linux/err.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h>  #include <linux/module.h>  #include <linux/of.h>  #include <linux/of_device.h> @@ -135,6 +135,33 @@ static const struct syscon_gpio_data clps711x_mctrl_gpio = {  	.dat_bit_offset	= 0x40 * 8 + 8,  }; +static void rockchip_gpio_set(struct gpio_chip *chip, unsigned int offset, +			      int val) +{ +	struct syscon_gpio_priv *priv = gpiochip_get_data(chip); +	unsigned int offs; +	u8 bit; +	u32 data; +	int ret; + +	offs = priv->dreg_offset + priv->data->dat_bit_offset + offset; +	bit = offs % SYSCON_REG_BITS; +	data = (val ? BIT(bit) : 0) | BIT(bit + 16); +	ret = regmap_write(priv->syscon, +			   (offs / SYSCON_REG_BITS) * SYSCON_REG_SIZE, +			   data); +	if (ret < 0) +		dev_err(chip->parent, "gpio write failed ret(%d)\n", ret); +} + +static const struct syscon_gpio_data rockchip_rk3328_gpio_mute = { +	/* RK3328 GPIO_MUTE is an output only pin at GRF_SOC_CON10[1] */ +	.flags		= GPIO_SYSCON_FEAT_OUT, +	.bit_count	= 1, +	.dat_bit_offset = 0x0428 * 8 + 1, +	.set		= rockchip_gpio_set, +}; +  #define KEYSTONE_LOCK_BIT BIT(0)  static void keystone_gpio_set(struct gpio_chip *chip, unsigned offset, int val) @@ -175,6 +202,10 @@ static const struct of_device_id syscon_gpio_ids[] = {  		.compatible	= "ti,keystone-dsp-gpio",  		.data		= &keystone_dsp_gpio,  	}, +	{ +		.compatible	= "rockchip,rk3328-grf-gpio", +		.data		= &rockchip_rk3328_gpio_mute, +	},  	{ }  };  MODULE_DEVICE_TABLE(of, syscon_gpio_ids); diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c index ac6f2a9841e5..a12cd0b5c972 100644 --- a/drivers/gpio/gpio-tb10x.c +++ b/drivers/gpio/gpio-tb10x.c @@ -22,7 +22,7 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/platform_device.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h>  #include <linux/slab.h>  #include <linux/irq.h>  #include <linux/irqdomain.h> @@ -30,7 +30,6 @@  #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> diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 94396caaca75..47dbd19751d0 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -22,7 +22,7 @@  #include <linux/irq.h>  #include <linux/interrupt.h>  #include <linux/io.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h>  #include <linux/of_device.h>  #include <linux/platform_device.h>  #include <linux/module.h> @@ -207,7 +207,7 @@ static int tegra_gpio_get_direction(struct gpio_chip *chip,  	oe = tegra_gpio_readl(tgi, GPIO_OE(tgi, offset)); -	return (oe & pin_mask) ? GPIOF_DIR_OUT : GPIOF_DIR_IN; +	return !(oe & pin_mask);  }  static int tegra_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset, @@ -323,13 +323,6 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)  		return -EINVAL;  	} -	ret = gpiochip_lock_as_irq(&tgi->gc, gpio); -	if (ret) { -		dev_err(tgi->dev, -			"unable to lock Tegra GPIO %u as IRQ\n", gpio); -		return ret; -	} -  	spin_lock_irqsave(&bank->lvl_lock[port], flags);  	val = tegra_gpio_readl(tgi, GPIO_INT_LVL(tgi, gpio)); @@ -342,6 +335,14 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)  	tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, gpio), gpio, 0);  	tegra_gpio_enable(tgi, gpio); +	ret = gpiochip_lock_as_irq(&tgi->gc, gpio); +	if (ret) { +		dev_err(tgi->dev, +			"unable to lock Tegra GPIO %u as IRQ\n", gpio); +		tegra_gpio_disable(tgi, gpio); +		return ret; +	} +  	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))  		irq_set_handler_locked(d, handle_level_irq);  	else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) @@ -550,13 +551,6 @@ static const struct dev_pm_ops tegra_gpio_pm_ops = {  	SET_SYSTEM_SLEEP_PM_OPS(tegra_gpio_suspend, tegra_gpio_resume)  }; -/* - * 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 struct lock_class_key gpio_request_class; -  static int tegra_gpio_probe(struct platform_device *pdev)  {  	struct tegra_gpio_info *tgi; @@ -661,8 +655,6 @@ static int tegra_gpio_probe(struct platform_device *pdev)  		bank = &tgi->bank_info[GPIO_BANK(gpio)]; -		irq_set_lockdep_class(irq, &gpio_lock_class, -				      &gpio_request_class);  		irq_set_chip_data(irq, bank);  		irq_set_chip_and_handler(irq, &tgi->ic, handle_simple_irq);  	} @@ -720,4 +712,4 @@ static int __init tegra_gpio_init(void)  {  	return platform_driver_register(&tegra_gpio_driver);  } -postcore_initcall(tegra_gpio_init); +subsys_initcall(tegra_gpio_init); diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index 7f1aa4c21e0d..9d0292c8a199 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -16,6 +16,7 @@  #include <linux/platform_device.h>  #include <dt-bindings/gpio/tegra186-gpio.h> +#include <dt-bindings/gpio/tegra194-gpio.h>  #define TEGRA186_GPIO_ENABLE_CONFIG 0x00  #define  TEGRA186_GPIO_ENABLE_CONFIG_ENABLE BIT(0) @@ -593,6 +594,73 @@ static const struct tegra_gpio_soc tegra186_aon_soc = {  	.name = "tegra186-gpio-aon",  }; +#define TEGRA194_MAIN_GPIO_PORT(port, base, count, controller)	\ +	[TEGRA194_MAIN_GPIO_PORT_##port] = {			\ +		.name = #port,					\ +		.offset = base,					\ +		.pins = count,					\ +		.irq = controller,				\ +	} + +static const struct tegra_gpio_port tegra194_main_ports[] = { +	TEGRA194_MAIN_GPIO_PORT( A, 0x1400, 8, 1), +	TEGRA194_MAIN_GPIO_PORT( B, 0x4e00, 2, 4), +	TEGRA194_MAIN_GPIO_PORT( C, 0x4600, 8, 4), +	TEGRA194_MAIN_GPIO_PORT( D, 0x4800, 4, 4), +	TEGRA194_MAIN_GPIO_PORT( E, 0x4a00, 8, 4), +	TEGRA194_MAIN_GPIO_PORT( F, 0x4c00, 6, 4), +	TEGRA194_MAIN_GPIO_PORT( G, 0x4000, 8, 4), +	TEGRA194_MAIN_GPIO_PORT( H, 0x4200, 8, 4), +	TEGRA194_MAIN_GPIO_PORT( I, 0x4400, 5, 4), +	TEGRA194_MAIN_GPIO_PORT( J, 0x5200, 6, 5), +	TEGRA194_MAIN_GPIO_PORT( K, 0x3000, 8, 3), +	TEGRA194_MAIN_GPIO_PORT( L, 0x3200, 4, 3), +	TEGRA194_MAIN_GPIO_PORT( M, 0x2600, 8, 2), +	TEGRA194_MAIN_GPIO_PORT( N, 0x2800, 3, 2), +	TEGRA194_MAIN_GPIO_PORT( O, 0x5000, 6, 5), +	TEGRA194_MAIN_GPIO_PORT( P, 0x2a00, 8, 2), +	TEGRA194_MAIN_GPIO_PORT( Q, 0x2c00, 8, 2), +	TEGRA194_MAIN_GPIO_PORT( R, 0x2e00, 6, 2), +	TEGRA194_MAIN_GPIO_PORT( S, 0x3600, 8, 3), +	TEGRA194_MAIN_GPIO_PORT( T, 0x3800, 8, 3), +	TEGRA194_MAIN_GPIO_PORT( U, 0x3a00, 1, 3), +	TEGRA194_MAIN_GPIO_PORT( V, 0x1000, 8, 1), +	TEGRA194_MAIN_GPIO_PORT( W, 0x1200, 2, 1), +	TEGRA194_MAIN_GPIO_PORT( X, 0x2000, 8, 2), +	TEGRA194_MAIN_GPIO_PORT( Y, 0x2200, 8, 2), +	TEGRA194_MAIN_GPIO_PORT( Z, 0x2400, 8, 2), +	TEGRA194_MAIN_GPIO_PORT(FF, 0x3400, 2, 3), +	TEGRA194_MAIN_GPIO_PORT(GG, 0x0000, 2, 0) +}; + +static const struct tegra_gpio_soc tegra194_main_soc = { +	.num_ports = ARRAY_SIZE(tegra194_main_ports), +	.ports = tegra194_main_ports, +	.name = "tegra194-gpio", +}; + +#define TEGRA194_AON_GPIO_PORT(port, base, count, controller)	\ +	[TEGRA194_AON_GPIO_PORT_##port] = {			\ +		.name = #port,					\ +		.offset = base,					\ +		.pins = count,					\ +		.irq = controller,				\ +	} + +static const struct tegra_gpio_port tegra194_aon_ports[] = { +	TEGRA194_AON_GPIO_PORT(AA, 0x0600, 8, 0), +	TEGRA194_AON_GPIO_PORT(BB, 0x0800, 4, 0), +	TEGRA194_AON_GPIO_PORT(CC, 0x0200, 8, 0), +	TEGRA194_AON_GPIO_PORT(DD, 0x0400, 3, 0), +	TEGRA194_AON_GPIO_PORT(EE, 0x0000, 7, 0) +}; + +static const struct tegra_gpio_soc tegra194_aon_soc = { +	.num_ports = ARRAY_SIZE(tegra194_aon_ports), +	.ports = tegra194_aon_ports, +	.name = "tegra194-gpio-aon", +}; +  static const struct of_device_id tegra186_gpio_of_match[] = {  	{  		.compatible = "nvidia,tegra186-gpio", @@ -601,6 +669,12 @@ static const struct of_device_id tegra186_gpio_of_match[] = {  		.compatible = "nvidia,tegra186-gpio-aon",  		.data = &tegra186_aon_soc  	}, { +		.compatible = "nvidia,tegra194-gpio", +		.data = &tegra194_main_soc +	}, { +		.compatible = "nvidia,tegra194-gpio-aon", +		.data = &tegra194_aon_soc +	}, {  		/* sentinel */  	}  }; diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index 6520a8475910..314e300d6ba3 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -22,7 +22,7 @@   */  #include <linux/init.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h>  #include <linux/platform_device.h>  #include <linux/irq.h>  #include <linux/io.h> diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c index 58faeb1cef63..7fdac9060979 100644 --- a/drivers/gpio/gpio-uniphier.c +++ b/drivers/gpio/gpio-uniphier.c @@ -310,8 +310,7 @@ static int uniphier_gpio_irq_domain_activate(struct irq_domain *domain,  	struct uniphier_gpio_priv *priv = domain->host_data;  	struct gpio_chip *chip = &priv->chip; -	gpiochip_lock_as_irq(chip, data->hwirq + UNIPHIER_GPIO_IRQ_OFFSET); -	return 0; +	return gpiochip_lock_as_irq(chip, data->hwirq + UNIPHIER_GPIO_IRQ_OFFSET);  }  static void uniphier_gpio_irq_domain_deactivate(struct irq_domain *domain, diff --git a/drivers/gpio/gpio-vr41xx.c b/drivers/gpio/gpio-vr41xx.c index ac8deb01f6f6..027699cec911 100644 --- a/drivers/gpio/gpio-vr41xx.c +++ b/drivers/gpio/gpio-vr41xx.c @@ -138,10 +138,16 @@ static void unmask_giuint_low(struct irq_data *d)  static unsigned int startup_giuint(struct irq_data *data)  { -	if (gpiochip_lock_as_irq(&vr41xx_gpio_chip, data->hwirq)) +	int ret; + +	ret = gpiochip_lock_as_irq(&vr41xx_gpio_chip, irqd_to_hwirq(data)); +	if (ret) {  		dev_err(vr41xx_gpio_chip.parent,  			"unable to lock HW IRQ %lu for IRQ\n",  			data->hwirq); +		return ret; +	} +  	/* Satisfy the .enable semantics by unmasking the line */  	unmask_giuint_low(data);  	return 0; diff --git a/drivers/gpio/gpio-xgene-sb.c b/drivers/gpio/gpio-xgene-sb.c index acd59113e08b..2eb76f35aa7e 100644 --- a/drivers/gpio/gpio-xgene-sb.c +++ b/drivers/gpio/gpio-xgene-sb.c @@ -143,12 +143,14 @@ static int xgene_gpio_sb_domain_activate(struct irq_domain *d,  {  	struct xgene_gpio_sb *priv = d->host_data;  	u32 gpio = HWIRQ_TO_GPIO(priv, irq_data->hwirq); +	int ret; -	if (gpiochip_lock_as_irq(&priv->gc, gpio)) { +	ret = gpiochip_lock_as_irq(&priv->gc, gpio); +	if (ret) {  		dev_err(priv->gc.parent,  		"Unable to configure XGene GPIO standby pin %d as IRQ\n",  				gpio); -		return -ENOSPC; +		return ret;  	}  	xgene_gpio_set_bit(&priv->gc, priv->regs + MPA_GPIO_SEL_LO, diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index e8ec0e33a0a9..8f24478cc18b 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -20,7 +20,7 @@  #include <linux/of_platform.h>  #include <linux/of_gpio.h>  #include <linux/io.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h>  #include <linux/slab.h>  /* Register Offset Definitions */ diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index addd9fecc198..c48ed9d89ff5 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -389,7 +389,7 @@ EXPORT_SYMBOL_GPL(devm_acpi_dev_remove_driver_gpios);  static bool acpi_get_driver_gpio_data(struct acpi_device *adev,  				      const char *name, int index, -				      struct acpi_reference_args *args, +				      struct fwnode_reference_args *args,  				      unsigned int *quirks)  {  	const struct acpi_gpio_mapping *gm; @@ -401,7 +401,7 @@ static bool acpi_get_driver_gpio_data(struct acpi_device *adev,  		if (!strcmp(name, gm->name) && gm->data && index < gm->size) {  			const struct acpi_gpio_params *par = gm->data + index; -			args->adev = adev; +			args->fwnode = acpi_fwnode_handle(adev);  			args->args[0] = par->crs_entry_index;  			args->args[1] = par->line_index;  			args->args[2] = par->active_low; @@ -564,7 +564,7 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,  				     const char *propname, int index,  				     struct acpi_gpio_lookup *lookup)  { -	struct acpi_reference_args args; +	struct fwnode_reference_args args;  	unsigned int quirks = 0;  	int ret; @@ -585,6 +585,8 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,  	 * The property was found and resolved, so need to lookup the GPIO based  	 * on returned args.  	 */ +	if (!to_acpi_device_node(args.fwnode)) +		return -EINVAL;  	if (args.nargs != 3)  		return -EPROTO; @@ -592,8 +594,9 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,  	lookup->pin_index = args.args[1];  	lookup->active_low = !!args.args[2]; -	lookup->info.adev = args.adev; +	lookup->info.adev = to_acpi_device_node(args.fwnode);  	lookup->info.quirks = quirks; +  	return 0;  } diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 53a14ee8ad6d..a4f1157d6aa0 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -621,9 +621,6 @@ int of_gpiochip_add(struct gpio_chip *chip)  {  	int status; -	if ((!chip->of_node) && (chip->parent)) -		chip->of_node = chip->parent->of_node; -  	if (!chip->of_node)  		return 0; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index e11a3bb03820..e8f8a1999393 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -431,7 +431,7 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd,  	int i;  	if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) { -		/* TODO: check if descriptors are really input */ +		/* NOTE: It's ok to read values of output lines. */  		int ret = gpiod_get_array_value_complex(false,  							true,  							lh->numdescs, @@ -449,7 +449,13 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd,  		return 0;  	} else if (cmd == GPIOHANDLE_SET_LINE_VALUES_IOCTL) { -		/* TODO: check if descriptors are really output */ +		/* +		 * All line descriptors were created at once with the same +		 * flags so just check if the first one is really output. +		 */ +		if (!test_bit(FLAG_IS_OUT, &lh->descs[0]->flags)) +			return -EPERM; +  		if (copy_from_user(&ghd, ip, sizeof(ghd)))  			return -EFAULT; @@ -1256,6 +1262,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,  	/* If the gpiochip has an assigned OF node this takes precedence */  	if (chip->of_node)  		gdev->dev.of_node = chip->of_node; +	else +		chip->of_node = gdev->dev.of_node;  #endif  	gdev->id = ida_simple_get(&gpio_ida, 0, 0, GFP_KERNEL); @@ -1408,9 +1416,9 @@ err_free_descs:  err_free_gdev:  	ida_simple_remove(&gpio_ida, gdev->id);  	/* failures here can mean systems won't boot... */ -	pr_err("%s: GPIOs %d..%d (%s) failed to register\n", __func__, +	pr_err("%s: GPIOs %d..%d (%s) failed to register, %d\n", __func__,  	       gdev->base, gdev->base + gdev->ngpio - 1, -	       chip->label ? : "generic"); +	       chip->label ? : "generic", status);  	kfree(gdev);  	return status;  } @@ -1664,8 +1672,7 @@ static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gpiochip,  	if (parent_handler) {  		if (gpiochip->can_sleep) {  			chip_err(gpiochip, -				 "you cannot have chained interrupts on a " -				 "chip that may sleep\n"); +				 "you cannot have chained interrupts on a chip that may sleep\n");  			return;  		}  		/* @@ -1800,16 +1807,18 @@ static const struct irq_domain_ops gpiochip_domain_ops = {  static int gpiochip_irq_reqres(struct irq_data *d)  {  	struct gpio_chip *chip = irq_data_get_irq_chip_data(d); +	int ret;  	if (!try_module_get(chip->gpiodev->owner))  		return -ENODEV; -	if (gpiochip_lock_as_irq(chip, d->hwirq)) { +	ret = gpiochip_lock_as_irq(chip, d->hwirq); +	if (ret) {  		chip_err(chip,  			"unable to lock HW IRQ %lu for IRQ\n",  			d->hwirq);  		module_put(chip->gpiodev->owner); -		return -EINVAL; +		return ret;  	}  	return 0;  } @@ -1850,8 +1859,7 @@ static int gpiochip_add_irqchip(struct gpio_chip *gpiochip,  		return 0;  	if (gpiochip->irq.parent_handler && gpiochip->can_sleep) { -		chip_err(gpiochip, "you cannot have chained interrupts on a " -			 "chip that may sleep\n"); +		chip_err(gpiochip, "you cannot have chained interrupts on a chip that may sleep\n");  		return -EINVAL;  	} @@ -2259,6 +2267,7 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label)  	struct gpio_chip	*chip = desc->gdev->chip;  	int			status;  	unsigned long		flags; +	unsigned		offset;  	spin_lock_irqsave(&gpio_lock, flags); @@ -2277,7 +2286,11 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label)  	if (chip->request) {  		/* chip->request may sleep */  		spin_unlock_irqrestore(&gpio_lock, flags); -		status = chip->request(chip, gpio_chip_hwgpio(desc)); +		offset = gpio_chip_hwgpio(desc); +		if (gpiochip_line_is_valid(chip, offset)) +			status = chip->request(chip, offset); +		else +			status = -EINVAL;  		spin_lock_irqsave(&gpio_lock, flags);  		if (status < 0) { @@ -3194,6 +3207,19 @@ int gpiod_cansleep(const struct gpio_desc *desc)  EXPORT_SYMBOL_GPL(gpiod_cansleep);  /** + * gpiod_set_consumer_name() - set the consumer name for the descriptor + * @desc: gpio to set the consumer name on + * @name: the new consumer name + */ +void gpiod_set_consumer_name(struct gpio_desc *desc, const char *name) +{ +	VALIDATE_DESC_VOID(desc); +	/* Just overwrite whatever the previous name was */ +	desc->label = name; +} +EXPORT_SYMBOL_GPL(gpiod_set_consumer_name); + +/**   * gpiod_to_irq() - return the IRQ corresponding to a GPIO   * @desc: gpio whose IRQ will be returned (already requested)   * @@ -3249,18 +3275,19 @@ int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)  	 * behind our back  	 */  	if (!chip->can_sleep && chip->get_direction) { -		int dir = chip->get_direction(chip, offset); +		int dir = gpiod_get_direction(desc); -		if (dir) -			clear_bit(FLAG_IS_OUT, &desc->flags); -		else -			set_bit(FLAG_IS_OUT, &desc->flags); +		if (dir < 0) { +			chip_err(chip, "%s: cannot get GPIO direction\n", +				 __func__); +			return dir; +		}  	}  	if (test_bit(FLAG_IS_OUT, &desc->flags)) {  		chip_err(chip, -			  "%s: tried to flag a GPIO set as output for IRQ\n", -			  __func__); +			 "%s: tried to flag a GPIO set as output for IRQ\n", +			 __func__);  		return -EIO;  	} @@ -3639,9 +3666,16 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,  		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); +			/* +			 * As the lookup table indicates a chip with +			 * p->chip_label should exist, assume it may +			 * still appear later and let the interested +			 * consumer be probed again or let the Deferred +			 * Probe infrastructure handle the error. +			 */ +			dev_warn(dev, "cannot find GPIO chip %s, deferring\n", +				 p->chip_label); +			return ERR_PTR(-EPROBE_DEFER);  		}  		if (chip->ngpio <= p->chip_hwnum) { @@ -4215,7 +4249,7 @@ static int __init gpiolib_dev_init(void)  	int ret;  	/* Register GPIO sysfs bus */ -	ret  = bus_register(&gpio_bus_type); +	ret = bus_register(&gpio_bus_type);  	if (ret < 0) {  		pr_err("gpiolib: could not register GPIO bus type\n");  		return ret; @@ -4259,9 +4293,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_device *gdev)  		seq_printf(s, " gpio-%-3d (%-20.20s|%-20.20s) %s %s %s",  			gpio, gdesc->name ? gdesc->name : "", gdesc->label,  			is_out ? "out" : "in ", -			chip->get -				? (chip->get(chip, i) ? "hi" : "lo") -				: "?  ", +			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 index 1a8e20363861..a7e49fef73d4 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -92,7 +92,7 @@ struct acpi_gpio_info {  };  /* gpio suffixes used for ACPI and device tree lookup */ -static const char * const gpio_suffixes[] = { "gpios", "gpio" }; +static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" };  #ifdef CONFIG_OF_GPIO  struct gpio_desc *of_find_gpio(struct device *dev,  | 
