Commit 877ef51d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-v5.0-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio

Pull GPIO fixes from Linus Walleij:
 "Here is a bunch of GPIO fixes for the v5.0 series. I was helped out by
  Bartosz in collecting these fixes, for which I am very grateful, the
  biggest achievement in GPIO right now is work distribution.

  There is one serious core fix (timestamping) and a bunch of driver
  fixes:

   - Fix timestamps on nested IRQs

   - Handle IRQs properly in multiple instances of PCF857x

   - Use the right data register and IRQ type setting in the Spreadtrum
     GPIO driver

   - Let the value argument work properly when setting direction in the
     Altera GPIO driver

   - Mask interrupts properly in the vf610 driver"

* tag 'gpio-v5.0-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio:
  gpio: vf610: Mask all GPIO interrupts
  gpio: altera-a10sr: Set proper output level for direction_output
  gpio: sprd: Fix incorrect irq type setting for the async EIC
  gpio: sprd: Fix the incorrect data register
  gpiolib: fix line event timestamps for nested irqs
  gpio: pcf857x: Fix interrupts on multiple instances
parents 62967898 7ae710f9
...@@ -66,8 +66,10 @@ static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc, ...@@ -66,8 +66,10 @@ static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc,
static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc, static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc,
unsigned int nr, int value) unsigned int nr, int value)
{ {
if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT)) if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT)) {
altr_a10sr_gpio_set(gc, nr, value);
return 0; return 0;
}
return -EINVAL; return -EINVAL;
} }
......
...@@ -180,7 +180,18 @@ static void sprd_eic_free(struct gpio_chip *chip, unsigned int offset) ...@@ -180,7 +180,18 @@ static void sprd_eic_free(struct gpio_chip *chip, unsigned int offset)
static int sprd_eic_get(struct gpio_chip *chip, unsigned int offset) static int sprd_eic_get(struct gpio_chip *chip, unsigned int offset)
{ {
struct sprd_eic *sprd_eic = gpiochip_get_data(chip);
switch (sprd_eic->type) {
case SPRD_EIC_DEBOUNCE:
return sprd_eic_read(chip, offset, SPRD_EIC_DBNC_DATA); return sprd_eic_read(chip, offset, SPRD_EIC_DBNC_DATA);
case SPRD_EIC_ASYNC:
return sprd_eic_read(chip, offset, SPRD_EIC_ASYNC_DATA);
case SPRD_EIC_SYNC:
return sprd_eic_read(chip, offset, SPRD_EIC_SYNC_DATA);
default:
return -ENOTSUPP;
}
} }
static int sprd_eic_direction_input(struct gpio_chip *chip, unsigned int offset) static int sprd_eic_direction_input(struct gpio_chip *chip, unsigned int offset)
...@@ -368,6 +379,7 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type) ...@@ -368,6 +379,7 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
irq_set_handler_locked(data, handle_edge_irq); irq_set_handler_locked(data, handle_edge_irq);
break; break;
case IRQ_TYPE_EDGE_BOTH: case IRQ_TYPE_EDGE_BOTH:
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0);
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 1); sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 1);
irq_set_handler_locked(data, handle_edge_irq); irq_set_handler_locked(data, handle_edge_irq);
break; break;
......
...@@ -84,6 +84,7 @@ MODULE_DEVICE_TABLE(of, pcf857x_of_table); ...@@ -84,6 +84,7 @@ MODULE_DEVICE_TABLE(of, pcf857x_of_table);
*/ */
struct pcf857x { struct pcf857x {
struct gpio_chip chip; struct gpio_chip chip;
struct irq_chip irqchip;
struct i2c_client *client; struct i2c_client *client;
struct mutex lock; /* protect 'out' */ struct mutex lock; /* protect 'out' */
unsigned out; /* software latch */ unsigned out; /* software latch */
...@@ -252,18 +253,6 @@ static void pcf857x_irq_bus_sync_unlock(struct irq_data *data) ...@@ -252,18 +253,6 @@ static void pcf857x_irq_bus_sync_unlock(struct irq_data *data)
mutex_unlock(&gpio->lock); mutex_unlock(&gpio->lock);
} }
static struct irq_chip pcf857x_irq_chip = {
.name = "pcf857x",
.irq_enable = pcf857x_irq_enable,
.irq_disable = pcf857x_irq_disable,
.irq_ack = noop,
.irq_mask = noop,
.irq_unmask = noop,
.irq_set_wake = pcf857x_irq_set_wake,
.irq_bus_lock = pcf857x_irq_bus_lock,
.irq_bus_sync_unlock = pcf857x_irq_bus_sync_unlock,
};
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static int pcf857x_probe(struct i2c_client *client, static int pcf857x_probe(struct i2c_client *client,
...@@ -376,8 +365,17 @@ static int pcf857x_probe(struct i2c_client *client, ...@@ -376,8 +365,17 @@ static int pcf857x_probe(struct i2c_client *client,
/* Enable irqchip if we have an interrupt */ /* Enable irqchip if we have an interrupt */
if (client->irq) { if (client->irq) {
gpio->irqchip.name = "pcf857x",
gpio->irqchip.irq_enable = pcf857x_irq_enable,
gpio->irqchip.irq_disable = pcf857x_irq_disable,
gpio->irqchip.irq_ack = noop,
gpio->irqchip.irq_mask = noop,
gpio->irqchip.irq_unmask = noop,
gpio->irqchip.irq_set_wake = pcf857x_irq_set_wake,
gpio->irqchip.irq_bus_lock = pcf857x_irq_bus_lock,
gpio->irqchip.irq_bus_sync_unlock = pcf857x_irq_bus_sync_unlock,
status = gpiochip_irqchip_add_nested(&gpio->chip, status = gpiochip_irqchip_add_nested(&gpio->chip,
&pcf857x_irq_chip, &gpio->irqchip,
0, handle_level_irq, 0, handle_level_irq,
IRQ_TYPE_NONE); IRQ_TYPE_NONE);
if (status) { if (status) {
...@@ -392,7 +390,7 @@ static int pcf857x_probe(struct i2c_client *client, ...@@ -392,7 +390,7 @@ static int pcf857x_probe(struct i2c_client *client,
if (status) if (status)
goto fail; goto fail;
gpiochip_set_nested_irqchip(&gpio->chip, &pcf857x_irq_chip, gpiochip_set_nested_irqchip(&gpio->chip, &gpio->irqchip,
client->irq); client->irq);
gpio->irq_parent = client->irq; gpio->irq_parent = client->irq;
} }
......
...@@ -253,6 +253,7 @@ static int vf610_gpio_probe(struct platform_device *pdev) ...@@ -253,6 +253,7 @@ static int vf610_gpio_probe(struct platform_device *pdev)
struct vf610_gpio_port *port; struct vf610_gpio_port *port;
struct resource *iores; struct resource *iores;
struct gpio_chip *gc; struct gpio_chip *gc;
int i;
int ret; int ret;
port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL); port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
...@@ -319,6 +320,10 @@ static int vf610_gpio_probe(struct platform_device *pdev) ...@@ -319,6 +320,10 @@ static int vf610_gpio_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
return ret; return ret;
/* Mask all GPIO interrupts */
for (i = 0; i < gc->ngpio; i++)
vf610_gpio_writel(0, port->base + PORT_PCR(i));
/* Clear the interrupt status register for all GPIO's */ /* Clear the interrupt status register for all GPIO's */
vf610_gpio_writel(~0, port->base + PORT_ISFR); vf610_gpio_writel(~0, port->base + PORT_ISFR);
......
...@@ -828,6 +828,13 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p) ...@@ -828,6 +828,13 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p)
/* Do not leak kernel stack to userspace */ /* Do not leak kernel stack to userspace */
memset(&ge, 0, sizeof(ge)); memset(&ge, 0, sizeof(ge));
/*
* We may be running from a nested threaded interrupt in which case
* we didn't get the timestamp from lineevent_irq_handler().
*/
if (!le->timestamp)
ge.timestamp = ktime_get_real_ns();
else
ge.timestamp = le->timestamp; ge.timestamp = le->timestamp;
if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment