GPIO fixes for the v5.0 series:
- 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 -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJcUWhGAAoJEEEQszewGV1z4YkQAITz3B6BAgXLjk0zKvJldjD8 gCt0BL9ZcwCJAinJjlAGT4DVQyZzzwd1jEXCeZli0KDDu8TJPamr3S6BXRJ4YP49 cC/k5kz61N1v1I5u9n6VoYd644BdBgn89JyRZ3SpKFf/zQHN73FhasA3yacQB2PN ZvW/2feGpXEkXNJ4472kbsayz3e8gEnyLB8xH/SPcwLL/gHWOCuTuze6733rv8GN oqqR0Ghxn4cR4gOHcoF10Z9PXMqYRIrltQlOlFQDsioKdfWGJEQWoF9ilVjuZ/fr NuHDa5von0ZGwqsJMs6unUODraQCr6P9UEKVULrrJprcWW+XUyQ7pgM8RjDGfqfJ r8GVn3f30JqsJGvx6fthKx0w4e6aZlHhBkremQELSXtvEcAp3DUCRxA6y+kvht6e QvhTg6SlxpLf0BfwDxmLwnL/Jy7vTXex13DzRN2fntax93dIHLGaydbhQPSN3dXg Mu+hySBY4kOoX175QKorvSfg93xbxpT8mCuaWi8+NsNq2R2I3Vhjoy17O0AZ9vwa 36CtN0BowJG8lD8ociO3F4ivUiqkuT/Gp2GqSy+St0gPbLfdZq4uznpXOTmLWSzJ 2yBKbhYVzCaiTjRY3E2T9pSXs8Yesa89Y5Maq9xhkKAi6vXoujRUfDAyT4YrO2Ji 318DMBIpy+pa2LuX/BnJ =2T7w -----END PGP SIGNATURE----- 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
This commit is contained in:
Коммит
877ef51d53
|
@ -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,
|
||||
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 -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
return sprd_eic_read(chip, offset, SPRD_EIC_DBNC_DATA);
|
||||
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);
|
||||
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)
|
||||
|
@ -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);
|
||||
break;
|
||||
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);
|
||||
irq_set_handler_locked(data, handle_edge_irq);
|
||||
break;
|
||||
|
|
|
@ -84,6 +84,7 @@ MODULE_DEVICE_TABLE(of, pcf857x_of_table);
|
|||
*/
|
||||
struct pcf857x {
|
||||
struct gpio_chip chip;
|
||||
struct irq_chip irqchip;
|
||||
struct i2c_client *client;
|
||||
struct mutex lock; /* protect 'out' */
|
||||
unsigned out; /* software latch */
|
||||
|
@ -252,18 +253,6 @@ static void pcf857x_irq_bus_sync_unlock(struct irq_data *data)
|
|||
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,
|
||||
|
@ -376,8 +365,17 @@ static int pcf857x_probe(struct i2c_client *client,
|
|||
|
||||
/* Enable irqchip if we have an interrupt */
|
||||
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,
|
||||
&pcf857x_irq_chip,
|
||||
&gpio->irqchip,
|
||||
0, handle_level_irq,
|
||||
IRQ_TYPE_NONE);
|
||||
if (status) {
|
||||
|
@ -392,7 +390,7 @@ static int pcf857x_probe(struct i2c_client *client,
|
|||
if (status)
|
||||
goto fail;
|
||||
|
||||
gpiochip_set_nested_irqchip(&gpio->chip, &pcf857x_irq_chip,
|
||||
gpiochip_set_nested_irqchip(&gpio->chip, &gpio->irqchip,
|
||||
client->irq);
|
||||
gpio->irq_parent = client->irq;
|
||||
}
|
||||
|
|
|
@ -253,6 +253,7 @@ static int vf610_gpio_probe(struct platform_device *pdev)
|
|||
struct vf610_gpio_port *port;
|
||||
struct resource *iores;
|
||||
struct gpio_chip *gc;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
|
||||
|
@ -319,6 +320,10 @@ static int vf610_gpio_probe(struct platform_device *pdev)
|
|||
if (ret < 0)
|
||||
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 */
|
||||
vf610_gpio_writel(~0, port->base + PORT_ISFR);
|
||||
|
||||
|
|
|
@ -828,7 +828,14 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p)
|
|||
/* Do not leak kernel stack to userspace */
|
||||
memset(&ge, 0, sizeof(ge));
|
||||
|
||||
ge.timestamp = le->timestamp;
|
||||
/*
|
||||
* 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;
|
||||
|
||||
if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE
|
||||
&& le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче