diff options
| author | Grant Likely <grant.likely@secretlab.ca> | 2013-02-05 13:33:49 +0000 | 
|---|---|---|
| committer | Grant Likely <grant.likely@secretlab.ca> | 2013-02-05 13:37:46 +0000 | 
| commit | 0fa2fd9a0d4f1305a54a396d44975894e90eed7b (patch) | |
| tree | 56045663b63cb29c2515e0c87519ff10398c4ab0 /drivers | |
| parent | 46ebfbc3745597067494186a0e7031add22f3134 (diff) | |
| parent | 476171ce7850b28280db6a2d0c0e4d3ff26c8117 (diff) | |
Merge branch 'linusw/devel' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git into gpio/next
Device driver features, cleanups and bug fixes.
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gpio/Kconfig | 3 | ||||
| -rw-r--r-- | drivers/gpio/Makefile | 3 | ||||
| -rw-r--r-- | drivers/gpio/gpio-mpc8xxx.c | 1 | ||||
| -rw-r--r-- | drivers/gpio/gpio-mxs.c | 31 | ||||
| -rw-r--r-- | drivers/gpio/gpio-pca953x.c | 380 | ||||
| -rw-r--r-- | drivers/gpio/gpio-pl061.c | 2 | ||||
| -rw-r--r-- | drivers/gpio/gpio-pxa.c | 7 | ||||
| -rw-r--r-- | drivers/gpio/gpio-twl4030.c | 176 | ||||
| -rw-r--r-- | drivers/gpio/gpio-vt8500.c | 4 | ||||
| -rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 87 | ||||
| -rw-r--r-- | drivers/gpio/gpiolib.c | 63 | 
11 files changed, 463 insertions, 294 deletions
| diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3a6714539201..ab97eb805379 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -30,6 +30,9 @@ config ARCH_REQUIRE_GPIOLIB  	  Selecting this from the architecture code will cause the gpiolib  	  code to always get built in. +config GPIO_DEVRES +	def_bool y +	depends on HAS_IOMEM  menuconfig GPIOLIB diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 519daaf57daf..4398034db4aa 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -2,7 +2,8 @@  ccflags-$(CONFIG_DEBUG_GPIO)	+= -DDEBUG -obj-$(CONFIG_GPIOLIB)		+= gpiolib.o devres.o +obj-$(CONFIG_GPIO_DEVRES)	+= devres.o +obj-$(CONFIG_GPIOLIB)		+= gpiolib.o  obj-$(CONFIG_OF_GPIO)		+= gpiolib-of.o  obj-$(CONFIG_GPIO_ACPI)		+= gpiolib-acpi.o diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index 9ae29cc0d17f..a0b33a216d4a 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -292,7 +292,6 @@ static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int virq,  	irq_set_chip_data(virq, h->host_data);  	irq_set_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq); -	irq_set_irq_type(virq, IRQ_TYPE_NONE);  	return 0;  } diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index fa2a63cad32e..859b6fabc7bc 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -65,6 +65,7 @@ struct mxs_gpio_port {  	struct irq_domain *domain;  	struct bgpio_chip bgc;  	enum mxs_gpio_id devid; +	u32 both_edges;  };  static inline int is_imx23_gpio(struct mxs_gpio_port *port) @@ -81,13 +82,23 @@ static inline int is_imx28_gpio(struct mxs_gpio_port *port)  static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)  { +	u32 val;  	u32 pin_mask = 1 << d->hwirq;  	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);  	struct mxs_gpio_port *port = gc->private;  	void __iomem *pin_addr;  	int edge; +	port->both_edges &= ~pin_mask;  	switch (type) { +	case IRQ_TYPE_EDGE_BOTH: +		val = gpio_get_value(port->bgc.gc.base + d->hwirq); +		if (val) +			edge = GPIO_INT_FALL_EDGE; +		else +			edge = GPIO_INT_RISE_EDGE; +		port->both_edges |= pin_mask; +		break;  	case IRQ_TYPE_EDGE_RISING:  		edge = GPIO_INT_RISE_EDGE;  		break; @@ -124,6 +135,23 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)  	return 0;  } +static void mxs_flip_edge(struct mxs_gpio_port *port, u32 gpio) +{ +	u32 bit, val, edge; +	void __iomem *pin_addr; + +	bit = 1 << gpio; + +	pin_addr = port->base + PINCTRL_IRQPOL(port); +	val = readl(pin_addr); +	edge = val & bit; + +	if (edge) +		writel(bit, pin_addr + MXS_CLR); +	else +		writel(bit, pin_addr + MXS_SET); +} +  /* MXS has one interrupt *per* gpio port */  static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)  { @@ -137,6 +165,9 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)  	while (irq_stat != 0) {  		int irqoffset = fls(irq_stat) - 1; +		if (port->both_edges & (1 << irqoffset)) +			mxs_flip_edge(port, irqoffset); +  		generic_handle_irq(irq_find_mapping(port->domain, irqoffset));  		irq_stat &= ~(1 << irqoffset);  	} diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index cc102d25ee24..24059462c87f 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -46,6 +46,7 @@  #define PCA957X_TYPE		0x2000  static const struct i2c_device_id pca953x_id[] = { +	{ "pca9505", 40 | PCA953X_TYPE | PCA_INT, },  	{ "pca9534", 8  | PCA953X_TYPE | PCA_INT, },  	{ "pca9535", 16 | PCA953X_TYPE | PCA_INT, },  	{ "pca9536", 4  | PCA953X_TYPE, }, @@ -71,19 +72,23 @@ static const struct i2c_device_id pca953x_id[] = {  };  MODULE_DEVICE_TABLE(i2c, pca953x_id); +#define MAX_BANK 5 +#define BANK_SZ 8 + +#define NBANK(chip) (chip->gpio_chip.ngpio / BANK_SZ) +  struct pca953x_chip {  	unsigned gpio_start; -	u32 reg_output; -	u32 reg_direction; +	u8 reg_output[MAX_BANK]; +	u8 reg_direction[MAX_BANK];  	struct mutex i2c_lock;  #ifdef CONFIG_GPIO_PCA953X_IRQ  	struct mutex irq_lock; -	u32 irq_mask; -	u32 irq_stat; -	u32 irq_trig_raise; -	u32 irq_trig_fall; -	int	 irq_base; +	u8 irq_mask[MAX_BANK]; +	u8 irq_stat[MAX_BANK]; +	u8 irq_trig_raise[MAX_BANK]; +	u8 irq_trig_fall[MAX_BANK];  	struct irq_domain *domain;  #endif @@ -93,33 +98,69 @@ struct pca953x_chip {  	int	chip_type;  }; -static int pca953x_write_reg(struct pca953x_chip *chip, int reg, u32 val) +static int pca953x_read_single(struct pca953x_chip *chip, int reg, u32 *val, +				int off) +{ +	int ret; +	int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); +	int offset = off / BANK_SZ; + +	ret = i2c_smbus_read_byte_data(chip->client, +				(reg << bank_shift) + offset); +	*val = ret; + +	if (ret < 0) { +		dev_err(&chip->client->dev, "failed reading register\n"); +		return ret; +	} + +	return 0; +} + +static int pca953x_write_single(struct pca953x_chip *chip, int reg, u32 val, +				int off) +{ +	int ret = 0; +	int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); +	int offset = off / BANK_SZ; + +	ret = i2c_smbus_write_byte_data(chip->client, +					(reg << bank_shift) + offset, val); + +	if (ret < 0) { +		dev_err(&chip->client->dev, "failed writing register\n"); +		return ret; +	} + +	return 0; +} + +static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val)  {  	int ret = 0;  	if (chip->gpio_chip.ngpio <= 8) -		ret = i2c_smbus_write_byte_data(chip->client, reg, val); -	else if (chip->gpio_chip.ngpio == 24) { -		cpu_to_le32s(&val); +		ret = i2c_smbus_write_byte_data(chip->client, reg, *val); +	else if (chip->gpio_chip.ngpio >= 24) { +		int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ);  		ret = i2c_smbus_write_i2c_block_data(chip->client, -						(reg << 2) | REG_ADDR_AI, -						3, -						(u8 *) &val); +					(reg << bank_shift) | REG_ADDR_AI, +					NBANK(chip), val);  	}  	else {  		switch (chip->chip_type) {  		case PCA953X_TYPE:  			ret = i2c_smbus_write_word_data(chip->client, -							reg << 1, val); +							reg << 1, (u16) *val);  			break;  		case PCA957X_TYPE:  			ret = i2c_smbus_write_byte_data(chip->client, reg << 1, -							val & 0xff); +							val[0]);  			if (ret < 0)  				break;  			ret = i2c_smbus_write_byte_data(chip->client,  							(reg << 1) + 1, -							(val & 0xff00) >> 8); +							val[1]);  			break;  		}  	} @@ -132,26 +173,24 @@ static int pca953x_write_reg(struct pca953x_chip *chip, int reg, u32 val)  	return 0;  } -static int pca953x_read_reg(struct pca953x_chip *chip, int reg, u32 *val) +static int pca953x_read_regs(struct pca953x_chip *chip, int reg, u8 *val)  {  	int ret;  	if (chip->gpio_chip.ngpio <= 8) {  		ret = i2c_smbus_read_byte_data(chip->client, reg);  		*val = ret; -	} -	else if (chip->gpio_chip.ngpio == 24) { -		*val = 0; +	} else if (chip->gpio_chip.ngpio >= 24) { +		int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); +  		ret = i2c_smbus_read_i2c_block_data(chip->client, -						(reg << 2) | REG_ADDR_AI, -						3, -						(u8 *) val); -		le32_to_cpus(val); +					(reg << bank_shift) | REG_ADDR_AI, +					NBANK(chip), val);  	} else {  		ret = i2c_smbus_read_word_data(chip->client, reg << 1); -		*val = ret; +		val[0] = (u16)ret & 0xFF; +		val[1] = (u16)ret >> 8;  	} -  	if (ret < 0) {  		dev_err(&chip->client->dev, "failed reading register\n");  		return ret; @@ -163,13 +202,13 @@ static int pca953x_read_reg(struct pca953x_chip *chip, int reg, u32 *val)  static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)  {  	struct pca953x_chip *chip; -	uint reg_val; +	u8 reg_val;  	int ret, offset = 0;  	chip = container_of(gc, struct pca953x_chip, gpio_chip);  	mutex_lock(&chip->i2c_lock); -	reg_val = chip->reg_direction | (1u << off); +	reg_val = chip->reg_direction[off / BANK_SZ] | (1u << (off % BANK_SZ));  	switch (chip->chip_type) {  	case PCA953X_TYPE: @@ -179,11 +218,11 @@ static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)  		offset = PCA957X_CFG;  		break;  	} -	ret = pca953x_write_reg(chip, offset, reg_val); +	ret = pca953x_write_single(chip, offset, reg_val, off);  	if (ret)  		goto exit; -	chip->reg_direction = reg_val; +	chip->reg_direction[off / BANK_SZ] = reg_val;  	ret = 0;  exit:  	mutex_unlock(&chip->i2c_lock); @@ -194,7 +233,7 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,  		unsigned off, int val)  {  	struct pca953x_chip *chip; -	uint reg_val; +	u8 reg_val;  	int ret, offset = 0;  	chip = container_of(gc, struct pca953x_chip, gpio_chip); @@ -202,9 +241,11 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,  	mutex_lock(&chip->i2c_lock);  	/* set output level */  	if (val) -		reg_val = chip->reg_output | (1u << off); +		reg_val = chip->reg_output[off / BANK_SZ] +			| (1u << (off % BANK_SZ));  	else -		reg_val = chip->reg_output & ~(1u << off); +		reg_val = chip->reg_output[off / BANK_SZ] +			& ~(1u << (off % BANK_SZ));  	switch (chip->chip_type) {  	case PCA953X_TYPE: @@ -214,14 +255,14 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,  		offset = PCA957X_OUT;  		break;  	} -	ret = pca953x_write_reg(chip, offset, reg_val); +	ret = pca953x_write_single(chip, offset, reg_val, off);  	if (ret)  		goto exit; -	chip->reg_output = reg_val; +	chip->reg_output[off / BANK_SZ] = reg_val;  	/* then direction */ -	reg_val = chip->reg_direction & ~(1u << off); +	reg_val = chip->reg_direction[off / BANK_SZ] & ~(1u << (off % BANK_SZ));  	switch (chip->chip_type) {  	case PCA953X_TYPE:  		offset = PCA953X_DIRECTION; @@ -230,11 +271,11 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,  		offset = PCA957X_CFG;  		break;  	} -	ret = pca953x_write_reg(chip, offset, reg_val); +	ret = pca953x_write_single(chip, offset, reg_val, off);  	if (ret)  		goto exit; -	chip->reg_direction = reg_val; +	chip->reg_direction[off / BANK_SZ] = reg_val;  	ret = 0;  exit:  	mutex_unlock(&chip->i2c_lock); @@ -258,7 +299,7 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)  		offset = PCA957X_IN;  		break;  	} -	ret = pca953x_read_reg(chip, offset, ®_val); +	ret = pca953x_read_single(chip, offset, ®_val, off);  	mutex_unlock(&chip->i2c_lock);  	if (ret < 0) {  		/* NOTE:  diagnostic already emitted; that's all we should @@ -274,16 +315,18 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)  static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)  {  	struct pca953x_chip *chip; -	u32 reg_val; +	u8 reg_val;  	int ret, offset = 0;  	chip = container_of(gc, struct pca953x_chip, gpio_chip);  	mutex_lock(&chip->i2c_lock);  	if (val) -		reg_val = chip->reg_output | (1u << off); +		reg_val = chip->reg_output[off / BANK_SZ] +			| (1u << (off % BANK_SZ));  	else -		reg_val = chip->reg_output & ~(1u << off); +		reg_val = chip->reg_output[off / BANK_SZ] +			& ~(1u << (off % BANK_SZ));  	switch (chip->chip_type) {  	case PCA953X_TYPE: @@ -293,11 +336,11 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)  		offset = PCA957X_OUT;  		break;  	} -	ret = pca953x_write_reg(chip, offset, reg_val); +	ret = pca953x_write_single(chip, offset, reg_val, off);  	if (ret)  		goto exit; -	chip->reg_output = reg_val; +	chip->reg_output[off / BANK_SZ] = reg_val;  exit:  	mutex_unlock(&chip->i2c_lock);  } @@ -328,21 +371,21 @@ static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off)  	struct pca953x_chip *chip;  	chip = container_of(gc, struct pca953x_chip, gpio_chip); -	return chip->irq_base + off; +	return irq_create_mapping(chip->domain, off);  }  static void pca953x_irq_mask(struct irq_data *d)  {  	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); -	chip->irq_mask &= ~(1 << d->hwirq); +	chip->irq_mask[d->hwirq / BANK_SZ] &= ~(1 << (d->hwirq % BANK_SZ));  }  static void pca953x_irq_unmask(struct irq_data *d)  {  	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); -	chip->irq_mask |= 1 << d->hwirq; +	chip->irq_mask[d->hwirq / BANK_SZ] |= 1 << (d->hwirq % BANK_SZ);  }  static void pca953x_irq_bus_lock(struct irq_data *d) @@ -355,17 +398,20 @@ static void pca953x_irq_bus_lock(struct irq_data *d)  static void pca953x_irq_bus_sync_unlock(struct irq_data *d)  {  	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); -	u32 new_irqs; -	u32 level; +	u8 new_irqs; +	int level, i;  	/* Look for any newly setup interrupt */ -	new_irqs = chip->irq_trig_fall | chip->irq_trig_raise; -	new_irqs &= ~chip->reg_direction; - -	while (new_irqs) { -		level = __ffs(new_irqs); -		pca953x_gpio_direction_input(&chip->gpio_chip, level); -		new_irqs &= ~(1 << level); +	for (i = 0; i < NBANK(chip); i++) { +		new_irqs = chip->irq_trig_fall[i] | chip->irq_trig_raise[i]; +		new_irqs &= ~chip->reg_direction[i]; + +		while (new_irqs) { +			level = __ffs(new_irqs); +			pca953x_gpio_direction_input(&chip->gpio_chip, +							level + (BANK_SZ * i)); +			new_irqs &= ~(1 << level); +		}  	}  	mutex_unlock(&chip->irq_lock); @@ -374,7 +420,8 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)  static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)  {  	struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); -	u32 mask = 1 << d->hwirq; +	int bank_nb = d->hwirq / BANK_SZ; +	u8 mask = 1 << (d->hwirq % BANK_SZ);  	if (!(type & IRQ_TYPE_EDGE_BOTH)) {  		dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", @@ -383,14 +430,14 @@ static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)  	}  	if (type & IRQ_TYPE_EDGE_FALLING) -		chip->irq_trig_fall |= mask; +		chip->irq_trig_fall[bank_nb] |= mask;  	else -		chip->irq_trig_fall &= ~mask; +		chip->irq_trig_fall[bank_nb] &= ~mask;  	if (type & IRQ_TYPE_EDGE_RISING) -		chip->irq_trig_raise |= mask; +		chip->irq_trig_raise[bank_nb] |= mask;  	else -		chip->irq_trig_raise &= ~mask; +		chip->irq_trig_raise[bank_nb] &= ~mask;  	return 0;  } @@ -404,13 +451,13 @@ static struct irq_chip pca953x_irq_chip = {  	.irq_set_type		= pca953x_irq_set_type,  }; -static u32 pca953x_irq_pending(struct pca953x_chip *chip) +static u8 pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending)  { -	u32 cur_stat; -	u32 old_stat; -	u32 pending; -	u32 trigger; -	int ret, offset = 0; +	u8 cur_stat[MAX_BANK]; +	u8 old_stat[MAX_BANK]; +	u8 pendings = 0; +	u8 trigger[MAX_BANK], triggers = 0; +	int ret, i, offset = 0;  	switch (chip->chip_type) {  	case PCA953X_TYPE: @@ -420,60 +467,88 @@ static u32 pca953x_irq_pending(struct pca953x_chip *chip)  		offset = PCA957X_IN;  		break;  	} -	ret = pca953x_read_reg(chip, offset, &cur_stat); +	ret = pca953x_read_regs(chip, offset, cur_stat);  	if (ret)  		return 0;  	/* Remove output pins from the equation */ -	cur_stat &= chip->reg_direction; +	for (i = 0; i < NBANK(chip); i++) +		cur_stat[i] &= chip->reg_direction[i]; + +	memcpy(old_stat, chip->irq_stat, NBANK(chip)); -	old_stat = chip->irq_stat; -	trigger = (cur_stat ^ old_stat) & chip->irq_mask; +	for (i = 0; i < NBANK(chip); i++) { +		trigger[i] = (cur_stat[i] ^ old_stat[i]) & chip->irq_mask[i]; +		triggers += trigger[i]; +	} -	if (!trigger) +	if (!triggers)  		return 0; -	chip->irq_stat = cur_stat; +	memcpy(chip->irq_stat, cur_stat, NBANK(chip)); -	pending = (old_stat & chip->irq_trig_fall) | -		  (cur_stat & chip->irq_trig_raise); -	pending &= trigger; +	for (i = 0; i < NBANK(chip); i++) { +		pending[i] = (old_stat[i] & chip->irq_trig_fall[i]) | +			(cur_stat[i] & chip->irq_trig_raise[i]); +		pending[i] &= trigger[i]; +		pendings += pending[i]; +	} -	return pending; +	return pendings;  }  static irqreturn_t pca953x_irq_handler(int irq, void *devid)  {  	struct pca953x_chip *chip = devid; -	u32 pending; -	u32 level; - -	pending = pca953x_irq_pending(chip); +	u8 pending[MAX_BANK]; +	u8 level; +	int i; -	if (!pending) +	if (!pca953x_irq_pending(chip, pending))  		return IRQ_HANDLED; -	do { -		level = __ffs(pending); -		handle_nested_irq(irq_find_mapping(chip->domain, level)); - -		pending &= ~(1 << level); -	} while (pending); +	for (i = 0; i < NBANK(chip); i++) { +		while (pending[i]) { +			level = __ffs(pending[i]); +			handle_nested_irq(irq_find_mapping(chip->domain, +							level + (BANK_SZ * i))); +			pending[i] &= ~(1 << level); +		} +	}  	return IRQ_HANDLED;  } +static int pca953x_gpio_irq_map(struct irq_domain *d, unsigned int irq, +		       irq_hw_number_t hwirq) +{ +	irq_clear_status_flags(irq, IRQ_NOREQUEST); +	irq_set_chip_data(irq, d->host_data); +	irq_set_chip(irq, &pca953x_irq_chip); +	irq_set_nested_thread(irq, true); +#ifdef CONFIG_ARM +	set_irq_flags(irq, IRQF_VALID); +#else +	irq_set_noprobe(irq); +#endif + +	return 0; +} + +static const struct irq_domain_ops pca953x_irq_simple_ops = { +	.map = pca953x_gpio_irq_map, +	.xlate = irq_domain_xlate_twocell, +}; +  static int pca953x_irq_setup(struct pca953x_chip *chip,  			     const struct i2c_device_id *id,  			     int irq_base)  {  	struct i2c_client *client = chip->client; -	int ret, offset = 0; -	u32 temporary; +	int ret, i, offset = 0;  	if (irq_base != -1  			&& (id->driver_data & PCA_INT)) { -		int lvl;  		switch (chip->chip_type) {  		case PCA953X_TYPE: @@ -483,49 +558,29 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,  			offset = PCA957X_IN;  			break;  		} -		ret = pca953x_read_reg(chip, offset, &temporary); -		chip->irq_stat = temporary; +		ret = pca953x_read_regs(chip, offset, chip->irq_stat);  		if (ret) -			goto out_failed; +			return ret;  		/*  		 * There is no way to know which GPIO line generated the  		 * interrupt.  We have to rely on the previous read for  		 * this purpose.  		 */ -		chip->irq_stat &= chip->reg_direction; +		for (i = 0; i < NBANK(chip); i++) +			chip->irq_stat[i] &= chip->reg_direction[i];  		mutex_init(&chip->irq_lock); -		chip->irq_base = irq_alloc_descs(-1, irq_base, chip->gpio_chip.ngpio, -1); -		if (chip->irq_base < 0) -			goto out_failed; - -		chip->domain = irq_domain_add_legacy(client->dev.of_node, +		chip->domain = irq_domain_add_simple(client->dev.of_node,  						chip->gpio_chip.ngpio, -						chip->irq_base, -						0, -						&irq_domain_simple_ops, +						irq_base, +						&pca953x_irq_simple_ops,  						NULL); -		if (!chip->domain) { -			ret = -ENODEV; -			goto out_irqdesc_free; -		} +		if (!chip->domain) +			return -ENODEV; -		for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) { -			int irq = lvl + chip->irq_base; - -			irq_clear_status_flags(irq, IRQ_NOREQUEST); -			irq_set_chip_data(irq, chip); -			irq_set_chip(irq, &pca953x_irq_chip); -			irq_set_nested_thread(irq, true); -#ifdef CONFIG_ARM -			set_irq_flags(irq, IRQF_VALID); -#else -			irq_set_noprobe(irq); -#endif -		} - -		ret = request_threaded_irq(client->irq, +		ret = devm_request_threaded_irq(&client->dev, +					client->irq,  					   NULL,  					   pca953x_irq_handler,  					   IRQF_TRIGGER_LOW | IRQF_ONESHOT, @@ -533,28 +588,15 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,  		if (ret) {  			dev_err(&client->dev, "failed to request irq %d\n",  				client->irq); -			goto out_irqdesc_free; +			return ret;  		}  		chip->gpio_chip.to_irq = pca953x_gpio_to_irq;  	}  	return 0; - -out_irqdesc_free: -	irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio); -out_failed: -	chip->irq_base = -1; -	return ret;  } -static void pca953x_irq_teardown(struct pca953x_chip *chip) -{ -	if (chip->irq_base != -1) { -		irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio); -		free_irq(chip->client->irq, chip); -	} -}  #else /* CONFIG_GPIO_PCA953X_IRQ */  static int pca953x_irq_setup(struct pca953x_chip *chip,  			     const struct i2c_device_id *id, @@ -567,10 +609,6 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,  	return 0;  } - -static void pca953x_irq_teardown(struct pca953x_chip *chip) -{ -}  #endif  /* @@ -619,18 +657,24 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert)  static int device_pca953x_init(struct pca953x_chip *chip, u32 invert)  {  	int ret; +	u8 val[MAX_BANK]; -	ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output); +	ret = pca953x_read_regs(chip, PCA953X_OUTPUT, chip->reg_output);  	if (ret)  		goto out; -	ret = pca953x_read_reg(chip, PCA953X_DIRECTION, -			       &chip->reg_direction); +	ret = pca953x_read_regs(chip, PCA953X_DIRECTION, +			       chip->reg_direction);  	if (ret)  		goto out;  	/* set platform specific polarity inversion */ -	ret = pca953x_write_reg(chip, PCA953X_INVERT, invert); +	if (invert) +		memset(val, 0xFF, NBANK(chip)); +	else +		memset(val, 0, NBANK(chip)); + +	ret = pca953x_write_regs(chip, PCA953X_INVERT, val);  out:  	return ret;  } @@ -638,28 +682,36 @@ out:  static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)  {  	int ret; -	u32 val = 0; +	u8 val[MAX_BANK];  	/* Let every port in proper state, that could save power */ -	pca953x_write_reg(chip, PCA957X_PUPD, 0x0); -	pca953x_write_reg(chip, PCA957X_CFG, 0xffff); -	pca953x_write_reg(chip, PCA957X_OUT, 0x0); - -	ret = pca953x_read_reg(chip, PCA957X_IN, &val); +	memset(val, 0, NBANK(chip)); +	pca953x_write_regs(chip, PCA957X_PUPD, val); +	memset(val, 0xFF, NBANK(chip)); +	pca953x_write_regs(chip, PCA957X_CFG, val); +	memset(val, 0, NBANK(chip)); +	pca953x_write_regs(chip, PCA957X_OUT, val); + +	ret = pca953x_read_regs(chip, PCA957X_IN, val);  	if (ret)  		goto out; -	ret = pca953x_read_reg(chip, PCA957X_OUT, &chip->reg_output); +	ret = pca953x_read_regs(chip, PCA957X_OUT, chip->reg_output);  	if (ret)  		goto out; -	ret = pca953x_read_reg(chip, PCA957X_CFG, &chip->reg_direction); +	ret = pca953x_read_regs(chip, PCA957X_CFG, chip->reg_direction);  	if (ret)  		goto out;  	/* set platform specific polarity inversion */ -	pca953x_write_reg(chip, PCA957X_INVRT, invert); +	if (invert) +		memset(val, 0xFF, NBANK(chip)); +	else +		memset(val, 0, NBANK(chip)); +	pca953x_write_regs(chip, PCA957X_INVRT, val);  	/* To enable register 6, 7 to controll pull up and pull down */ -	pca953x_write_reg(chip, PCA957X_BKEN, 0x202); +	memset(val, 0x02, NBANK(chip)); +	pca953x_write_regs(chip, PCA957X_BKEN, val);  	return 0;  out: @@ -675,7 +727,8 @@ static int pca953x_probe(struct i2c_client *client,  	int ret;  	u32 invert = 0; -	chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); +	chip = devm_kzalloc(&client->dev, +			sizeof(struct pca953x_chip), GFP_KERNEL);  	if (chip == NULL)  		return -ENOMEM; @@ -710,15 +763,15 @@ static int pca953x_probe(struct i2c_client *client,  	else  		ret = device_pca957x_init(chip, invert);  	if (ret) -		goto out_failed; +		return ret;  	ret = pca953x_irq_setup(chip, id, irq_base);  	if (ret) -		goto out_failed; +		return ret;  	ret = gpiochip_add(&chip->gpio_chip);  	if (ret) -		goto out_failed_irq; +		return ret;  	if (pdata && pdata->setup) {  		ret = pdata->setup(client, chip->gpio_chip.base, @@ -729,12 +782,6 @@ static int pca953x_probe(struct i2c_client *client,  	i2c_set_clientdata(client, chip);  	return 0; - -out_failed_irq: -	pca953x_irq_teardown(chip); -out_failed: -	kfree(chip); -	return ret;  }  static int pca953x_remove(struct i2c_client *client) @@ -760,12 +807,11 @@ static int pca953x_remove(struct i2c_client *client)  		return ret;  	} -	pca953x_irq_teardown(chip); -	kfree(chip);  	return 0;  }  static const struct of_device_id pca953x_dt_ids[] = { +	{ .compatible = "nxp,pca9505", },  	{ .compatible = "nxp,pca9534", },  	{ .compatible = "nxp,pca9535", },  	{ .compatible = "nxp,pca9536", }, diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index c1720de18a4f..b820869ca93c 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -365,7 +365,7 @@ static int __init pl061_gpio_init(void)  {  	return amba_driver_register(&pl061_gpio_driver);  } -subsys_initcall(pl061_gpio_init); +module_init(pl061_gpio_init);  MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");  MODULE_DESCRIPTION("PL061 GPIO driver"); diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 8325f580c0f1..9cc108d2b770 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -642,12 +642,7 @@ static struct platform_driver pxa_gpio_driver = {  		.of_match_table = of_match_ptr(pxa_gpio_dt_ids),  	},  }; - -static int __init pxa_gpio_init(void) -{ -	return platform_driver_register(&pxa_gpio_driver); -} -postcore_initcall(pxa_gpio_init); +module_platform_driver(pxa_gpio_driver);  #ifdef CONFIG_PM  static int pxa_gpio_suspend(void) diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c index 9572aa137e6f..4d330e36da1d 100644 --- a/drivers/gpio/gpio-twl4030.c +++ b/drivers/gpio/gpio-twl4030.c @@ -37,7 +37,6 @@  #include <linux/i2c/twl.h> -  /*   * The GPIO "subchip" supports 18 GPIOs which can be configured as   * inputs or outputs, with pullups or pulldowns on each pin.  Each @@ -49,11 +48,6 @@   * There are also two LED pins used sometimes as output-only GPIOs.   */ - -static struct gpio_chip twl_gpiochip; -static int twl4030_gpio_base; -static int twl4030_gpio_irq_base; -  /* genirq interfaces are not available to modules */  #ifdef MODULE  #define is_module()	true @@ -69,14 +63,24 @@ static int twl4030_gpio_irq_base;  /* Mask for GPIO registers when aggregated into a 32-bit integer */  #define GPIO_32_MASK			0x0003ffff -/* Data structures */ -static DEFINE_MUTEX(gpio_lock); +struct gpio_twl4030_priv { +	struct gpio_chip gpio_chip; +	struct mutex mutex; +	int irq_base; -/* store usage of each GPIO. - each bit represents one GPIO */ -static unsigned int gpio_usage_count; +	/* Bitfields for state caching */ +	unsigned int usage_count; +	unsigned int direction; +	unsigned int out_state; +};  /*----------------------------------------------------------------------*/ +static inline struct gpio_twl4030_priv *to_gpio_twl4030(struct gpio_chip *chip) +{ +	return container_of(chip, struct gpio_twl4030_priv, gpio_chip); +} +  /*   * To configure TWL4030 GPIO module registers   */ @@ -126,7 +130,7 @@ static inline int gpio_twl4030_read(u8 address)  /*----------------------------------------------------------------------*/ -static u8 cached_leden;		/* protected by gpio_lock */ +static u8 cached_leden;  /* The LED lines are open drain outputs ... a FET pulls to GND, so an   * external pullup is needed.  We could also expose the integrated PWM @@ -140,14 +144,12 @@ static void twl4030_led_set_value(int led, int value)  	if (led)  		mask <<= 1; -	mutex_lock(&gpio_lock);  	if (value)  		cached_leden &= ~mask;  	else  		cached_leden |= mask;  	status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden,  				  TWL4030_LED_LEDEN_REG); -	mutex_unlock(&gpio_lock);  }  static int twl4030_set_gpio_direction(int gpio, int is_input) @@ -158,7 +160,6 @@ static int twl4030_set_gpio_direction(int gpio, int is_input)  	u8 base = REG_GPIODATADIR1 + d_bnk;  	int ret = 0; -	mutex_lock(&gpio_lock);  	ret = gpio_twl4030_read(base);  	if (ret >= 0) {  		if (is_input) @@ -168,7 +169,6 @@ static int twl4030_set_gpio_direction(int gpio, int is_input)  		ret = gpio_twl4030_write(base, reg);  	} -	mutex_unlock(&gpio_lock);  	return ret;  } @@ -193,10 +193,6 @@ static int twl4030_get_gpio_datain(int gpio)  	u8 base = 0;  	int ret = 0; -	if (unlikely((gpio >= TWL4030_GPIO_MAX) -		|| !(gpio_usage_count & BIT(gpio)))) -		return -EPERM; -  	base = REG_GPIODATAIN1 + d_bnk;  	ret = gpio_twl4030_read(base);  	if (ret > 0) @@ -209,9 +205,10 @@ static int twl4030_get_gpio_datain(int gpio)  static int twl_request(struct gpio_chip *chip, unsigned offset)  { +	struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip);  	int status = 0; -	mutex_lock(&gpio_lock); +	mutex_lock(&priv->mutex);  	/* Support the two LED outputs as output-only GPIOs. */  	if (offset >= TWL4030_GPIO_MAX) { @@ -252,7 +249,7 @@ static int twl_request(struct gpio_chip *chip, unsigned offset)  	}  	/* on first use, turn GPIO module "on" */ -	if (!gpio_usage_count) { +	if (!priv->usage_count) {  		struct twl4030_gpio_platform_data *pdata;  		u8 value = MASK_GPIO_CTRL_GPIO_ON; @@ -266,79 +263,120 @@ static int twl_request(struct gpio_chip *chip, unsigned offset)  		status = gpio_twl4030_write(REG_GPIO_CTRL, value);  	} +done:  	if (!status) -		gpio_usage_count |= (0x1 << offset); +		priv->usage_count |= BIT(offset); -done: -	mutex_unlock(&gpio_lock); +	mutex_unlock(&priv->mutex);  	return status;  }  static void twl_free(struct gpio_chip *chip, unsigned offset)  { +	struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); + +	mutex_lock(&priv->mutex);  	if (offset >= TWL4030_GPIO_MAX) {  		twl4030_led_set_value(offset - TWL4030_GPIO_MAX, 1); -		return; +		goto out;  	} -	mutex_lock(&gpio_lock); - -	gpio_usage_count &= ~BIT(offset); +	priv->usage_count &= ~BIT(offset);  	/* on last use, switch off GPIO module */ -	if (!gpio_usage_count) +	if (!priv->usage_count)  		gpio_twl4030_write(REG_GPIO_CTRL, 0x0); -	mutex_unlock(&gpio_lock); +out: +	mutex_unlock(&priv->mutex);  }  static int twl_direction_in(struct gpio_chip *chip, unsigned offset)  { -	return (offset < TWL4030_GPIO_MAX) -		? twl4030_set_gpio_direction(offset, 1) -		: -EINVAL; +	struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); +	int ret; + +	mutex_lock(&priv->mutex); +	if (offset < TWL4030_GPIO_MAX) +		ret = twl4030_set_gpio_direction(offset, 1); +	else +		ret = -EINVAL; + +	if (!ret) +		priv->direction &= ~BIT(offset); + +	mutex_unlock(&priv->mutex); + +	return ret;  }  static int twl_get(struct gpio_chip *chip, unsigned offset)  { +	struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); +	int ret;  	int status = 0; -	if (offset < TWL4030_GPIO_MAX) -		status = twl4030_get_gpio_datain(offset); -	else if (offset == TWL4030_GPIO_MAX) -		status = cached_leden & LEDEN_LEDAON; +	mutex_lock(&priv->mutex); +	if (!(priv->usage_count & BIT(offset))) { +		ret = -EPERM; +		goto out; +	} + +	if (priv->direction & BIT(offset)) +		status = priv->out_state & BIT(offset);  	else -		status = cached_leden & LEDEN_LEDBON; -	return (status < 0) ? 0 : status; +		status = twl4030_get_gpio_datain(offset); + +	ret = (status <= 0) ? 0 : 1; +out: +	mutex_unlock(&priv->mutex); +	return ret;  } -static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value) +static void twl_set(struct gpio_chip *chip, unsigned offset, int value)  { -	if (offset < TWL4030_GPIO_MAX) { +	struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); + +	mutex_lock(&priv->mutex); +	if (offset < TWL4030_GPIO_MAX)  		twl4030_set_gpio_dataout(offset, value); -		return twl4030_set_gpio_direction(offset, 0); -	} else { +	else  		twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value); -		return 0; -	} + +	if (value) +		priv->out_state |= BIT(offset); +	else +		priv->out_state &= ~BIT(offset); + +	mutex_unlock(&priv->mutex);  } -static void twl_set(struct gpio_chip *chip, unsigned offset, int value) +static int twl_direction_out(struct gpio_chip *chip, unsigned offset, int value)  { +	struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); + +	mutex_lock(&priv->mutex);  	if (offset < TWL4030_GPIO_MAX)  		twl4030_set_gpio_dataout(offset, value); -	else -		twl4030_led_set_value(offset - TWL4030_GPIO_MAX, value); + +	priv->direction |= BIT(offset); +	mutex_unlock(&priv->mutex); + +	twl_set(chip, offset, value); + +	return 0;  }  static int twl_to_irq(struct gpio_chip *chip, unsigned offset)  { -	return (twl4030_gpio_irq_base && (offset < TWL4030_GPIO_MAX)) -		? (twl4030_gpio_irq_base + offset) +	struct gpio_twl4030_priv *priv = to_gpio_twl4030(chip); + +	return (priv->irq_base && (offset < TWL4030_GPIO_MAX)) +		? (priv->irq_base + offset)  		: -EINVAL;  } -static struct gpio_chip twl_gpiochip = { +static struct gpio_chip template_chip = {  	.label			= "twl4030",  	.owner			= THIS_MODULE,  	.request		= twl_request, @@ -424,8 +462,14 @@ static int gpio_twl4030_probe(struct platform_device *pdev)  {  	struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;  	struct device_node *node = pdev->dev.of_node; +	struct gpio_twl4030_priv *priv;  	int ret, irq_base; +	priv = devm_kzalloc(&pdev->dev, sizeof(struct gpio_twl4030_priv), +			    GFP_KERNEL); +	if (!priv) +		return -ENOMEM; +  	/* maybe setup IRQs */  	if (is_module()) {  		dev_err(&pdev->dev, "can't dispatch IRQs from modules\n"); @@ -445,12 +489,15 @@ static int gpio_twl4030_probe(struct platform_device *pdev)  	if (ret < 0)  		return ret; -	twl4030_gpio_irq_base = irq_base; +	priv->irq_base = irq_base;  no_irqs: -	twl_gpiochip.base = -1; -	twl_gpiochip.ngpio = TWL4030_GPIO_MAX; -	twl_gpiochip.dev = &pdev->dev; +	priv->gpio_chip = template_chip; +	priv->gpio_chip.base = -1; +	priv->gpio_chip.ngpio = TWL4030_GPIO_MAX; +	priv->gpio_chip.dev = &pdev->dev; + +	mutex_init(&priv->mutex);  	if (node)  		pdata = of_gpio_twl4030(&pdev->dev); @@ -481,23 +528,23 @@ no_irqs:  	 * is (still) clear if use_leds is set.  	 */  	if (pdata->use_leds) -		twl_gpiochip.ngpio += 2; +		priv->gpio_chip.ngpio += 2; -	ret = gpiochip_add(&twl_gpiochip); +	ret = gpiochip_add(&priv->gpio_chip);  	if (ret < 0) {  		dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret); -		twl_gpiochip.ngpio = 0; +		priv->gpio_chip.ngpio = 0;  		gpio_twl4030_remove(pdev);  		goto out;  	} -	twl4030_gpio_base = twl_gpiochip.base; +	platform_set_drvdata(pdev, priv);  	if (pdata && pdata->setup) {  		int status; -		status = pdata->setup(&pdev->dev, -				twl4030_gpio_base, TWL4030_GPIO_MAX); +		status = pdata->setup(&pdev->dev, priv->gpio_chip.base, +				      TWL4030_GPIO_MAX);  		if (status)  			dev_dbg(&pdev->dev, "setup --> %d\n", status);  	} @@ -510,18 +557,19 @@ out:  static int gpio_twl4030_remove(struct platform_device *pdev)  {  	struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data; +	struct gpio_twl4030_priv *priv = platform_get_drvdata(pdev);  	int status;  	if (pdata && pdata->teardown) { -		status = pdata->teardown(&pdev->dev, -				twl4030_gpio_base, TWL4030_GPIO_MAX); +		status = pdata->teardown(&pdev->dev, priv->gpio_chip.base, +					 TWL4030_GPIO_MAX);  		if (status) {  			dev_dbg(&pdev->dev, "teardown --> %d\n", status);  			return status;  		}  	} -	status = gpiochip_remove(&twl_gpiochip); +	status = gpiochip_remove(&priv->gpio_chip);  	if (status < 0)  		return status; diff --git a/drivers/gpio/gpio-vt8500.c b/drivers/gpio/gpio-vt8500.c index b53320a16fc8..9a7c434d2947 100644 --- a/drivers/gpio/gpio-vt8500.c +++ b/drivers/gpio/gpio-vt8500.c @@ -73,19 +73,20 @@ struct vt8500_gpio_data {  static struct vt8500_gpio_data vt8500_data = {  	.num_banks	= 7,  	.banks	= { +		VT8500_BANK(NO_REG, 0x3C, 0x5C, 0x7C, 9),  		VT8500_BANK(0x00, 0x20, 0x40, 0x60, 26),  		VT8500_BANK(0x04, 0x24, 0x44, 0x64, 28),  		VT8500_BANK(0x08, 0x28, 0x48, 0x68, 31),  		VT8500_BANK(0x0C, 0x2C, 0x4C, 0x6C, 19),  		VT8500_BANK(0x10, 0x30, 0x50, 0x70, 19),  		VT8500_BANK(0x14, 0x34, 0x54, 0x74, 23), -		VT8500_BANK(NO_REG, 0x3C, 0x5C, 0x7C, 9),  	},  };  static struct vt8500_gpio_data wm8505_data = {  	.num_banks	= 10,  	.banks	= { +		VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22),  		VT8500_BANK(0x40, 0x68, 0x90, 0xB8, 8),  		VT8500_BANK(0x44, 0x6C, 0x94, 0xBC, 32),  		VT8500_BANK(0x48, 0x70, 0x98, 0xC0, 6), @@ -95,7 +96,6 @@ static struct vt8500_gpio_data wm8505_data = {  		VT8500_BANK(0x58, 0x80, 0xA8, 0xD0, 5),  		VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12),  		VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16), -		VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22),  		VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6),  	},  }; diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index cbad6e908d30..a063eb04b6ce 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -15,6 +15,7 @@  #include <linux/export.h>  #include <linux/acpi_gpio.h>  #include <linux/acpi.h> +#include <linux/interrupt.h>  static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)  { @@ -52,3 +53,89 @@ int acpi_get_gpio(char *path, int pin)  	return chip->base + pin;  }  EXPORT_SYMBOL_GPL(acpi_get_gpio); + + +static irqreturn_t acpi_gpio_irq_handler(int irq, void *data) +{ +	acpi_handle handle = data; + +	acpi_evaluate_object(handle, NULL, NULL, NULL); + +	return IRQ_HANDLED; +} + +/** + * acpi_gpiochip_request_interrupts() - Register isr for gpio chip ACPI events + * @chip:      gpio chip + * + * ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are + * handled by ACPI event methods which need to be called from the GPIO + * chip's interrupt handler. acpi_gpiochip_request_interrupts finds out which + * gpio pins have acpi event methods and assigns interrupt handlers that calls + * the acpi event methods for those pins. + * + * Interrupts are automatically freed on driver detach + */ + +void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) +{ +	struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; +	struct acpi_resource *res; +	acpi_handle handle, ev_handle; +	acpi_status status; +	unsigned int pin; +	int irq, ret; +	char ev_name[5]; + +	if (!chip->dev || !chip->to_irq) +		return; + +	handle = ACPI_HANDLE(chip->dev); +	if (!handle) +		return; + +	status = acpi_get_event_resources(handle, &buf); +	if (ACPI_FAILURE(status)) +		return; + +	/* If a gpio interrupt has an acpi event handler method, then +	 * set up an interrupt handler that calls the acpi event handler +	 */ + +	for (res = buf.pointer; +	     res && (res->type != ACPI_RESOURCE_TYPE_END_TAG); +	     res = ACPI_NEXT_RESOURCE(res)) { + +		if (res->type != ACPI_RESOURCE_TYPE_GPIO || +		    res->data.gpio.connection_type != +		    ACPI_RESOURCE_GPIO_TYPE_INT) +			continue; + +		pin = res->data.gpio.pin_table[0]; +		if (pin > chip->ngpio) +			continue; + +		sprintf(ev_name, "_%c%02X", +		res->data.gpio.triggering ? 'E' : 'L', pin); + +		status = acpi_get_handle(handle, ev_name, &ev_handle); +		if (ACPI_FAILURE(status)) +			continue; + +		irq = chip->to_irq(chip, pin); +		if (irq < 0) +			continue; + +		/* Assume BIOS sets the triggering, so no flags */ +		ret = devm_request_threaded_irq(chip->dev, irq, NULL, +					  acpi_gpio_irq_handler, +					  0, +					  "GPIO-signaled-ACPI-event", +					  ev_handle); +		if (ret) +			dev_err(chip->dev, +				"Failed to request IRQ %d ACPI event handler\n", +				irq); +	} +} +EXPORT_SYMBOL(acpi_gpiochip_request_interrupts); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 199fca15f270..e14eb88bbe8d 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -52,14 +52,13 @@ struct gpio_desc {  /* flag symbols are bit numbers */  #define FLAG_REQUESTED	0  #define FLAG_IS_OUT	1 -#define FLAG_RESERVED	2 -#define FLAG_EXPORT	3	/* protected by sysfs_lock */ -#define FLAG_SYSFS	4	/* exported via /sys/class/gpio/control */ -#define FLAG_TRIG_FALL	5	/* trigger on falling edge */ -#define FLAG_TRIG_RISE	6	/* trigger on rising edge */ -#define FLAG_ACTIVE_LOW	7	/* sysfs value has active low */ -#define FLAG_OPEN_DRAIN	8	/* Gpio is open drain type */ -#define FLAG_OPEN_SOURCE 9	/* Gpio is open source type */ +#define FLAG_EXPORT	2	/* protected by sysfs_lock */ +#define FLAG_SYSFS	3	/* exported via /sys/class/gpio/control */ +#define FLAG_TRIG_FALL	4	/* trigger on falling edge */ +#define FLAG_TRIG_RISE	5	/* trigger on rising edge */ +#define FLAG_ACTIVE_LOW	6	/* sysfs value has active low */ +#define FLAG_OPEN_DRAIN	7	/* Gpio is open drain type */ +#define FLAG_OPEN_SOURCE 8	/* Gpio is open source type */  #define ID_SHIFT	16	/* add new flags before this one */ @@ -132,7 +131,7 @@ static int gpiochip_find_base(int ngpio)  		struct gpio_desc *desc = &gpio_desc[i];  		struct gpio_chip *chip = desc->chip; -		if (!chip && !test_bit(FLAG_RESERVED, &desc->flags)) { +		if (!chip) {  			spare++;  			if (spare == ngpio) {  				base = i; @@ -150,47 +149,6 @@ static int gpiochip_find_base(int ngpio)  	return base;  } -/** - * gpiochip_reserve() - reserve range of gpios to use with platform code only - * @start: starting gpio number - * @ngpio: number of gpios to reserve - * Context: platform init, potentially before irqs or kmalloc will work - * - * Returns a negative errno if any gpio within the range is already reserved - * or registered, else returns zero as a success code.  Use this function - * to mark a range of gpios as unavailable for dynamic gpio number allocation, - * for example because its driver support is not yet loaded. - */ -int __init gpiochip_reserve(int start, int ngpio) -{ -	int ret = 0; -	unsigned long flags; -	int i; - -	if (!gpio_is_valid(start) || !gpio_is_valid(start + ngpio - 1)) -		return -EINVAL; - -	spin_lock_irqsave(&gpio_lock, flags); - -	for (i = start; i < start + ngpio; i++) { -		struct gpio_desc *desc = &gpio_desc[i]; - -		if (desc->chip || test_bit(FLAG_RESERVED, &desc->flags)) { -			ret = -EBUSY; -			goto err; -		} - -		set_bit(FLAG_RESERVED, &desc->flags); -	} - -	pr_debug("%s: reserved gpios from %d to %d\n", -		 __func__, start, start + ngpio - 1); -err: -	spin_unlock_irqrestore(&gpio_lock, flags); - -	return ret; -} -  /* caller ensures gpio is valid and requested, chip->get_direction may sleep  */  static int gpio_get_direction(unsigned gpio)  { @@ -254,13 +212,14 @@ static ssize_t gpio_direction_show(struct device *dev,  	mutex_lock(&sysfs_lock); -	if (!test_bit(FLAG_EXPORT, &desc->flags)) +	if (!test_bit(FLAG_EXPORT, &desc->flags)) {  		status = -EIO; -	else +	} else {  		gpio_get_direction(gpio);  		status = sprintf(buf, "%s\n",  			test_bit(FLAG_IS_OUT, &desc->flags)  				? "out" : "in"); +	}  	mutex_unlock(&sysfs_lock);  	return status; | 
