diff options
Diffstat (limited to 'arch/openrisc/kernel/irq.c')
-rw-r--r-- | arch/openrisc/kernel/irq.c | 146 |
1 files changed, 13 insertions, 133 deletions
diff --git a/arch/openrisc/kernel/irq.c b/arch/openrisc/kernel/irq.c index 8ec77bc9f1e7..967eb1430203 100644 --- a/arch/openrisc/kernel/irq.c +++ b/arch/openrisc/kernel/irq.c | |||
@@ -16,11 +16,10 @@ | |||
16 | 16 | ||
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/of.h> | ||
20 | #include <linux/ftrace.h> | 19 | #include <linux/ftrace.h> |
21 | #include <linux/irq.h> | 20 | #include <linux/irq.h> |
21 | #include <linux/irqchip.h> | ||
22 | #include <linux/export.h> | 22 | #include <linux/export.h> |
23 | #include <linux/irqdomain.h> | ||
24 | #include <linux/irqflags.h> | 23 | #include <linux/irqflags.h> |
25 | 24 | ||
26 | /* read interrupt enabled status */ | 25 | /* read interrupt enabled status */ |
@@ -37,150 +36,31 @@ void arch_local_irq_restore(unsigned long flags) | |||
37 | } | 36 | } |
38 | EXPORT_SYMBOL(arch_local_irq_restore); | 37 | EXPORT_SYMBOL(arch_local_irq_restore); |
39 | 38 | ||
40 | 39 | void __init init_IRQ(void) | |
41 | /* OR1K PIC implementation */ | ||
42 | |||
43 | /* We're a couple of cycles faster than the generic implementations with | ||
44 | * these 'fast' versions. | ||
45 | */ | ||
46 | |||
47 | static void or1k_pic_mask(struct irq_data *data) | ||
48 | { | ||
49 | mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq)); | ||
50 | } | ||
51 | |||
52 | static void or1k_pic_unmask(struct irq_data *data) | ||
53 | { | ||
54 | mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (1UL << data->hwirq)); | ||
55 | } | ||
56 | |||
57 | static void or1k_pic_ack(struct irq_data *data) | ||
58 | { | ||
59 | /* EDGE-triggered interrupts need to be ack'ed in order to clear | ||
60 | * the latch. | ||
61 | * LEVEL-triggered interrupts do not need to be ack'ed; however, | ||
62 | * ack'ing the interrupt has no ill-effect and is quicker than | ||
63 | * trying to figure out what type it is... | ||
64 | */ | ||
65 | |||
66 | /* The OpenRISC 1000 spec says to write a 1 to the bit to ack the | ||
67 | * interrupt, but the OR1200 does this backwards and requires a 0 | ||
68 | * to be written... | ||
69 | */ | ||
70 | |||
71 | #ifdef CONFIG_OR1K_1200 | ||
72 | /* There are two oddities with the OR1200 PIC implementation: | ||
73 | * i) LEVEL-triggered interrupts are latched and need to be cleared | ||
74 | * ii) the interrupt latch is cleared by writing a 0 to the bit, | ||
75 | * as opposed to a 1 as mandated by the spec | ||
76 | */ | ||
77 | |||
78 | mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq)); | ||
79 | #else | ||
80 | WARN(1, "Interrupt handling possibly broken\n"); | ||
81 | mtspr(SPR_PICSR, (1UL << data->hwirq)); | ||
82 | #endif | ||
83 | } | ||
84 | |||
85 | static void or1k_pic_mask_ack(struct irq_data *data) | ||
86 | { | ||
87 | /* Comments for pic_ack apply here, too */ | ||
88 | |||
89 | #ifdef CONFIG_OR1K_1200 | ||
90 | mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq)); | ||
91 | mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq)); | ||
92 | #else | ||
93 | WARN(1, "Interrupt handling possibly broken\n"); | ||
94 | mtspr(SPR_PICMR, (1UL << data->hwirq)); | ||
95 | mtspr(SPR_PICSR, (1UL << data->hwirq)); | ||
96 | #endif | ||
97 | } | ||
98 | |||
99 | #if 0 | ||
100 | static int or1k_pic_set_type(struct irq_data *data, unsigned int flow_type) | ||
101 | { | ||
102 | /* There's nothing to do in the PIC configuration when changing | ||
103 | * flow type. Level and edge-triggered interrupts are both | ||
104 | * supported, but it's PIC-implementation specific which type | ||
105 | * is handled. */ | ||
106 | |||
107 | return irq_setup_alt_chip(data, flow_type); | ||
108 | } | ||
109 | #endif | ||
110 | |||
111 | static struct irq_chip or1k_dev = { | ||
112 | .name = "or1k-PIC", | ||
113 | .irq_unmask = or1k_pic_unmask, | ||
114 | .irq_mask = or1k_pic_mask, | ||
115 | .irq_ack = or1k_pic_ack, | ||
116 | .irq_mask_ack = or1k_pic_mask_ack, | ||
117 | }; | ||
118 | |||
119 | static struct irq_domain *root_domain; | ||
120 | |||
121 | static inline int pic_get_irq(int first) | ||
122 | { | ||
123 | int hwirq; | ||
124 | |||
125 | hwirq = ffs(mfspr(SPR_PICSR) >> first); | ||
126 | if (!hwirq) | ||
127 | return NO_IRQ; | ||
128 | else | ||
129 | hwirq = hwirq + first -1; | ||
130 | |||
131 | return irq_find_mapping(root_domain, hwirq); | ||
132 | } | ||
133 | |||
134 | |||
135 | static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) | ||
136 | { | 40 | { |
137 | irq_set_chip_and_handler_name(irq, &or1k_dev, | 41 | irqchip_init(); |
138 | handle_level_irq, "level"); | ||
139 | irq_set_status_flags(irq, IRQ_LEVEL | IRQ_NOPROBE); | ||
140 | |||
141 | return 0; | ||
142 | } | 42 | } |
143 | 43 | ||
144 | static const struct irq_domain_ops or1k_irq_domain_ops = { | 44 | static void (*handle_arch_irq)(struct pt_regs *); |
145 | .xlate = irq_domain_xlate_onecell, | ||
146 | .map = or1k_map, | ||
147 | }; | ||
148 | |||
149 | /* | ||
150 | * This sets up the IRQ domain for the PIC built in to the OpenRISC | ||
151 | * 1000 CPU. This is the "root" domain as these are the interrupts | ||
152 | * that directly trigger an exception in the CPU. | ||
153 | */ | ||
154 | static void __init or1k_irq_init(void) | ||
155 | { | ||
156 | struct device_node *intc = NULL; | ||
157 | |||
158 | /* The interrupt controller device node is mandatory */ | ||
159 | intc = of_find_compatible_node(NULL, NULL, "opencores,or1k-pic"); | ||
160 | BUG_ON(!intc); | ||
161 | |||
162 | /* Disable all interrupts until explicitly requested */ | ||
163 | mtspr(SPR_PICMR, (0UL)); | ||
164 | |||
165 | root_domain = irq_domain_add_linear(intc, 32, | ||
166 | &or1k_irq_domain_ops, NULL); | ||
167 | } | ||
168 | 45 | ||
169 | void __init init_IRQ(void) | 46 | void __init set_handle_irq(void (*handle_irq)(struct pt_regs *)) |
170 | { | 47 | { |
171 | or1k_irq_init(); | 48 | handle_arch_irq = handle_irq; |
172 | } | 49 | } |
173 | 50 | ||
174 | void __irq_entry do_IRQ(struct pt_regs *regs) | 51 | void handle_IRQ(unsigned int irq, struct pt_regs *regs) |
175 | { | 52 | { |
176 | int irq = -1; | ||
177 | struct pt_regs *old_regs = set_irq_regs(regs); | 53 | struct pt_regs *old_regs = set_irq_regs(regs); |
178 | 54 | ||
179 | irq_enter(); | 55 | irq_enter(); |
180 | 56 | ||
181 | while ((irq = pic_get_irq(irq + 1)) != NO_IRQ) | 57 | generic_handle_irq(irq); |
182 | generic_handle_irq(irq); | ||
183 | 58 | ||
184 | irq_exit(); | 59 | irq_exit(); |
185 | set_irq_regs(old_regs); | 60 | set_irq_regs(old_regs); |
186 | } | 61 | } |
62 | |||
63 | void __irq_entry do_IRQ(struct pt_regs *regs) | ||
64 | { | ||
65 | handle_arch_irq(regs); | ||
66 | } | ||