Skip to content

Commit

Permalink
[ARM] pxa: fix issue of muxed GPIO irq_chip functions touching non-mu…
Browse files Browse the repository at this point in the history
…xed 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>
  • Loading branch information
Eric Miao committed Apr 27, 2009
1 parent 6ae85d6 commit a8f6fae
Showing 1 changed file with 19 additions and 4 deletions.
23 changes: 19 additions & 4 deletions arch/arm/plat-pxa/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -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" : ""),
Expand Down Expand Up @@ -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 = {
Expand Down

0 comments on commit a8f6fae

Please sign in to comment.