Commit 8598066cddd186809c4edf5aae5f018c00079e8c

Authored by Felipe Balbi
Committed by Tony Lindgren
1 parent eaacabc0d9

arm: omap: irq: move irq.c to drivers/irqchip/

Just move the code over as it has no dependencies
on arch/arm/ anymore.

Signed-off-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>

Showing 6 changed files with 402 additions and 395 deletions Side-by-side Diff

arch/arm/mach-omap2/Kconfig
... ... @@ -86,6 +86,7 @@
86 86 select PINCTRL
87 87 select SOC_BUS
88 88 select TI_PRIV_EDMA
  89 + select OMAP_IRQCHIP
89 90 help
90 91 Systems based on OMAP2, OMAP3, OMAP4 or OMAP5
91 92  
arch/arm/mach-omap2/Makefile
... ... @@ -10,7 +10,6 @@
10 10 common.o gpio.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o \
11 11 omap_device.o sram.o drm.o
12 12  
13   -omap-2-3-common = irq.o
14 13 hwmod-common = omap_hwmod.o omap_hwmod_reset.o \
15 14 omap_hwmod_common_data.o
16 15 clock-common = clock.o clock_common_data.o \
... ... @@ -20,7 +19,7 @@
20 19 obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
21 20 obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common) $(secure-common)
22 21 obj-$(CONFIG_ARCH_OMAP4) += $(hwmod-common) $(secure-common)
23   -obj-$(CONFIG_SOC_AM33XX) += irq.o $(hwmod-common)
  22 +obj-$(CONFIG_SOC_AM33XX) += $(hwmod-common)
