diff options
Diffstat (limited to 'arch/powerpc/platforms/powermac/pic.c')
-rw-r--r-- | arch/powerpc/platforms/powermac/pic.c | 422 |
1 files changed, 192 insertions, 230 deletions
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index c9b09a9e6050..3d328bc1f7e0 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c | |||
@@ -65,39 +65,36 @@ static u32 level_mask[4]; | |||
65 | 65 | ||
66 | static DEFINE_SPINLOCK(pmac_pic_lock); | 66 | static DEFINE_SPINLOCK(pmac_pic_lock); |
67 | 67 | ||
68 | #define GATWICK_IRQ_POOL_SIZE 10 | ||
69 | static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE]; | ||
70 | |||
71 | #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) | 68 | #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) |
72 | static unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; | 69 | static unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; |
70 | static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; | ||
71 | static int pmac_irq_cascade = -1; | ||
72 | static struct irq_host *pmac_pic_host; | ||
73 | 73 | ||
74 | /* | 74 | static void __pmac_retrigger(unsigned int irq_nr) |
75 | * Mark an irq as "lost". This is only used on the pmac | ||
76 | * since it can lose interrupts (see pmac_set_irq_mask). | ||
77 | * -- Cort | ||
78 | */ | ||
79 | void __set_lost(unsigned long irq_nr, int nokick) | ||
80 | { | 75 | { |
81 | if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) { | 76 | if (irq_nr >= max_real_irqs && pmac_irq_cascade > 0) { |
77 | __set_bit(irq_nr, ppc_lost_interrupts); | ||
78 | irq_nr = pmac_irq_cascade; | ||
79 | mb(); | ||
80 | } | ||
81 | if (!__test_and_set_bit(irq_nr, ppc_lost_interrupts)) { | ||
82 | atomic_inc(&ppc_n_lost_interrupts); | 82 | atomic_inc(&ppc_n_lost_interrupts); |
83 | if (!nokick) | 83 | set_dec(1); |
84 | set_dec(1); | ||
85 | } | 84 | } |
86 | } | 85 | } |
87 | 86 | ||
88 | static void pmac_mask_and_ack_irq(unsigned int irq_nr) | 87 | static void pmac_mask_and_ack_irq(unsigned int virq) |
89 | { | 88 | { |
90 | unsigned long bit = 1UL << (irq_nr & 0x1f); | 89 | unsigned int src = irq_map[virq].hwirq; |
91 | int i = irq_nr >> 5; | 90 | unsigned long bit = 1UL << (virq & 0x1f); |
91 | int i = virq >> 5; | ||
92 | unsigned long flags; | 92 | unsigned long flags; |
93 | 93 | ||
94 | if ((unsigned)irq_nr >= max_irqs) | ||
95 | return; | ||
96 | |||
97 | clear_bit(irq_nr, ppc_cached_irq_mask); | ||
98 | if (test_and_clear_bit(irq_nr, ppc_lost_interrupts)) | ||
99 | atomic_dec(&ppc_n_lost_interrupts); | ||
100 | spin_lock_irqsave(&pmac_pic_lock, flags); | 94 | spin_lock_irqsave(&pmac_pic_lock, flags); |
95 | __clear_bit(src, ppc_cached_irq_mask); | ||
96 | if (__test_and_clear_bit(src, ppc_lost_interrupts)) | ||
97 | atomic_dec(&ppc_n_lost_interrupts); | ||
101 | out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); | 98 | out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); |
102 | out_le32(&pmac_irq_hw[i]->ack, bit); | 99 | out_le32(&pmac_irq_hw[i]->ack, bit); |
103 | do { | 100 | do { |
@@ -109,16 +106,29 @@ static void pmac_mask_and_ack_irq(unsigned int irq_nr) | |||
109 | spin_unlock_irqrestore(&pmac_pic_lock, flags); | 106 | spin_unlock_irqrestore(&pmac_pic_lock, flags); |
110 | } | 107 | } |
111 | 108 | ||
112 | static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost) | 109 | static void pmac_ack_irq(unsigned int virq) |
110 | { | ||
111 | unsigned int src = irq_map[virq].hwirq; | ||
112 | unsigned long bit = 1UL << (src & 0x1f); | ||
113 | int i = src >> 5; | ||
114 | unsigned long flags; | ||
115 | |||
116 | spin_lock_irqsave(&pmac_pic_lock, flags); | ||
117 | if (__test_and_clear_bit(src, ppc_lost_interrupts)) | ||
118 | atomic_dec(&ppc_n_lost_interrupts); | ||
119 | out_le32(&pmac_irq_hw[i]->ack, bit); | ||
120 | (void)in_le32(&pmac_irq_hw[i]->ack); | ||
121 | spin_unlock_irqrestore(&pmac_pic_lock, flags); | ||
122 | } | ||
123 | |||
124 | static void __pmac_set_irq_mask(unsigned int irq_nr, int nokicklost) | ||
113 | { | 125 | { |
114 | unsigned long bit = 1UL << (irq_nr & 0x1f); | 126 | unsigned long bit = 1UL << (irq_nr & 0x1f); |
115 | int i = irq_nr >> 5; | 127 | int i = irq_nr >> 5; |
116 | unsigned long flags; | ||
117 | 128 | ||
118 | if ((unsigned)irq_nr >= max_irqs) | 129 | if ((unsigned)irq_nr >= max_irqs) |
119 | return; | 130 | return; |
120 | 131 | ||
121 | spin_lock_irqsave(&pmac_pic_lock, flags); | ||
122 | /* enable unmasked interrupts */ | 132 | /* enable unmasked interrupts */ |
123 | out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); | 133 | out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); |
124 | 134 | ||
@@ -135,71 +145,78 @@ static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost) | |||
135 | * the bit in the flag register or request another interrupt. | 145 | * the bit in the flag register or request another interrupt. |
136 | */ | 146 | */ |
137 | if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level)) | 147 | if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level)) |
138 | __set_lost((ulong)irq_nr, nokicklost); | 148 | __pmac_retrigger(irq_nr); |
139 | spin_unlock_irqrestore(&pmac_pic_lock, flags); | ||
140 | } | 149 | } |
141 | 150 | ||
142 | /* When an irq gets requested for the first client, if it's an | 151 | /* When an irq gets requested for the first client, if it's an |
143 | * edge interrupt, we clear any previous one on the controller | 152 | * edge interrupt, we clear any previous one on the controller |
144 | */ | 153 | */ |
145 | static unsigned int pmac_startup_irq(unsigned int irq_nr) | 154 | static unsigned int pmac_startup_irq(unsigned int virq) |
146 | { | 155 | { |
147 | unsigned long bit = 1UL << (irq_nr & 0x1f); | 156 | unsigned long flags; |
148 | int i = irq_nr >> 5; | 157 | unsigned int src = irq_map[virq].hwirq; |
158 | unsigned long bit = 1UL << (src & 0x1f); | ||
159 | int i = src >> 5; | ||
149 | 160 | ||
150 | if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0) | 161 | spin_lock_irqsave(&pmac_pic_lock, flags); |
162 | if ((irq_desc[virq].status & IRQ_LEVEL) == 0) | ||
151 | out_le32(&pmac_irq_hw[i]->ack, bit); | 163 | out_le32(&pmac_irq_hw[i]->ack, bit); |
152 | set_bit(irq_nr, ppc_cached_irq_mask); | 164 | __set_bit(src, ppc_cached_irq_mask); |
153 | pmac_set_irq_mask(irq_nr, 0); | 165 | __pmac_set_irq_mask(src, 0); |
166 | spin_unlock_irqrestore(&pmac_pic_lock, flags); | ||
154 | 167 | ||
155 | return 0; | 168 | return 0; |
156 | } | 169 | } |
157 | 170 | ||
158 | static void pmac_mask_irq(unsigned int irq_nr) | 171 | static void pmac_mask_irq(unsigned int virq) |
159 | { | 172 | { |
160 | clear_bit(irq_nr, ppc_cached_irq_mask); | 173 | unsigned long flags; |
161 | pmac_set_irq_mask(irq_nr, 0); | 174 | unsigned int src = irq_map[virq].hwirq; |
162 | mb(); | 175 | |
176 | spin_lock_irqsave(&pmac_pic_lock, flags); | ||
177 | __clear_bit(src, ppc_cached_irq_mask); | ||
178 | __pmac_set_irq_mask(src, 0); | ||
179 | spin_unlock_irqrestore(&pmac_pic_lock, flags); | ||
163 | } | 180 | } |
164 | 181 | ||
165 | static void pmac_unmask_irq(unsigned int irq_nr) | 182 | static void pmac_unmask_irq(unsigned int virq) |
166 | { | 183 | { |
167 | set_bit(irq_nr, ppc_cached_irq_mask); | 184 | unsigned long flags; |
168 | pmac_set_irq_mask(irq_nr, 0); | 185 | unsigned int src = irq_map[virq].hwirq; |
186 | |||
187 | spin_lock_irqsave(&pmac_pic_lock, flags); | ||
188 | __set_bit(src, ppc_cached_irq_mask); | ||
189 | __pmac_set_irq_mask(src, 0); | ||
190 | spin_unlock_irqrestore(&pmac_pic_lock, flags); | ||
169 | } | 191 | } |
170 | 192 | ||
171 | static void pmac_end_irq(unsigned int irq_nr) | 193 | static int pmac_retrigger(unsigned int virq) |
172 | { | 194 | { |
173 | if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)) | 195 | unsigned long flags; |
174 | && irq_desc[irq_nr].action) { | ||
175 | set_bit(irq_nr, ppc_cached_irq_mask); | ||
176 | pmac_set_irq_mask(irq_nr, 1); | ||
177 | } | ||
178 | } | ||
179 | 196 | ||
197 | spin_lock_irqsave(&pmac_pic_lock, flags); | ||
198 | __pmac_retrigger(irq_map[virq].hwirq); | ||
199 | spin_unlock_irqrestore(&pmac_pic_lock, flags); | ||
200 | return 1; | ||
201 | } | ||
180 | 202 | ||
181 | struct hw_interrupt_type pmac_pic = { | 203 | static struct irq_chip pmac_pic = { |
182 | .typename = " PMAC-PIC ", | 204 | .typename = " PMAC-PIC ", |
183 | .startup = pmac_startup_irq, | 205 | .startup = pmac_startup_irq, |
184 | .enable = pmac_unmask_irq, | 206 | .mask = pmac_mask_irq, |
185 | .disable = pmac_mask_irq, | 207 | .ack = pmac_ack_irq, |
186 | .ack = pmac_mask_and_ack_irq, | 208 | .mask_ack = pmac_mask_and_ack_irq, |
187 | .end = pmac_end_irq, | 209 | .unmask = pmac_unmask_irq, |
188 | }; | 210 | .retrigger = pmac_retrigger, |
189 | |||
190 | struct hw_interrupt_type gatwick_pic = { | ||
191 | .typename = " GATWICK ", | ||
192 | .startup = pmac_startup_irq, | ||
193 | .enable = pmac_unmask_irq, | ||
194 | .disable = pmac_mask_irq, | ||
195 | .ack = pmac_mask_and_ack_irq, | ||
196 | .end = pmac_end_irq, | ||
197 | }; | 211 | }; |
198 | 212 | ||
199 | static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs) | 213 | static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs) |
200 | { | 214 | { |
215 | unsigned long flags; | ||
201 | int irq, bits; | 216 | int irq, bits; |
217 | int rc = IRQ_NONE; | ||
202 | 218 | ||
219 | spin_lock_irqsave(&pmac_pic_lock, flags); | ||
203 | for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) { | 220 | for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) { |
204 | int i = irq >> 5; | 221 | int i = irq >> 5; |
205 | bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; | 222 | bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; |
@@ -209,17 +226,20 @@ static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs) | |||
209 | if (bits == 0) | 226 | if (bits == 0) |
210 | continue; | 227 | continue; |
211 | irq += __ilog2(bits); | 228 | irq += __ilog2(bits); |
229 | spin_unlock_irqrestore(&pmac_pic_lock, flags); | ||
212 | __do_IRQ(irq, regs); | 230 | __do_IRQ(irq, regs); |
213 | return IRQ_HANDLED; | 231 | spin_lock_irqsave(&pmac_pic_lock, flags); |
232 | rc = IRQ_HANDLED; | ||
214 | } | 233 | } |
215 | printk("gatwick irq not from gatwick pic\n"); | 234 | spin_unlock_irqrestore(&pmac_pic_lock, flags); |
216 | return IRQ_NONE; | 235 | return rc; |
217 | } | 236 | } |
218 | 237 | ||
219 | static int pmac_get_irq(struct pt_regs *regs) | 238 | static unsigned int pmac_pic_get_irq(struct pt_regs *regs) |
220 | { | 239 | { |
221 | int irq; | 240 | int irq; |
222 | unsigned long bits = 0; | 241 | unsigned long bits = 0; |
242 | unsigned long flags; | ||
223 | 243 | ||
224 | #ifdef CONFIG_SMP | 244 | #ifdef CONFIG_SMP |
225 | void psurge_smp_message_recv(struct pt_regs *); | 245 | void psurge_smp_message_recv(struct pt_regs *); |
@@ -227,9 +247,10 @@ static int pmac_get_irq(struct pt_regs *regs) | |||
227 | /* IPI's are a hack on the powersurge -- Cort */ | 247 | /* IPI's are a hack on the powersurge -- Cort */ |
228 | if ( smp_processor_id() != 0 ) { | 248 | if ( smp_processor_id() != 0 ) { |
229 | psurge_smp_message_recv(regs); | 249 | psurge_smp_message_recv(regs); |
230 | return -2; /* ignore, already handled */ | 250 | return NO_IRQ_IGNORE; /* ignore, already handled */ |
231 | } | 251 | } |
232 | #endif /* CONFIG_SMP */ | 252 | #endif /* CONFIG_SMP */ |
253 | spin_lock_irqsave(&pmac_pic_lock, flags); | ||
233 | for (irq = max_real_irqs; (irq -= 32) >= 0; ) { | 254 | for (irq = max_real_irqs; (irq -= 32) >= 0; ) { |
234 | int i = irq >> 5; | 255 | int i = irq >> 5; |
235 | bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; | 256 | bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; |
@@ -241,133 +262,10 @@ static int pmac_get_irq(struct pt_regs *regs) | |||
241 | irq += __ilog2(bits); | 262 | irq += __ilog2(bits); |
242 | break; | 263 | break; |
243 | } | 264 | } |
244 | 265 | spin_unlock_irqrestore(&pmac_pic_lock, flags); | |
245 | return irq; | 266 | if (unlikely(irq < 0)) |
246 | } | 267 | return NO_IRQ; |
247 | 268 | return irq_linear_revmap(pmac_pic_host, irq); | |
248 | /* This routine will fix some missing interrupt values in the device tree | ||
249 | * on the gatwick mac-io controller used by some PowerBooks | ||
250 | * | ||
251 | * Walking of OF nodes could use a bit more fixing up here, but it's not | ||
252 | * very important as this is all boot time code on static portions of the | ||
253 | * device-tree. | ||
254 | * | ||
255 | * However, the modifications done to "intrs" will have to be removed and | ||
256 | * replaced with proper updates of the "interrupts" properties or | ||
257 | * AAPL,interrupts, yet to be decided, once the dynamic parsing is there. | ||
258 | */ | ||
259 | static void __init pmac_fix_gatwick_interrupts(struct device_node *gw, | ||
260 | int irq_base) | ||
261 | { | ||
262 | struct device_node *node; | ||
263 | int count; | ||
264 | |||
265 | memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool)); | ||
266 | count = 0; | ||
267 | for (node = NULL; (node = of_get_next_child(gw, node)) != NULL;) { | ||
268 | /* Fix SCC */ | ||
269 | if ((strcasecmp(node->name, "escc") == 0) && node->child) { | ||
270 | if (node->child->n_intrs < 3) { | ||
271 | node->child->intrs = &gatwick_int_pool[count]; | ||
272 | count += 3; | ||
273 | } | ||
274 | node->child->n_intrs = 3; | ||
275 | node->child->intrs[0].line = 15+irq_base; | ||
276 | node->child->intrs[1].line = 4+irq_base; | ||
277 | node->child->intrs[2].line = 5+irq_base; | ||
278 | printk(KERN_INFO "irq: fixed SCC on gatwick" | ||
279 | " (%d,%d,%d)\n", | ||
280 | node->child->intrs[0].line, | ||
281 | node->child->intrs[1].line, | ||
282 | node->child->intrs[2].line); | ||
283 | } | ||
284 | /* Fix media-bay & left SWIM */ | ||
285 | if (strcasecmp(node->name, "media-bay") == 0) { | ||
286 | struct device_node* ya_node; | ||
287 | |||
288 | if (node->n_intrs == 0) | ||
289 | node->intrs = &gatwick_int_pool[count++]; | ||
290 | node->n_intrs = 1; | ||
291 | node->intrs[0].line = 29+irq_base; | ||
292 | printk(KERN_INFO "irq: fixed media-bay on gatwick" | ||
293 | " (%d)\n", node->intrs[0].line); | ||
294 | |||
295 | ya_node = node->child; | ||
296 | while(ya_node) { | ||
297 | if (strcasecmp(ya_node->name, "floppy") == 0) { | ||
298 | if (ya_node->n_intrs < 2) { | ||
299 | ya_node->intrs = &gatwick_int_pool[count]; | ||
300 | count += 2; | ||
301 | } | ||
302 | ya_node->n_intrs = 2; | ||
303 | ya_node->intrs[0].line = 19+irq_base; | ||
304 | ya_node->intrs[1].line = 1+irq_base; | ||
305 | printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n", | ||
306 | ya_node->intrs[0].line, ya_node->intrs[1].line); | ||
307 | } | ||
308 | if (strcasecmp(ya_node->name, "ata4") == 0) { | ||
309 | if (ya_node->n_intrs < 2) { | ||
310 | ya_node->intrs = &gatwick_int_pool[count]; | ||
311 | count += 2; | ||
312 | } | ||
313 | ya_node->n_intrs = 2; | ||
314 | ya_node->intrs[0].line = 14+irq_base; | ||
315 | ya_node->intrs[1].line = 3+irq_base; | ||
316 | printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n", | ||
317 | ya_node->intrs[0].line, ya_node->intrs[1].line); | ||
318 | } | ||
319 | ya_node = ya_node->sibling; | ||
320 | } | ||
321 | } | ||
322 | } | ||
323 | if (count > 10) { | ||
324 | printk("WARNING !! Gatwick interrupt pool overflow\n"); | ||
325 | printk(" GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE); | ||
326 | printk(" requested = %d\n", count); | ||
327 | } | ||
328 | } | ||
329 | |||
330 | /* | ||
331 | * The PowerBook 3400/2400/3500 can have a combo ethernet/modem | ||
332 | * card which includes an ohare chip that acts as a second interrupt | ||
333 | * controller. If we find this second ohare, set it up and fix the | ||
334 | * interrupt value in the device tree for the ethernet chip. | ||
335 | */ | ||
336 | static void __init enable_second_ohare(struct device_node *np) | ||
337 | { | ||
338 | unsigned char bus, devfn; | ||
339 | unsigned short cmd; | ||
340 | struct device_node *ether; | ||
341 | |||
342 | /* This code doesn't strictly belong here, it could be part of | ||
343 | * either the PCI initialisation or the feature code. It's kept | ||
344 | * here for historical reasons. | ||
345 | */ | ||
346 | if (pci_device_from_OF_node(np, &bus, &devfn) == 0) { | ||
347 | struct pci_controller* hose = | ||
348 | pci_find_hose_for_OF_device(np); | ||
349 | if (!hose) { | ||
350 | printk(KERN_ERR "Can't find PCI hose for OHare2 !\n"); | ||
351 | return; | ||
352 | } | ||
353 | early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd); | ||
354 | cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; | ||
355 | cmd &= ~PCI_COMMAND_IO; | ||
356 | early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd); | ||
357 | } | ||
358 | |||
359 | /* Fix interrupt for the modem/ethernet combo controller. The number | ||
360 | * in the device tree (27) is bogus (correct for the ethernet-only | ||
361 | * board but not the combo ethernet/modem board). | ||
362 | * The real interrupt is 28 on the second controller -> 28+32 = 60. | ||
363 | */ | ||
364 | ether = of_find_node_by_name(NULL, "pci1011,14"); | ||
365 | if (ether && ether->n_intrs > 0) { | ||
366 | ether->intrs[0].line = 60; | ||
367 | printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n", | ||
368 | ether->intrs[0].line); | ||
369 | } | ||
370 | of_node_put(ether); | ||
371 | } | 269 | } |
372 | 270 | ||
373 | #ifdef CONFIG_XMON | 271 | #ifdef CONFIG_XMON |
@@ -386,17 +284,60 @@ static struct irqaction gatwick_cascade_action = { | |||
386 | .name = "cascade", | 284 | .name = "cascade", |
387 | }; | 285 | }; |
388 | 286 | ||
287 | static int pmac_pic_host_match(struct irq_host *h, struct device_node *node) | ||
288 | { | ||
289 | /* We match all, we don't always have a node anyway */ | ||
290 | return 1; | ||
291 | } | ||
292 | |||
293 | static int pmac_pic_host_map(struct irq_host *h, unsigned int virq, | ||
294 | irq_hw_number_t hw, unsigned int flags) | ||
295 | { | ||
296 | struct irq_desc *desc = get_irq_desc(virq); | ||
297 | int level; | ||
298 | |||
299 | if (hw >= max_irqs) | ||
300 | return -EINVAL; | ||
301 | |||
302 | /* Mark level interrupts, set delayed disable for edge ones and set | ||
303 | * handlers | ||
304 | */ | ||
305 | level = !!(level_mask[hw >> 5] & (1UL << (hw & 0x1f))); | ||
306 | if (level) | ||
307 | desc->status |= IRQ_LEVEL; | ||
308 | else | ||
309 | desc->status |= IRQ_DELAYED_DISABLE; | ||
310 | set_irq_chip_and_handler(virq, &pmac_pic, level ? | ||
311 | handle_level_irq : handle_edge_irq); | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | static int pmac_pic_host_xlate(struct irq_host *h, struct device_node *ct, | ||
316 | u32 *intspec, unsigned int intsize, | ||
317 | irq_hw_number_t *out_hwirq, | ||
318 | unsigned int *out_flags) | ||
319 | |||
320 | { | ||
321 | *out_hwirq = *intspec; | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static struct irq_host_ops pmac_pic_host_ops = { | ||
326 | .match = pmac_pic_host_match, | ||
327 | .map = pmac_pic_host_map, | ||
328 | .xlate = pmac_pic_host_xlate, | ||
329 | }; | ||
330 | |||
389 | static void __init pmac_pic_probe_oldstyle(void) | 331 | static void __init pmac_pic_probe_oldstyle(void) |
390 | { | 332 | { |
391 | int i; | 333 | int i; |
392 | int irq_cascade = -1; | ||
393 | struct device_node *master = NULL; | 334 | struct device_node *master = NULL; |
394 | struct device_node *slave = NULL; | 335 | struct device_node *slave = NULL; |
395 | u8 __iomem *addr; | 336 | u8 __iomem *addr; |
396 | struct resource r; | 337 | struct resource r; |
397 | 338 | ||
398 | /* Set our get_irq function */ | 339 | /* Set our get_irq function */ |
399 | ppc_md.get_irq = pmac_get_irq; | 340 | ppc_md.get_irq = pmac_pic_get_irq; |
400 | 341 | ||
401 | /* | 342 | /* |
402 | * Find the interrupt controller type & node | 343 | * Find the interrupt controller type & node |
@@ -414,7 +355,6 @@ static void __init pmac_pic_probe_oldstyle(void) | |||
414 | if (slave) { | 355 | if (slave) { |
415 | max_irqs = 64; | 356 | max_irqs = 64; |
416 | level_mask[1] = OHARE_LEVEL_MASK; | 357 | level_mask[1] = OHARE_LEVEL_MASK; |
417 | enable_second_ohare(slave); | ||
418 | } | 358 | } |
419 | } else if ((master = of_find_node_by_name(NULL, "mac-io")) != NULL) { | 359 | } else if ((master = of_find_node_by_name(NULL, "mac-io")) != NULL) { |
420 | max_irqs = max_real_irqs = 64; | 360 | max_irqs = max_real_irqs = 64; |
@@ -438,14 +378,18 @@ static void __init pmac_pic_probe_oldstyle(void) | |||
438 | max_irqs = 128; | 378 | max_irqs = 128; |
439 | level_mask[2] = HEATHROW_LEVEL_MASK; | 379 | level_mask[2] = HEATHROW_LEVEL_MASK; |
440 | level_mask[3] = 0; | 380 | level_mask[3] = 0; |
441 | pmac_fix_gatwick_interrupts(slave, max_real_irqs); | ||
442 | } | 381 | } |
443 | } | 382 | } |
444 | BUG_ON(master == NULL); | 383 | BUG_ON(master == NULL); |
445 | 384 | ||
446 | /* Set the handler for the main PIC */ | 385 | /* |
447 | for ( i = 0; i < max_real_irqs ; i++ ) | 386 | * Allocate an irq host |
448 | irq_desc[i].chip = &pmac_pic; | 387 | */ |
388 | pmac_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, max_irqs, | ||
389 | &pmac_pic_host_ops, | ||
390 | max_irqs); | ||
391 | BUG_ON(pmac_pic_host == NULL); | ||
392 | irq_set_default_host(pmac_pic_host); | ||
449 | 393 | ||
450 | /* Get addresses of first controller if we have a node for it */ | 394 | /* Get addresses of first controller if we have a node for it */ |
451 | BUG_ON(of_address_to_resource(master, 0, &r)); | 395 | BUG_ON(of_address_to_resource(master, 0, &r)); |
@@ -472,39 +416,38 @@ static void __init pmac_pic_probe_oldstyle(void) | |||
472 | pmac_irq_hw[i++] = | 416 | pmac_irq_hw[i++] = |
473 | (volatile struct pmac_irq_hw __iomem *) | 417 | (volatile struct pmac_irq_hw __iomem *) |
474 | (addr + 0x10); | 418 | (addr + 0x10); |
475 | irq_cascade = slave->intrs[0].line; | 419 | pmac_irq_cascade = irq_of_parse_and_map(slave, 0); |
476 | 420 | ||
477 | printk(KERN_INFO "irq: Found slave Apple PIC %s for %d irqs" | 421 | printk(KERN_INFO "irq: Found slave Apple PIC %s for %d irqs" |
478 | " cascade: %d\n", slave->full_name, | 422 | " cascade: %d\n", slave->full_name, |
479 | max_irqs - max_real_irqs, irq_cascade); | 423 | max_irqs - max_real_irqs, pmac_irq_cascade); |
480 | } | 424 | } |
481 | of_node_put(slave); | 425 | of_node_put(slave); |
482 | 426 | ||
483 | /* disable all interrupts in all controllers */ | 427 | /* Disable all interrupts in all controllers */ |
484 | for (i = 0; i * 32 < max_irqs; ++i) | 428 | for (i = 0; i * 32 < max_irqs; ++i) |
485 | out_le32(&pmac_irq_hw[i]->enable, 0); | 429 | out_le32(&pmac_irq_hw[i]->enable, 0); |
486 | 430 | ||
487 | /* mark level interrupts */ | 431 | /* Hookup cascade irq */ |
488 | for (i = 0; i < max_irqs; i++) | 432 | if (slave && pmac_irq_cascade != NO_IRQ) |
489 | if (level_mask[i >> 5] & (1UL << (i & 0x1f))) | 433 | setup_irq(pmac_irq_cascade, &gatwick_cascade_action); |
490 | irq_desc[i].status = IRQ_LEVEL; | ||
491 | 434 | ||
492 | /* Setup handlers for secondary controller and hook cascade irq*/ | ||
493 | if (slave) { | ||
494 | for ( i = max_real_irqs ; i < max_irqs ; i++ ) | ||
495 | irq_desc[i].chip = &gatwick_pic; | ||
496 | setup_irq(irq_cascade, &gatwick_cascade_action); | ||
497 | } | ||
498 | printk(KERN_INFO "irq: System has %d possible interrupts\n", max_irqs); | 435 | printk(KERN_INFO "irq: System has %d possible interrupts\n", max_irqs); |
499 | #ifdef CONFIG_XMON | 436 | #ifdef CONFIG_XMON |
500 | setup_irq(20, &xmon_action); | 437 | setup_irq(irq_create_mapping(NULL, 20, 0), &xmon_action); |
501 | #endif | 438 | #endif |
502 | } | 439 | } |
503 | #endif /* CONFIG_PPC32 */ | 440 | #endif /* CONFIG_PPC32 */ |
504 | 441 | ||
505 | static int pmac_u3_cascade(struct pt_regs *regs, void *data) | 442 | static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc, |
443 | struct pt_regs *regs) | ||
506 | { | 444 | { |
507 | return mpic_get_one_irq((struct mpic *)data, regs); | 445 | struct mpic *mpic = desc->handler_data; |
446 | |||
447 | unsigned int cascade_irq = mpic_get_one_irq(mpic, regs); | ||
448 | if (cascade_irq != NO_IRQ) | ||
449 | generic_handle_irq(cascade_irq, regs); | ||
450 | desc->chip->eoi(irq); | ||
508 | } | 451 | } |
509 | 452 | ||
510 | static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic) | 453 | static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic) |
@@ -514,21 +457,20 @@ static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic) | |||
514 | int nmi_irq; | 457 | int nmi_irq; |
515 | 458 | ||
516 | pswitch = of_find_node_by_name(NULL, "programmer-switch"); | 459 | pswitch = of_find_node_by_name(NULL, "programmer-switch"); |
517 | if (pswitch && pswitch->n_intrs) { | 460 | if (pswitch) { |
518 | nmi_irq = pswitch->intrs[0].line; | 461 | nmi_irq = irq_of_parse_and_map(pswitch, 0); |
519 | mpic_irq_set_priority(nmi_irq, 9); | 462 | if (nmi_irq != NO_IRQ) { |
520 | setup_irq(nmi_irq, &xmon_action); | 463 | mpic_irq_set_priority(nmi_irq, 9); |
464 | setup_irq(nmi_irq, &xmon_action); | ||
465 | } | ||
466 | of_node_put(pswitch); | ||
521 | } | 467 | } |
522 | of_node_put(pswitch); | ||
523 | #endif /* defined(CONFIG_XMON) && defined(CONFIG_PPC32) */ | 468 | #endif /* defined(CONFIG_XMON) && defined(CONFIG_PPC32) */ |
524 | } | 469 | } |
525 | 470 | ||
526 | static struct mpic * __init pmac_setup_one_mpic(struct device_node *np, | 471 | static struct mpic * __init pmac_setup_one_mpic(struct device_node *np, |
527 | int master) | 472 | int master) |
528 | { | 473 | { |
529 | unsigned char senses[128]; | ||
530 | int offset = master ? 0 : 128; | ||
531 | int count = master ? 128 : 124; | ||
532 | const char *name = master ? " MPIC 1 " : " MPIC 2 "; | 474 | const char *name = master ? " MPIC 1 " : " MPIC 2 "; |
533 | struct resource r; | 475 | struct resource r; |
534 | struct mpic *mpic; | 476 | struct mpic *mpic; |
@@ -541,8 +483,6 @@ static struct mpic * __init pmac_setup_one_mpic(struct device_node *np, | |||
541 | 483 | ||
542 | pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0); | 484 | pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0); |
543 | 485 | ||
544 | prom_get_irq_senses(senses, offset, offset + count); | ||
545 | |||
546 | flags |= MPIC_WANTS_RESET; | 486 | flags |= MPIC_WANTS_RESET; |
547 | if (get_property(np, "big-endian", NULL)) | 487 | if (get_property(np, "big-endian", NULL)) |
548 | flags |= MPIC_BIG_ENDIAN; | 488 | flags |= MPIC_BIG_ENDIAN; |
@@ -553,8 +493,7 @@ static struct mpic * __init pmac_setup_one_mpic(struct device_node *np, | |||
553 | if (master && (flags & MPIC_BIG_ENDIAN)) | 493 | if (master && (flags & MPIC_BIG_ENDIAN)) |
554 | flags |= MPIC_BROKEN_U3; | 494 | flags |= MPIC_BROKEN_U3; |
555 | 495 | ||
556 | mpic = mpic_alloc(r.start, flags, 0, offset, count, master ? 252 : 0, | 496 | mpic = mpic_alloc(np, r.start, flags, 0, 0, name); |
557 | senses, count, name); | ||
558 | if (mpic == NULL) | 497 | if (mpic == NULL) |
559 | return NULL; | 498 | return NULL; |
560 | 499 | ||
@@ -567,6 +506,7 @@ static int __init pmac_pic_probe_mpic(void) | |||
567 | { | 506 | { |
568 | struct mpic *mpic1, *mpic2; | 507 | struct mpic *mpic1, *mpic2; |
569 | struct device_node *np, *master = NULL, *slave = NULL; | 508 | struct device_node *np, *master = NULL, *slave = NULL; |
509 | unsigned int cascade; | ||
570 | 510 | ||
571 | /* We can have up to 2 MPICs cascaded */ | 511 | /* We can have up to 2 MPICs cascaded */ |
572 | for (np = NULL; (np = of_find_node_by_type(np, "open-pic")) | 512 | for (np = NULL; (np = of_find_node_by_type(np, "open-pic")) |
@@ -603,8 +543,15 @@ static int __init pmac_pic_probe_mpic(void) | |||
603 | of_node_put(master); | 543 | of_node_put(master); |
604 | 544 | ||
605 | /* No slave, let's go out */ | 545 | /* No slave, let's go out */ |
606 | if (slave == NULL || slave->n_intrs < 1) | 546 | if (slave == NULL) |
547 | return 0; | ||
548 | |||
549 | /* Get/Map slave interrupt */ | ||
550 | cascade = irq_of_parse_and_map(slave, 0); | ||
551 | if (cascade == NO_IRQ) { | ||
552 | printk(KERN_ERR "Failed to map cascade IRQ\n"); | ||
607 | return 0; | 553 | return 0; |
554 | } | ||
608 | 555 | ||
609 | mpic2 = pmac_setup_one_mpic(slave, 0); | 556 | mpic2 = pmac_setup_one_mpic(slave, 0); |
610 | if (mpic2 == NULL) { | 557 | if (mpic2 == NULL) { |
@@ -612,7 +559,8 @@ static int __init pmac_pic_probe_mpic(void) | |||
612 | of_node_put(slave); | 559 | of_node_put(slave); |
613 | return 0; | 560 | return 0; |
614 | } | 561 | } |
615 | mpic_setup_cascade(slave->intrs[0].line, pmac_u3_cascade, mpic2); | 562 | set_irq_data(cascade, mpic2); |
563 | set_irq_chained_handler(cascade, pmac_u3_cascade); | ||
616 | 564 | ||
617 | of_node_put(slave); | 565 | of_node_put(slave); |
618 | return 0; | 566 | return 0; |
@@ -621,6 +569,19 @@ static int __init pmac_pic_probe_mpic(void) | |||
621 | 569 | ||
622 | void __init pmac_pic_init(void) | 570 | void __init pmac_pic_init(void) |
623 | { | 571 | { |
572 | unsigned int flags = 0; | ||
573 | |||
574 | /* We configure the OF parsing based on our oldworld vs. newworld | ||
575 | * platform type and wether we were booted by BootX. | ||
576 | */ | ||
577 | #ifdef CONFIG_PPC32 | ||
578 | if (!pmac_newworld) | ||
579 | flags |= OF_IMAP_OLDWORLD_MAC; | ||
580 | if (get_property(of_chosen, "linux,bootx", NULL) != NULL) | ||
581 | flags |= OF_IMAP_NO_PHANDLE; | ||
582 | of_irq_map_init(flags); | ||
583 | #endif /* CONFIG_PPC_32 */ | ||
584 | |||
624 | /* We first try to detect Apple's new Core99 chipset, since mac-io | 585 | /* We first try to detect Apple's new Core99 chipset, since mac-io |
625 | * is quite different on those machines and contains an IBM MPIC2. | 586 | * is quite different on those machines and contains an IBM MPIC2. |
626 | */ | 587 | */ |
@@ -643,6 +604,7 @@ unsigned long sleep_save_mask[2]; | |||
643 | 604 | ||
644 | /* This used to be passed by the PMU driver but that link got | 605 | /* This used to be passed by the PMU driver but that link got |
645 | * broken with the new driver model. We use this tweak for now... | 606 | * broken with the new driver model. We use this tweak for now... |
607 | * We really want to do things differently though... | ||
646 | */ | 608 | */ |
647 | static int pmacpic_find_viaint(void) | 609 | static int pmacpic_find_viaint(void) |
648 | { | 610 | { |
@@ -656,7 +618,7 @@ static int pmacpic_find_viaint(void) | |||
656 | np = of_find_node_by_name(NULL, "via-pmu"); | 618 | np = of_find_node_by_name(NULL, "via-pmu"); |
657 | if (np == NULL) | 619 | if (np == NULL) |
658 | goto not_found; | 620 | goto not_found; |
659 | viaint = np->intrs[0].line; | 621 | viaint = irq_of_parse_and_map(np, 0);; |
660 | #endif /* CONFIG_ADB_PMU */ | 622 | #endif /* CONFIG_ADB_PMU */ |
661 | 623 | ||
662 | not_found: | 624 | not_found: |