aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-imx/avic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-imx/avic.c')
-rw-r--r--arch/arm/mach-imx/avic.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/avic.c b/arch/arm/mach-imx/avic.c
index 1afccae0420c..c0434a36687a 100644
--- a/arch/arm/mach-imx/avic.c
+++ b/arch/arm/mach-imx/avic.c
@@ -22,6 +22,7 @@
#include <linux/irqdomain.h>
#include <linux/io.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <asm/mach/irq.h>
#include <asm/exception.h>
@@ -51,7 +52,12 @@
#define AVIC_NUM_IRQS 64
+/* low power interrupt mask registers */
+#define MX25_CCM_LPIMR0 0x68
+#define MX25_CCM_LPIMR1 0x6C
+
static void __iomem *avic_base;
+static void __iomem *mx25_ccm_base;
static struct irq_domain *domain;
#ifdef CONFIG_FIQ
@@ -93,6 +99,18 @@ static void avic_irq_suspend(struct irq_data *d)
avic_saved_mask_reg[idx] = imx_readl(avic_base + ct->regs.mask);
imx_writel(gc->wake_active, avic_base + ct->regs.mask);
+
+ if (mx25_ccm_base) {
+ u8 offs = d->hwirq < AVIC_NUM_IRQS / 2 ?
+ MX25_CCM_LPIMR0 : MX25_CCM_LPIMR1;
+ /*
+ * The interrupts which are still enabled will be used as wakeup
+ * sources. Allow those interrupts in low-power mode.
+ * The LPIMR registers use 0 to allow an interrupt, the AVIC
+ * registers use 1.
+ */
+ imx_writel(~gc->wake_active, mx25_ccm_base + offs);
+ }
}
static void avic_irq_resume(struct irq_data *d)
@@ -102,6 +120,13 @@ static void avic_irq_resume(struct irq_data *d)
int idx = d->hwirq >> 5;
imx_writel(avic_saved_mask_reg[idx], avic_base + ct->regs.mask);
+
+ if (mx25_ccm_base) {
+ u8 offs = d->hwirq < AVIC_NUM_IRQS / 2 ?
+ MX25_CCM_LPIMR0 : MX25_CCM_LPIMR1;
+
+ imx_writel(0xffffffff, mx25_ccm_base + offs);
+ }
}
#else
@@ -158,6 +183,18 @@ void __init mxc_init_irq(void __iomem *irqbase)
avic_base = irqbase;
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx25-ccm");
+ mx25_ccm_base = of_iomap(np, 0);
+
+ if (mx25_ccm_base) {
+ /*
+ * By default, we mask all interrupts. We set the actual mask
+ * before we go into low-power mode.
+ */
+ imx_writel(0xffffffff, mx25_ccm_base + MX25_CCM_LPIMR0);
+ imx_writel(0xffffffff, mx25_ccm_base + MX25_CCM_LPIMR1);
+ }
+
/* put the AVIC into the reset value with
* all interrupts disabled
*/