24 23 obj-$(CONFIG_SOC_OMAP5) += $(hwmod-common) $(secure-common)
25 24 obj-$(CONFIG_SOC_AM43XX) += $(hwmod-common) $(secure-common)
26 25 obj-$(CONFIG_SOC_DRA7XX) += $(hwmod-common) $(secure-common)
arch/arm/mach-omap2/irq.c
1   -/*
2   - * linux/arch/arm/mach-omap2/irq.c
3   - *
4   - * Interrupt handler for OMAP2 boards.
5   - *
6   - * Copyright (C) 2005 Nokia Corporation
7   - * Author: Paul Mundt <paul.mundt@nokia.com>
8   - *
9   - * This file is subject to the terms and conditions of the GNU General Public
10   - * License. See the file "COPYING" in the main directory of this archive
11   - * for more details.
12   - */
13   -#include <linux/kernel.h>
14   -#include <linux/module.h>
15   -#include <linux/init.h>
16   -#include <linux/interrupt.h>
17   -#include <linux/io.h>
18   -
19   -#include <asm/exception.h>
20   -#include <asm/mach/irq.h>
21   -#include <linux/irqdomain.h>
22   -#include <linux/of.h>
23   -#include <linux/of_address.h>
24   -#include <linux/of_irq.h>
25   -
26   -#include "soc.h"
27   -#include "common.h"
28   -#include "../../drivers/irqchip/irqchip.h"
29   -
30   -/* selected INTC register offsets */
31   -
32   -#define INTC_REVISION 0x0000
33   -#define INTC_SYSCONFIG 0x0010
34   -#define INTC_SYSSTATUS 0x0014
35   -#define INTC_SIR 0x0040
36   -#define INTC_CONTROL 0x0048
37   -#define INTC_PROTECTION 0x004C
38   -#define INTC_IDLE 0x0050
39   -#define INTC_THRESHOLD 0x0068
40   -#define INTC_MIR0 0x0084
41   -#define INTC_MIR_CLEAR0 0x0088
42   -#define INTC_MIR_SET0 0x008c
43   -#define INTC_PENDING_IRQ0 0x0098
44   -#define INTC_PENDING_IRQ1 0x00b8
45   -#define INTC_PENDING_IRQ2 0x00d8
46   -#define INTC_PENDING_IRQ3 0x00f8
47   -#define INTC_ILR0 0x0100
48   -
49   -#define ACTIVEIRQ_MASK 0x7f /* omap2/3 active interrupt bits */
50   -#define INTCPS_NR_ILR_REGS 128
51   -#define INTCPS_NR_MIR_REGS 3
52   -
53   -/*
54   - * OMAP2 has a number of different interrupt controllers, each interrupt
55   - * controller is identified as its own "bank". Register definitions are
56   - * fairly consistent for each bank, but not all registers are implemented
57   - * for each bank.. when in doubt, consult the TRM.
58   - */
59   -
60   -/* Structure to save interrupt controller context */
61   -struct omap_intc_regs {
62   - u32 sysconfig;
63   - u32 protection;
64   - u32 idle;
65   - u32 threshold;
66   - u32 ilr[INTCPS_NR_ILR_REGS];
67   - u32 mir[INTCPS_NR_MIR_REGS];
68   -};
69   -static struct omap_intc_regs intc_context;
70   -
71   -static struct irq_domain *domain;
72   -static void __iomem *omap_irq_base;
73   -static int omap_nr_pending = 3;
74   -static int omap_nr_irqs = 96;
75   -
76   -/* INTC bank register get/set */
77   -static void intc_writel(u32 reg, u32 val)
78   -{
79   - writel_relaxed(val, omap_irq_base + reg);
80   -}
81   -
82   -static u32 intc_readl(u32 reg)
83   -{
84   - return readl_relaxed(omap_irq_base + reg);
85   -}
86   -
87   -void omap_intc_save_context(void)
88   -{
89   - int i;
90   -
91   - intc_context.sysconfig =
92   - intc_readl(INTC_SYSCONFIG);
93   - intc_context.protection =
94   - intc_readl(INTC_PROTECTION);
95   - intc_context.idle =
96   - intc_readl(INTC_IDLE);
97   - intc_context.threshold =
98   - intc_readl(INTC_THRESHOLD);
99   -
100   - for (i = 0; i < omap_nr_irqs; i++)
101   - intc_context.ilr[i] =
102   - intc_readl((INTC_ILR0 + 0x4 * i));
103   - for (i = 0; i < INTCPS_NR_MIR_REGS; i++)
104   - intc_context.mir[i] =
105   - intc_readl(INTC_MIR0 + (0x20 * i));
106   -}
107   -
108   -void omap_intc_restore_context(void)
109   -{
110   - int i;
111   -
112   - intc_writel(INTC_SYSCONFIG, intc_context.sysconfig);
113   - intc_writel(INTC_PROTECTION, intc_context.protection);
114   - intc_writel(INTC_IDLE, intc_context.idle);
115   - intc_writel(INTC_THRESHOLD, intc_context.threshold);
116   -
117   - for (i = 0; i < omap_nr_irqs; i++)
118   - intc_writel(INTC_ILR0 + 0x4 * i,
119   - intc_context.ilr[i]);
120   -
121   - for (i = 0; i < INTCPS_NR_MIR_REGS; i++)
122   - intc_writel(INTC_MIR0 + 0x20 * i,
123   - intc_context.mir[i]);
124   - /* MIRs are saved and restore with other PRCM registers */
125   -}
126   -
127   -void omap3_intc_prepare_idle(void)
128   -{
129   - /*
130   - * Disable autoidle as it can stall interrupt controller,
131   - * cf. errata ID i540 for 3430 (all revisions up to 3.1.x)
132   - */
133   - intc_writel(INTC_SYSCONFIG, 0);
134   -}
135   -
136   -void omap3_intc_resume_idle(void)
137   -{
138   - /* Re-enable autoidle */
139   - intc_writel(INTC_SYSCONFIG, 1);
140   -}
141   -
142   -/* XXX: FIQ and additional INTC support (only MPU at the moment) */
143   -static void omap_ack_irq(struct irq_data *d)
144   -{
145   - intc_writel(INTC_CONTROL, 0x1);
146   -}
147   -
148   -static void omap_mask_ack_irq(struct irq_data *d)
149   -{
150   - irq_gc_mask_disable_reg(d);
151   - omap_ack_irq(d);
152   -}
153   -
154   -static void __init omap_irq_soft_reset(void)
155   -{
156   - unsigned long tmp;
157   -
158   - tmp = intc_readl(INTC_REVISION) & 0xff;
159   -
160   - pr_info("IRQ: Found an INTC at 0x%p (revision %ld.%ld) with %d interrupts\n",
161   - omap_irq_base, tmp >> 4, tmp & 0xf, omap_nr_irqs);
162   -
163   - tmp = intc_readl(INTC_SYSCONFIG);
164   - tmp |= 1 << 1; /* soft reset */
165   - intc_writel(INTC_SYSCONFIG, tmp);
166   -
167   - while (!(intc_readl(INTC_SYSSTATUS) & 0x1))
168   - /* Wait for reset to complete */;
169   -
170   - /* Enable autoidle */
171   - intc_writel(INTC_SYSCONFIG, 1 << 0);
172   -}
173   -
174   -int omap_irq_pending(void)
175   -{
176   - int irq;
177   -
178   - for (irq = 0; irq < omap_nr_irqs; irq += 32)
179   - if (intc_readl(INTC_PENDING_IRQ0 +
180   - ((irq >> 5) << 5)))
181   - return 1;
182   - return 0;
183   -}
184   -
185   -void omap3_intc_suspend(void)
186   -{
187   - /* A pending interrupt would prevent OMAP from entering suspend */
188   - omap_ack_irq(NULL);
189   -}
190   -
191   -static int __init omap_alloc_gc_of(struct irq_domain *d, void __iomem *base)
192   -{
193   - int ret;
194   - int i;
195   -
196   - ret = irq_alloc_domain_generic_chips(d, 32, 1, "INTC",
197   - handle_level_irq, IRQ_NOREQUEST | IRQ_NOPROBE,
198   - IRQ_LEVEL, 0);
199   - if (ret) {
200   - pr_warn("Failed to allocate irq chips\n");
201   - return ret;
202   - }
203   -
204   - for (i = 0; i < omap_nr_pending; i++) {
205   - struct irq_chip_generic *gc;
206   - struct irq_chip_type *ct;
207   -
208   - gc = irq_get_domain_generic_chip(d, 32 * i);
209   - gc->reg_base = base;
210   - ct = gc->chip_types;
211   -
212   - ct->type = IRQ_TYPE_LEVEL_MASK;
213   - ct->handler = handle_level_irq;
214   -
215   - ct->chip.irq_ack = omap_mask_ack_irq;
216   - ct->chip.irq_mask = irq_gc_mask_disable_reg;
217   - ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
218   -
219   - ct->chip.flags |= IRQCHIP_SKIP_SET_WAKE;
220   -
221   - ct->regs.enable = INTC_MIR_CLEAR0 + 32 * i;
222   - ct->regs.disable = INTC_MIR_SET0 + 32 * i;
223   - }
224   -
225   - return 0;
226   -}
227   -
228   -static void __init omap_alloc_gc_legacy(void __iomem *base,
229   - unsigned int irq_start, unsigned int num)
230   -{
231   - struct irq_chip_generic *gc;
232   - struct irq_chip_type *ct;
233   -
234   - gc = irq_alloc_generic_chip("INTC", 1, irq_start, base,
235   - handle_level_irq);
236   - ct = gc->chip_types;
237   - ct->chip.irq_ack = omap_mask_ack_irq;
238   - ct->chip.irq_mask = irq_gc_mask_disable_reg;
239   - ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
240   - ct->chip.flags |= IRQCHIP_SKIP_SET_WAKE;
241   -
242   - ct->regs.enable = INTC_MIR_CLEAR0;
243   - ct->regs.disable = INTC_MIR_SET0;
244   - irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
245   - IRQ_NOREQUEST | IRQ_NOPROBE, 0);
246   -}
247   -
248   -static int __init omap_init_irq_of(struct device_node *node)
249   -{
250   - int ret;
251   -
252   - omap_irq_base = of_iomap(node, 0);
253   - if (WARN_ON(!omap_irq_base))
254   - return -ENOMEM;
255   -
256   - domain = irq_domain_add_linear(node, omap_nr_irqs,
257   - &irq_generic_chip_ops, NULL);
258   -
259   - omap_irq_soft_reset();
260   -
261   - ret = omap_alloc_gc_of(domain, omap_irq_base);
262   - if (ret < 0)
263   - irq_domain_remove(domain);
264   -
265   - return ret;
266   -}
267   -
268   -static int __init omap_init_irq_legacy(u32 base)
269   -{
270   - int j, irq_base;
271   -
272   - omap_irq_base = ioremap(base, SZ_4K);
273   - if (WARN_ON(!omap_irq_base))
274   - return -ENOMEM;
275   -
276   - irq_base = irq_alloc_descs(-1, 0, omap_nr_irqs, 0);
277   - if (irq_base < 0) {
278   - pr_warn("Couldn't allocate IRQ numbers\n");
279   - irq_base = 0;
280   - }
281   -
282   - domain = irq_domain_add_legacy(NULL, omap_nr_irqs, irq_base, 0,
283   - &irq_domain_simple_ops, NULL);
284   -
285   - omap_irq_soft_reset();
286   -
287   - for (j = 0; j < omap_nr_irqs; j += 32)
288   - omap_alloc_gc_legacy(omap_irq_base + j, j + irq_base, 32);
289   -
290   - return 0;
291   -}
292   -
293   -static int __init omap_init_irq(u32 base, struct device_node *node)
294   -{
295   - if (node)
296   - return omap_init_irq_of(node);
297   - else
298   - return omap_init_irq_legacy(base);
299   -}
300   -
301   -static asmlinkage void __exception_irq_entry
302   -omap_intc_handle_irq(struct pt_regs *regs)
303   -{
304   - u32 irqnr = 0;
305   - int handled_irq = 0;
306   - int i;
307   -
308   - do {
309   - for (i = 0; i < omap_nr_pending; i++) {
310   - irqnr = intc_readl(INTC_PENDING_IRQ0 + (0x20 * i));
311   - if (irqnr)
312   - goto out;
313   - }
314   -
315   -out:
316   - if (!irqnr)
317   - break;
318   -
319   - irqnr = intc_readl(INTC_SIR);
320   - irqnr &= ACTIVEIRQ_MASK;
321   -
322   - if (irqnr) {
323   - irqnr = irq_find_mapping(domain, irqnr);
324   - handle_IRQ(irqnr, regs);
325   - handled_irq = 1;
326   - }
327   - } while (irqnr);
328   -
329   - /* If an irq is masked or deasserted while active, we will
330   - * keep ending up here with no irq handled. So remove it from
331   - * the INTC with an ack.*/
332   - if (!handled_irq)
333   - omap_ack_irq(NULL);
334   -}
335   -
336   -void __init omap2_init_irq(void)
337   -{
338   - omap_nr_irqs = 96;
339   - omap_nr_pending = 3;
340   - omap_init_irq(OMAP24XX_IC_BASE, NULL);
341   - set_handle_irq(omap_intc_handle_irq);
342   -}
343   -
344   -void __init omap3_init_irq(void)
345   -{
346   - omap_nr_irqs = 96;
347   - omap_nr_pending = 3;
348   - omap_init_irq(OMAP34XX_IC_BASE, NULL);
349   - set_handle_irq(omap_intc_handle_irq);
350   -}
351   -
352   -void __init ti81xx_init_irq(void)
353   -{
354   - omap_nr_irqs = 96;
355   - omap_nr_pending = 4;
356   - omap_init_irq(OMAP34XX_IC_BASE, NULL);
357   - set_handle_irq(omap_intc_handle_irq);
358   -}
359   -
360   -static int __init intc_of_init(struct device_node *node,
361   - struct device_node *parent)
362   -{
363   - struct resource res;
364   - int ret;
365   -
366   - omap_nr_pending = 3;
367   - omap_nr_irqs = 96;
368   -
369   - if (WARN_ON(!node))
370   - return -ENODEV;
371   -
372   - if (of_address_to_resource(node, 0, &res)) {
373   - WARN(1, "unable to get intc registers\n");
374   - return -EINVAL;
375   - }
376   -
377   - if (of_device_is_compatible(node, "ti,am33xx-intc")) {
378   - omap_nr_irqs = 128;
379   - omap_nr_pending = 4;
380   - }
381   -
382   - ret = omap_init_irq(-1, of_node_get(node));
383   - if (ret < 0)
384   - return ret;
385   -
386   - set_handle_irq(omap_intc_handle_irq);
387   -
388   - return 0;
389   -}
390   -
391   -IRQCHIP_DECLARE(omap2_intc, "ti,omap2-intc", intc_of_init);
392   -IRQCHIP_DECLARE(omap3_intc, "ti,omap3-intc", intc_of_init);
393   -IRQCHIP_DECLARE(am33xx_intc, "ti,am33xx-intc", intc_of_init);
drivers/irqchip/Kconfig
... ... @@ -75,6 +75,11 @@
75 75 bool
76 76 select IRQ_DOMAIN
77 77  
  78 +config OMAP_IRQCHIP
  79 + bool
  80 + select GENERIC_IRQ_CHIP
  81 + select IRQ_DOMAIN
  82 +
