summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorXinyu Chen <xinyu.chen@freescale.com>2010-04-08 09:49:22 +0800
committerAlejandro Gonzalez <alex.gonzalez@digi.com>2010-05-25 11:20:21 +0200
commitc7bc95433254c656fba7aaabd789f3ba09149a06 (patch)
tree1ffe4dfc24883564cdc88e49da5305e78ee68f9f /arch
parent2dd7d6980a9f5f622e89183da684a6e150631f08 (diff)
ENGR00121291 System can not suspend after RTC alarm wakeup
The set irq type routing of GPIO irqchip did not set the correct handler when user want to set it's trigger mode to level. The PMIC irq request as level trigger, but actually, handle_edge_irq is set. PMIC irq handler disables the irq, and re-enable it after all event callbacks complete in thread. Therefore edge irq handle can not handle this pending irq case correctly, left the IRQ_PENDING flag always on. This made the kernel refuse to enter suspend mode. Signed-off-by: Xinyu Chen <xinyu.chen@freescale.com> Signed-off-by: Alejandro Gonzalez <alex.gonzalez@digi.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/plat-mxc/gpio.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
index a4ff5d768484..0ad808ed9c7b 100644
--- a/arch/arm/plat-mxc/gpio.c
+++ b/arch/arm/plat-mxc/gpio.c
@@ -3,7 +3,7 @@
* Copyright 2008 Juergen Beisert, kernel@pengutronix.de
*
* Based on code from Freescale,
- * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -123,6 +123,12 @@ static int gpio_set_irq_type(u32 irq, u32 type)
return -EINVAL;
}
+ /* set the correct irq handler */
+ if (type & IRQ_TYPE_EDGE_BOTH)
+ set_irq_handler(irq, handle_edge_irq);
+ else if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+ set_irq_handler(irq, handle_level_irq);
+
reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
bit = gpio & 0xf;
val = __raw_readl(reg) & ~(0x3 << (bit << 1));
@@ -418,7 +424,7 @@ int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt)
for (j = port[i].virtual_irq_start;
j < port[i].virtual_irq_start + 32; j++) {
set_irq_chip(j, &gpio_irq_chip);
- set_irq_handler(j, handle_edge_irq);
+ set_irq_handler(j, handle_level_irq);
set_irq_flags(j, IRQF_VALID);
}