mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-09 14:43:16 +00:00
[ARM] pxa: fix issue of muxed GPIO irq_chip functions touching non-muxed GPIOs
pxa_gpio_irq_type() and pxa_unmask_muxed_gpio() will touch non-muxed GPIOs (0 and 1 on PXA2xx/PXA3xx) bits in GRERx and GFERx, which is incorrect. Actually, only those bits should get updated if the corresponding bits are set in c->irq_mask as well. Fix this by updating only those relevant bits. Reported-and-tested-by: Daniel Ribeiro <drwyrm@gmail.com> Signed-off-by: Eric Miao <eric.miao@marvell.com>
This commit is contained in:
parent
6ae85d6db4
commit
a8f6faebaf
@ -121,6 +121,8 @@ static int __init pxa_init_gpio_chip(int gpio_end)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(chips, 0, nbanks * sizeof(struct pxa_gpio_chip));
|
||||
|
||||
for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
|
||||
struct gpio_chip *c = &chips[i].chip;
|
||||
|
||||
@ -143,6 +145,21 @@ static int __init pxa_init_gpio_chip(int gpio_end)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Update only those GRERx and GFERx edge detection register bits if those
|
||||
* bits are set in c->irq_mask
|
||||
*/
|
||||
static inline void update_edge_detect(struct pxa_gpio_chip *c)
|
||||
{
|
||||
uint32_t grer, gfer;
|
||||
|
||||
grer = __raw_readl(c->regbase + GRER_OFFSET) & ~c->irq_mask;
|
||||
gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~c->irq_mask;
|
||||
grer |= c->irq_edge_rise & c->irq_mask;
|
||||
gfer |= c->irq_edge_fall & c->irq_mask;
|
||||
__raw_writel(grer, c->regbase + GRER_OFFSET);
|
||||
__raw_writel(gfer, c->regbase + GFER_OFFSET);
|
||||
}
|
||||
|
||||
static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
|
||||
{
|
||||
struct pxa_gpio_chip *c;
|
||||
@ -181,8 +198,7 @@ static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
|
||||
else
|
||||
c->irq_edge_fall &= ~mask;
|
||||
|
||||
__raw_writel(c->irq_edge_rise & c->irq_mask, c->regbase + GRER_OFFSET);
|
||||
__raw_writel(c->irq_edge_fall & c->irq_mask, c->regbase + GFER_OFFSET);
|
||||
update_edge_detect(c);
|
||||
|
||||
pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, irq, gpio,
|
||||
((type & IRQ_TYPE_EDGE_RISING) ? " rising" : ""),
|
||||
@ -244,8 +260,7 @@ static void pxa_unmask_muxed_gpio(unsigned int irq)
|
||||
struct pxa_gpio_chip *c = gpio_to_chip(gpio);
|
||||
|
||||
c->irq_mask |= GPIO_bit(gpio);
|
||||
__raw_writel(c->irq_edge_rise & c->irq_mask, c->regbase + GRER_OFFSET);
|
||||
__raw_writel(c->irq_edge_fall & c->irq_mask, c->regbase + GFER_OFFSET);
|
||||
update_edge_detect(c);
|
||||
}
|
||||
|
||||
static struct irq_chip pxa_muxed_gpio_chip = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user