78 83 config ORION_IRQCHIP
79 84 bool
80 85 select IRQ_DOMAIN
drivers/irqchip/Makefile
... ... @@ -13,6 +13,7 @@
13 13 obj-$(CONFIG_CLPS711X_IRQCHIP) += irq-clps711x.o
14 14 obj-$(CONFIG_OR1K_PIC) += irq-or1k-pic.o
15 15 obj-$(CONFIG_ORION_IRQCHIP) += irq-orion.o
  16 +obj-$(CONFIG_OMAP_IRQCHIP) += irq-omap-intc.o
16 17 obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o
17 18 obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o
18 19 obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o
drivers/irqchip/irq-omap-intc.c
  1 +/*
  2 + * linux/arch/arm/mach-omap2/irq.c
  3 + *
  4 + * Interrupt handler for OMAP2 boards.
  5 + *
  6 + * Copyright (C) 2005 Nokia Corporation
  7 + * Author: Paul Mundt <paul.mundt@nokia.com>
  8 + *
  9 + * This file is subject to the terms and conditions of the GNU General Public
  10 + * License. See the file "COPYING" in the main directory of this archive
  11 + * for more details.
  12 + */
  13 +#include <linux/kernel.h>
  14 +#include <linux/module.h>
  15 +#include <linux/init.h>
  16 +#include <linux/interrupt.h>
  17 +#include <linux/io.h>
  18 +
  19 +#include <asm/exception.h>
  20 +#include <linux/irqdomain.h>
  21 +#include <linux/of.h>
  22 +#include <linux/of_address.h>
  23 +#include <linux/of_irq.h>
  24 +
  25 +#include "irqchip.h"
  26 +
  27 +/* Define these here for now until we drop all board-files */
  28 +#define OMAP24XX_IC_BASE 0x480fe000
  29 +#define OMAP34XX_IC_BASE 0x48200000
  30 +
  31 +/* selected INTC register offsets */
  32 +
  33 +#define INTC_REVISION 0x0000
  34 +#define INTC_SYSCONFIG 0x0010
  35 +#define INTC_SYSSTATUS 0x0014
  36 +#define INTC_SIR 0x0040
  37 +#define INTC_CONTROL 0x0048
  38 +#define INTC_PROTECTION 0x004C
  39 +#define INTC_IDLE 0x0050
  40 +#define INTC_THRESHOLD 0x0068
  41 +#define INTC_MIR0 0x0084
  42 +#define INTC_MIR_CLEAR0 0x0088
  43 +#define INTC_MIR_SET0 0x008c
  44 +#define INTC_PENDING_IRQ0 0x0098
  45 +#define INTC_PENDING_IRQ1 0x00b8
  46 +#define INTC_PENDING_IRQ2 0x00d8
  47 +#define INTC_PENDING_IRQ3 0x00f8
  48 +#define INTC_ILR0 0x0100
  49 +
  50 +#define ACTIVEIRQ_MASK 0x7f /* omap2/3 active interrupt bits */
  51 +#define INTCPS_NR_ILR_REGS 128
  52 +#define INTCPS_NR_MIR_REGS 3
  53 +
  54 +/*
  55 + * OMAP2 has a number of different interrupt controllers, each interrupt
  56 + * controller is identified as its own "bank". Register definitions are
  57 + * fairly consistent for each bank, but not all registers are implemented
  58 + * for each bank.. when in doubt, consult the TRM.
  59 + */
  60 +
  61 +/* Structure to save interrupt controller context */
  62 +struct omap_intc_regs {
  63 + u32 sysconfig;
  64 + u32 protection;
  65 + u32 idle;
  66 + u32 threshold;
  67 + u32 ilr[INTCPS_NR_ILR_REGS];
  68 + u32 mir[INTCPS_NR_MIR_REGS];
  69 +};
  70 +static struct omap_intc_regs intc_context;
  71 +
  72 +static struct irq_domain *domain;
  73 +static void __iomem *omap_irq_base;
  74 +static int omap_nr_pending = 3;
  75 +static int omap_nr_irqs = 96;
  76 +
  77 +/* INTC bank register get/set */
  78 +static void intc_writel(u32 reg, u32 val)
  79 +{
  80 + writel_relaxed(val, omap_irq_base + reg);
  81 +}
  82 +
  83 +static u32 intc_readl(u32 reg)
  84 +{
  85 + return readl_relaxed(omap_irq_base + reg);
  86 +}
  87 +
  88 +void omap_intc_save_context(void)
  89 +{
  90 + int i;
  91 +
  92 + intc_context.sysconfig =
  93 + intc_readl(INTC_SYSCONFIG);
  94 + intc_context.protection =
  95 + intc_readl(INTC_PROTECTION);
  96 + intc_context.idle =
  97 + intc_readl(INTC_IDLE);
  98 + intc_context.threshold =
  99 + intc_readl(INTC_THRESHOLD);
  100 +
  101 + for (i = 0; i < omap_nr_irqs; i++)
  102 + intc_context.ilr[i] =
  103 + intc_readl((INTC_ILR0 + 0x4 * i));
  104 + for (i = 0; i < INTCPS_NR_MIR_REGS; i++)
  105 + intc_context.mir[i] =
  106 + intc_readl(INTC_MIR0 + (0x20 * i));
  107 +}
  108 +
  109 +void omap_intc_restore_context(void)
  110 +{
  111 + int i;
  112 +
  113 + intc_writel(INTC_SYSCONFIG, intc_context.sysconfig);
  114 + intc_writel(INTC_PROTECTION, intc_context.protection);
  115 + intc_writel(INTC_IDLE, intc_context.idle);
  116 + intc_writel(INTC_THRESHOLD, intc_context.threshold);
  117 +
  118 + for (i = 0; i < omap_nr_irqs; i++)
  119 + intc_writel(INTC_ILR0 + 0x4 * i,
  120 + intc_context.ilr[i]);
  121 +
  122 + for (i = 0; i < INTCPS_NR_MIR_REGS; i++)
  123 + intc_writel(INTC_MIR0 + 0x20 * i,
  124 + intc_context.mir[i]);
  125 + /* MIRs are saved and restore with other PRCM registers */
  126 +}
  127 +
  128 +void omap3_intc_prepare_idle(void)
  129 +{
  130 + /*
  131 + * Disable autoidle as it can stall interrupt controller,
  132 + * cf. errata ID i540 for 3430 (all revisions up to 3.1.x)
  133 + */
  134 + intc_writel(INTC_SYSCONFIG, 0);
  135 +}
  136 +
  137 +void omap3_intc_resume_idle(void)
  138 +{
  139 + /* Re-enable autoidle */
  140 + intc_writel(INTC_SYSCONFIG, 1);
  141 +}
  142 +
  143 +/* XXX: FIQ and additional INTC support (only MPU at the moment) */
  144 +static void omap_ack_irq(struct irq_data *d)
  145 +{
  146 + intc_writel(INTC_CONTROL, 0x1);
  147 +}
  148 +
  149 +static void omap_mask_ack_irq(struct irq_data *d)
  150 +{
  151 + irq_gc_mask_disable_reg(d);
  152 + omap_ack_irq(d);
  153 +}
  154 +
  155 +static void __init omap_irq_soft_reset(void)
  156 +{
  157 + unsigned long tmp;
  158 +
  159 + tmp = intc_readl(INTC_REVISION) & 0xff;
  160 +
  161 + pr_info("IRQ: Found an INTC at 0x%p (revision %ld.%ld) with %d interrupts\n",
  162 + omap_irq_base, tmp >> 4, tmp & 0xf, omap_nr_irqs);
  163 +
  164 + tmp = intc_readl(INTC_SYSCONFIG);
  165 + tmp |= 1 << 1; /* soft reset */
  166 + intc_writel(INTC_SYSCONFIG, tmp);
  167 +
  168 + while (!(intc_readl(INTC_SYSSTATUS) & 0x1))
  169 + /* Wait for reset to complete */;
  170 +
  171 + /* Enable autoidle */
  172 + intc_writel(INTC_SYSCONFIG, 1 << 0);
  173 +}
  174 +
  175 +int omap_irq_pending(void)
  176 +{
  177 + int irq;
  178 +
  179 + for (irq = 0; irq < omap_nr_irqs; irq += 32)
  180 + if (intc_readl(INTC_PENDING_IRQ0 +
  181 + ((irq >> 5) << 5)))
  182 + return 1;
  183 + return 0;
  184 +}
  185 +
  186 +void omap3_intc_suspend(void)
  187 +{
  188 + /* A pending interrupt would prevent OMAP from entering suspend */
  189 + omap_ack_irq(NULL);
  190 +}
  191 +
  192 +static int __init omap_alloc_gc_of(struct irq_domain *d, void __iomem *base)
  193 +{
  194 + int ret;
  195 + int i;
  196 +
  197 + ret = irq_alloc_domain_generic_chips(d, 32, 1, "INTC",
  198 + handle_level_irq, IRQ_NOREQUEST | IRQ_NOPROBE,
  199 + IRQ_LEVEL, 0);
  200 + if (ret) {
  201 + pr_warn("Failed to allocate irq chips\n");
  202 + return ret;
  203 + }
  204 +
  205 + for (i = 0; i < omap_nr_pending; i++) {
  206 + struct irq_chip_generic *gc;
  207 + struct irq_chip_type *ct;
  208 +
  209 + gc = irq_get_domain_generic_chip(d, 32 * i);
  210 + gc->reg_base = base;
  211 + ct = gc->chip_types;
  212 +
  213 + ct->type = IRQ_TYPE_LEVEL_MASK;
  214 + ct->handler = handle_level_irq;
  215 +
  216 + ct->chip.irq_ack = omap_mask_ack_irq;
  217 + ct->chip.irq_mask = irq_gc_mask_disable_reg;
  218 + ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
  219 +
  220 + ct->chip.flags |= IRQCHIP_SKIP_SET_WAKE;
  221 +
  222 + ct->regs.enable = INTC_MIR_CLEAR0 + 32 * i;
  223 + ct->regs.disable = INTC_MIR_SET0 + 32 * i;
  224 + }
  225 +
  226 + return 0;
  227 +}
  228 +
  229 +static void __init omap_alloc_gc_legacy(void __iomem *base,
  230 + unsigned int irq_start, unsigned int num)
  231 +{
  232 + struct irq_chip_generic *gc;
  233 + struct irq_chip_type *ct;
  234 +
  235 + gc = irq_alloc_generic_chip("INTC", 1, irq_start, base,
  236 + handle_level_irq);
  237 + ct = gc->chip_types;
  238 + ct->chip.irq_ack = omap_mask_ack_irq;
  239 + ct->chip.irq_mask = irq_gc_mask_disable_reg;
  240 + ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
  241 + ct->chip.flags |= IRQCHIP_SKIP_SET_WAKE;
  242 +
  243 + ct->regs.enable = INTC_MIR_CLEAR0;
  244 + ct->regs.disable = INTC_MIR_SET0;
  245 + irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
  246 + IRQ_NOREQUEST | IRQ_NOPROBE, 0);
  247 +}
  248 +
  249 +static int __init omap_init_irq_of(struct device_node *node)
  250 +{
  251 + int ret;
  252 +
  253 + omap_irq_base = of_iomap(node, 0);
  254 + if (WARN_ON(!omap_irq_base))
  255 + return -ENOMEM;
  256 +
  257 + domain = irq_domain_add_linear(node, omap_nr_irqs,
  258 + &irq_generic_chip_ops, NULL);
  259 +
  260 + omap_irq_soft_reset();
  261 +
  262 + ret = omap_alloc_gc_of(domain, omap_irq_base);
  263 + if (ret < 0)
  264 + irq_domain_remove(domain);
  265 +
  266 + return ret;
  267 +}
  268 +
  269 +static int __init omap_init_irq_legacy(u32 base)
  270 +{
  271 + int j, irq_base;
  272 +
  273 + omap_irq_base = ioremap(base, SZ_4K);
  274 + if (WARN_ON(!omap_irq_base))
  275 + return -ENOMEM;
  276 +
  277 + irq_base = irq_alloc_descs(-1, 0, omap_nr_irqs, 0);
  278 + if (irq_base < 0) {
  279 + pr_warn("Couldn't allocate IRQ numbers\n");
  280 + irq_base = 0;
  281 + }
  282 +
  283 + domain = irq_domain_add_legacy(NULL, omap_nr_irqs, irq_base, 0,
  284 + &irq_domain_simple_ops, NULL);
  285 +
  286 + omap_irq_soft_reset();
  287 +
  288 + for (j = 0; j < omap_nr_irqs; j += 32)
  289 + omap_alloc_gc_legacy(omap_irq_base + j, j + irq_base, 32);
  290 +
  291 + return 0;
  292 +}
  293 +
  294 +static int __init omap_init_irq(u32 base, struct device_node *node)
  295 +{
  296 + if (node)
  297 + return omap_init_irq_of(node);
  298 + else
  299 + return omap_init_irq_legacy(base);
  300 +}
  301 +
  302 +static asmlinkage void __exception_irq_entry
  303 +omap_intc_handle_irq(struct pt_regs *regs)
  304 +{
  305 + u32 irqnr = 0;
  306 + int handled_irq = 0;
  307 + int i;
  308 +
  309 + do {
  310 + for (i = 0; i < omap_nr_pending; i++) {
  311 + irqnr = intc_readl(INTC_PENDING_IRQ0 + (0x20 * i));
  312 + if (irqnr)
  313 + goto out;
  314 + }
  315 +
  316 +out:
  317 + if (!irqnr)
  318 + break;
  319 +
  320 + irqnr = intc_readl(INTC_SIR);
  321 + irqnr &= ACTIVEIRQ_MASK;
  322 +
  323 + if (irqnr) {
  324 + irqnr = irq_find_mapping(domain, irqnr);
  325 + handle_IRQ(irqnr, regs);
  326 + handled_irq = 1;
  327 + }
  328 + } while (irqnr);
  329 +
  330 + /* If an irq is masked or deasserted while active, we will
  331 + * keep ending up here with no irq handled. So remove it from
  332 + * the INTC with an ack.*/
  333 + if (!handled_irq)
  334 + omap_ack_irq(NULL);
  335 +}
  336 +
  337 +void __init omap2_init_irq(void)
  338 +{
  339 + omap_nr_irqs = 96;
  340 + omap_nr_pending = 3;
  341 + omap_init_irq(OMAP24XX_IC_BASE, NULL);
  342 + set_handle_irq(omap_intc_handle_irq);
  343 +}
  344 +
  345 +void __init omap3_init_irq(void)
  346 +{
  347 + omap_nr_irqs = 96;
  348 + omap_nr_pending = 3;
  349 + omap_init_irq(OMAP34XX_IC_BASE, NULL);
  350 + set_handle_irq(omap_intc_handle_irq);
  351 +}
  352 +
  353 +void __init ti81xx_init_irq(void)
  354 +{
  355 + omap_nr_irqs = 96;
  356 + omap_nr_pending = 4;
  357 + omap_init_irq(OMAP34XX_IC_BASE, NULL);
  358 + set_handle_irq(omap_intc_handle_irq);
  359 +}
  360 +
  361 +static int __init intc_of_init(struct device_node *node,
  362 + struct device_node *parent)
  363 +{
  364 + struct resource res;
  365 + int ret;
  366 +
  367 + omap_nr_pending = 3;
  368 + omap_nr_irqs = 96;
  369 +
  370 + if (WARN_ON(!node))
  371 + return -ENODEV;
  372 +
  373 + if (of_address_to_resource(node, 0, &res)) {
  374 + WARN(1, "unable to get intc registers\n");
  375 + return -EINVAL;
  376 + }
  377 +
  378 + if (of_device_is_compatible(node, "ti,am33xx-intc")) {
  379 + omap_nr_irqs = 128;
  380 + omap_nr_pending = 4;
  381 + }
  382 +
  383 + ret = omap_init_irq(-1, of_node_get(node));
  384 + if (ret < 0)
  385 + return ret;
  386 +
  387 + set_handle_irq(omap_intc_handle_irq);
  388 +
  389 + return 0;
  390 +}
  391 +
  392 +IRQCHIP_DECLARE(omap2_intc, "ti,omap2-intc", intc_of_init);
  393 +IRQCHIP_DECLARE(omap3_intc, "ti,omap3-intc", intc_of_init);
  394 +IRQCHIP_DECLARE(am33xx_intc, "ti,am33xx-intc", intc_of_init);