diff options
Diffstat (limited to 'arch/arm/mach-ns9xxx/irq.c')
-rw-r--r-- | arch/arm/mach-ns9xxx/irq.c | 74 |
1 files changed, 59 insertions, 15 deletions
diff --git a/arch/arm/mach-ns9xxx/irq.c b/arch/arm/mach-ns9xxx/irq.c index 00001b874e97..36e5835e6097 100644 --- a/arch/arm/mach-ns9xxx/irq.c +++ b/arch/arm/mach-ns9xxx/irq.c | |||
@@ -9,21 +9,27 @@ | |||
9 | * the Free Software Foundation. | 9 | * the Free Software Foundation. |
10 | */ | 10 | */ |
11 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
12 | #include <linux/kernel_stat.h> | ||
12 | #include <asm/io.h> | 13 | #include <asm/io.h> |
13 | #include <asm/mach/irq.h> | 14 | #include <asm/mach/irq.h> |
14 | #include <asm/mach-types.h> | 15 | #include <asm/mach-types.h> |
15 | #include <asm/arch-ns9xxx/regs-sys.h> | 16 | #include <asm/arch-ns9xxx/regs-sys-common.h> |
16 | #include <asm/arch-ns9xxx/irqs.h> | 17 | #include <asm/arch-ns9xxx/irqs.h> |
17 | #include <asm/arch-ns9xxx/board.h> | 18 | #include <asm/arch-ns9xxx/board.h> |
18 | 19 | ||
19 | #include "generic.h" | 20 | #include "generic.h" |
20 | 21 | ||
22 | /* simple interrupt prio table: prio(x) < prio(y) <=> x < y */ | ||
23 | #define irq2prio(i) (i) | ||
24 | #define prio2irq(p) (p) | ||
25 | |||
21 | static void ns9xxx_mask_irq(unsigned int irq) | 26 | static void ns9xxx_mask_irq(unsigned int irq) |
22 | { | 27 | { |
23 | /* XXX: better use cpp symbols */ | 28 | /* XXX: better use cpp symbols */ |
24 | u32 ic = __raw_readl(SYS_IC(irq / 4)); | 29 | int prio = irq2prio(irq); |
25 | ic &= ~(1 << (7 + 8 * (3 - (irq & 3)))); | 30 | u32 ic = __raw_readl(SYS_IC(prio / 4)); |
26 | __raw_writel(ic, SYS_IC(irq / 4)); | 31 | ic &= ~(1 << (7 + 8 * (3 - (prio & 3)))); |
32 | __raw_writel(ic, SYS_IC(prio / 4)); | ||
27 | } | 33 | } |
28 | 34 | ||
29 | static void ns9xxx_ack_irq(unsigned int irq) | 35 | static void ns9xxx_ack_irq(unsigned int irq) |
@@ -40,9 +46,10 @@ static void ns9xxx_maskack_irq(unsigned int irq) | |||
40 | static void ns9xxx_unmask_irq(unsigned int irq) | 46 | static void ns9xxx_unmask_irq(unsigned int irq) |
41 | { | 47 | { |
42 | /* XXX: better use cpp symbols */ | 48 | /* XXX: better use cpp symbols */ |
43 | u32 ic = __raw_readl(SYS_IC(irq / 4)); | 49 | int prio = irq2prio(irq); |
44 | ic |= 1 << (7 + 8 * (3 - (irq & 3))); | 50 | u32 ic = __raw_readl(SYS_IC(prio / 4)); |
45 | __raw_writel(ic, SYS_IC(irq / 4)); | 51 | ic |= 1 << (7 + 8 * (3 - (prio & 3))); |
52 | __raw_writel(ic, SYS_IC(prio / 4)); | ||
46 | } | 53 | } |
47 | 54 | ||
48 | static struct irq_chip ns9xxx_chip = { | 55 | static struct irq_chip ns9xxx_chip = { |
@@ -52,24 +59,61 @@ static struct irq_chip ns9xxx_chip = { | |||
52 | .unmask = ns9xxx_unmask_irq, | 59 | .unmask = ns9xxx_unmask_irq, |
53 | }; | 60 | }; |
54 | 61 | ||
62 | #if 0 | ||
63 | #define handle_irq handle_level_irq | ||
64 | #else | ||
65 | void handle_prio_irq(unsigned int irq, struct irq_desc *desc) | ||
66 | { | ||
67 | unsigned int cpu = smp_processor_id(); | ||
68 | struct irqaction *action; | ||
69 | irqreturn_t action_ret; | ||
70 | |||
71 | spin_lock(&desc->lock); | ||
72 | |||
73 | if (unlikely(desc->status & IRQ_INPROGRESS)) | ||
74 | goto out_unlock; | ||
75 | |||
76 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | ||
77 | kstat_cpu(cpu).irqs[irq]++; | ||
78 | |||
79 | action = desc->action; | ||
80 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) | ||
81 | goto out_unlock; | ||
82 | |||
83 | desc->status |= IRQ_INPROGRESS; | ||
84 | spin_unlock(&desc->lock); | ||
85 | |||
86 | action_ret = handle_IRQ_event(irq, action); | ||
87 | |||
88 | spin_lock(&desc->lock); | ||
89 | desc->status &= ~IRQ_INPROGRESS; | ||
90 | if (!(desc->status & IRQ_DISABLED) && desc->chip->ack) | ||
91 | desc->chip->ack(irq); | ||
92 | |||
93 | out_unlock: | ||
94 | spin_unlock(&desc->lock); | ||
95 | } | ||
96 | #define handle_irq handle_prio_irq | ||
97 | #endif | ||
98 | |||
55 | void __init ns9xxx_init_irq(void) | 99 | void __init ns9xxx_init_irq(void) |
56 | { | 100 | { |
57 | int i; | 101 | int i; |
58 | 102 | ||
59 | /* disable all IRQs */ | 103 | /* disable all IRQs */ |
60 | for (i = 0; i < 8; ++i) | 104 | for (i = 0; i < 8; ++i) |
61 | __raw_writel((4 * i) << 24 | (4 * i + 1) << 16 | | 105 | __raw_writel(prio2irq(4 * i) << 24 | |
62 | (4 * i + 2) << 8 | (4 * i + 3), SYS_IC(i)); | 106 | prio2irq(4 * i + 1) << 16 | |
107 | prio2irq(4 * i + 2) << 8 | | ||
108 | prio2irq(4 * i + 3), | ||
109 | SYS_IC(i)); | ||
63 | 110 | ||
64 | /* simple interrupt prio table: | ||
65 | * prio(x) < prio(y) <=> x < y | ||
66 | */ | ||
67 | for (i = 0; i < 32; ++i) | 111 | for (i = 0; i < 32; ++i) |
68 | __raw_writel(i, SYS_IVA(i)); | 112 | __raw_writel(prio2irq(i), SYS_IVA(i)); |
69 | 113 | ||
70 | for (i = IRQ_WATCHDOG; i <= IRQ_EXT3; ++i) { | 114 | for (i = 0; i <= 31; ++i) { |
71 | set_irq_chip(i, &ns9xxx_chip); | 115 | set_irq_chip(i, &ns9xxx_chip); |
72 | set_irq_handler(i, handle_level_irq); | 116 | set_irq_handler(i, handle_irq); |
73 | set_irq_flags(i, IRQF_VALID); | 117 | set_irq_flags(i, IRQF_VALID); |
74 | } | 118 | } |
75 | } | 119 | } |