gpio: eic-sprd: Clear interrupt after set the interrupt type
[ Upstream commit 84aef4ed59705585d629e81d633a83b7d416f5fb ]
The raw interrupt status of eic maybe set before the interrupt is enabled,
since the eic interrupt has a latch function, which would trigger the
interrupt event once enabled it from user side. To solve this problem,
interrupts generated before setting the interrupt trigger type are ignored.
Fixes: 25518e024e
("gpio: Add Spreadtrum EIC driver support")
Acked-by: Chunyan Zhang <zhang.lyra@gmail.com>
Signed-off-by: Wenhua Lin <Wenhua.Lin@unisoc.com>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Родитель
fcf44c782c
Коммит
f2d3ae8cf6
|
@ -318,20 +318,27 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
|
|||
switch (flow_type) {
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 1);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IC, 1);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 0);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IC, 1);
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
state = sprd_eic_get(chip, offset);
|
||||
if (state)
|
||||
if (state) {
|
||||
sprd_eic_update(chip, offset,
|
||||
SPRD_EIC_DBNC_IEV, 0);
|
||||
else
|
||||
sprd_eic_update(chip, offset,
|
||||
SPRD_EIC_DBNC_IC, 1);
|
||||
} else {
|
||||
sprd_eic_update(chip, offset,
|
||||
SPRD_EIC_DBNC_IEV, 1);
|
||||
sprd_eic_update(chip, offset,
|
||||
SPRD_EIC_DBNC_IC, 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
|
@ -343,20 +350,27 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
|
|||
switch (flow_type) {
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 0);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTCLR, 1);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 1);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTCLR, 1);
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
state = sprd_eic_get(chip, offset);
|
||||
if (state)
|
||||
if (state) {
|
||||
sprd_eic_update(chip, offset,
|
||||
SPRD_EIC_LATCH_INTPOL, 0);
|
||||
else
|
||||
sprd_eic_update(chip, offset,
|
||||
SPRD_EIC_LATCH_INTCLR, 1);
|
||||
} else {
|
||||
sprd_eic_update(chip, offset,
|
||||
SPRD_EIC_LATCH_INTPOL, 1);
|
||||
sprd_eic_update(chip, offset,
|
||||
SPRD_EIC_LATCH_INTCLR, 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
|
@ -370,29 +384,34 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
|
|||
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 1);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1);
|
||||
irq_set_handler_locked(data, handle_edge_irq);
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 0);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1);
|
||||
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);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1);
|
||||
irq_set_handler_locked(data, handle_edge_irq);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 1);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 1);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1);
|
||||
irq_set_handler_locked(data, handle_level_irq);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 1);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 0);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1);
|
||||
irq_set_handler_locked(data, handle_level_irq);
|
||||
break;
|
||||
default:
|
||||
|
@ -405,29 +424,34 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
|
|||
sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 0);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 1);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1);
|
||||
irq_set_handler_locked(data, handle_edge_irq);
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 0);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 0);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1);
|
||||
irq_set_handler_locked(data, handle_edge_irq);
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 0);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 1);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1);
|
||||
irq_set_handler_locked(data, handle_edge_irq);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 1);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 1);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1);
|
||||
irq_set_handler_locked(data, handle_level_irq);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 1);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 0);
|
||||
sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1);
|
||||
irq_set_handler_locked(data, handle_level_irq);
|
||||
break;
|
||||
default:
|
||||
|
|
Загрузка…
Ссылка в новой задаче