diff options
Diffstat (limited to 'arch/arm/mach-imx/avic.c')
-rw-r--r-- | arch/arm/mach-imx/avic.c | 37 |
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 @@ | |||
22 | #include <linux/irqdomain.h> | 22 | #include <linux/irqdomain.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/of.h> | 24 | #include <linux/of.h> |
25 | #include <linux/of_address.h> | ||
25 | #include <asm/mach/irq.h> | 26 | #include <asm/mach/irq.h> |
26 | #include <asm/exception.h> | 27 | #include <asm/exception.h> |
27 | 28 | ||
@@ -51,7 +52,12 @@ | |||
51 | 52 | ||
52 | #define AVIC_NUM_IRQS 64 | 53 | #define AVIC_NUM_IRQS 64 |
53 | 54 | ||
55 | /* low power interrupt mask registers */ | ||
56 | #define MX25_CCM_LPIMR0 0x68 | ||
57 | #define MX25_CCM_LPIMR1 0x6C | ||
58 | |||
54 | static void __iomem *avic_base; | 59 | static void __iomem *avic_base; |
60 | static void __iomem *mx25_ccm_base; | ||
55 | static struct irq_domain *domain; | 61 | static struct irq_domain *domain; |
56 | 62 | ||
57 | #ifdef CONFIG_FIQ | 63 | #ifdef CONFIG_FIQ |
@@ -93,6 +99,18 @@ static void avic_irq_suspend(struct irq_data *d) | |||
93 | 99 | ||
94 | avic_saved_mask_reg[idx] = imx_readl(avic_base + ct->regs.mask); | 100 | avic_saved_mask_reg[idx] = imx_readl(avic_base + ct->regs.mask); |
95 | imx_writel(gc->wake_active, avic_base + ct->regs.mask); | 101 | imx_writel(gc->wake_active, avic_base + ct->regs.mask); |
102 | |||
103 | if (mx25_ccm_base) { | ||
104 | u8 offs = d->hwirq < AVIC_NUM_IRQS / 2 ? | ||
105 | MX25_CCM_LPIMR0 : MX25_CCM_LPIMR1; | ||
106 | /* | ||
107 | * The interrupts which are still enabled will be used as wakeup | ||
108 | * sources. Allow those interrupts in low-power mode. | ||
109 | * The LPIMR registers use 0 to allow an interrupt, the AVIC | ||
110 | * registers use 1. | ||
111 | */ | ||
112 | imx_writel(~gc->wake_active, mx25_ccm_base + offs); | ||
113 | } | ||
96 | } | 114 | } |
97 | 115 | ||
98 | static void avic_irq_resume(struct irq_data *d) | 116 | static void avic_irq_resume(struct irq_data *d) |
@@ -102,6 +120,13 @@ static void avic_irq_resume(struct irq_data *d) | |||
102 | int idx = d->hwirq >> 5; | 120 | int idx = d->hwirq >> 5; |
103 | 121 | ||
104 | imx_writel(avic_saved_mask_reg[idx], avic_base + ct->regs.mask); | 122 | imx_writel(avic_saved_mask_reg[idx], avic_base + ct->regs.mask); |
123 | |||
124 | if (mx25_ccm_base) { | ||
125 | u8 offs = d->hwirq < AVIC_NUM_IRQS / 2 ? | ||
126 | MX25_CCM_LPIMR0 : MX25_CCM_LPIMR1; | ||
127 | |||
128 | imx_writel(0xffffffff, mx25_ccm_base + offs); | ||
129 | } | ||
105 | } | 130 | } |
106 | 131 | ||
107 | #else | 132 | #else |
@@ -158,6 +183,18 @@ void __init mxc_init_irq(void __iomem *irqbase) | |||
158 | 183 | ||
159 | avic_base = irqbase; | 184 | avic_base = irqbase; |
160 | 185 | ||
186 | np = of_find_compatible_node(NULL, NULL, "fsl,imx25-ccm"); | ||
187 | mx25_ccm_base = of_iomap(np, 0); | ||
188 | |||
189 | if (mx25_ccm_base) { | ||
190 | /* | ||
191 | * By default, we mask all interrupts. We set the actual mask | ||
192 | * before we go into low-power mode. | ||
193 | */ | ||
194 | imx_writel(0xffffffff, mx25_ccm_base + MX25_CCM_LPIMR0); | ||
195 | imx_writel(0xffffffff, mx25_ccm_base + MX25_CCM_LPIMR1); | ||
196 | } | ||
197 | |||
161 | /* put the AVIC into the reset value with | 198 | /* put the AVIC into the reset value with |
162 | * all interrupts disabled | 199 | * all interrupts disabled |
163 | */ | 200 | */ |