GNU Linux-libre 6.8.9-gnu
[releases.git] / arch / sparc / kernel / prom_irqtrans.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/kernel.h>
3 #include <linux/string.h>
4 #include <linux/init.h>
5 #include <linux/of.h>
6 #include <linux/of_platform.h>
7 #include <linux/platform_device.h>
8
9 #include <asm/oplib.h>
10 #include <asm/prom.h>
11 #include <asm/irq.h>
12 #include <asm/upa.h>
13
14 #include "prom.h"
15
16 #ifdef CONFIG_PCI
17 /* PSYCHO interrupt mapping support. */
18 #define PSYCHO_IMAP_A_SLOT0     0x0c00UL
19 #define PSYCHO_IMAP_B_SLOT0     0x0c20UL
20 static unsigned long psycho_pcislot_imap_offset(unsigned long ino)
21 {
22         unsigned int bus =  (ino & 0x10) >> 4;
23         unsigned int slot = (ino & 0x0c) >> 2;
24
25         if (bus == 0)
26                 return PSYCHO_IMAP_A_SLOT0 + (slot * 8);
27         else
28                 return PSYCHO_IMAP_B_SLOT0 + (slot * 8);
29 }
30
31 #define PSYCHO_OBIO_IMAP_BASE   0x1000UL
32
33 #define PSYCHO_ONBOARD_IRQ_BASE         0x20
34 #define psycho_onboard_imap_offset(__ino) \
35         (PSYCHO_OBIO_IMAP_BASE + (((__ino) & 0x1f) << 3))
36
37 #define PSYCHO_ICLR_A_SLOT0     0x1400UL
38 #define PSYCHO_ICLR_SCSI        0x1800UL
39
40 #define psycho_iclr_offset(ino)                                       \
41         ((ino & 0x20) ? (PSYCHO_ICLR_SCSI + (((ino) & 0x1f) << 3)) :  \
42                         (PSYCHO_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))
43
44 static unsigned int psycho_irq_build(struct device_node *dp,
45                                      unsigned int ino,
46                                      void *_data)
47 {
48         unsigned long controller_regs = (unsigned long) _data;
49         unsigned long imap, iclr;
50         unsigned long imap_off, iclr_off;
51         int inofixup = 0;
52
53         ino &= 0x3f;
54         if (ino < PSYCHO_ONBOARD_IRQ_BASE) {
55                 /* PCI slot */
56                 imap_off = psycho_pcislot_imap_offset(ino);
57         } else {
58                 /* Onboard device */
59                 imap_off = psycho_onboard_imap_offset(ino);
60         }
61
62         /* Now build the IRQ bucket. */
63         imap = controller_regs + imap_off;
64
65         iclr_off = psycho_iclr_offset(ino);
66         iclr = controller_regs + iclr_off;
67
68         if ((ino & 0x20) == 0)
69                 inofixup = ino & 0x03;
70
71         return build_irq(inofixup, iclr, imap);
72 }
73
74 static void __init psycho_irq_trans_init(struct device_node *dp)
75 {
76         const struct linux_prom64_registers *regs;
77
78         dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
79         dp->irq_trans->irq_build = psycho_irq_build;
80
81         regs = of_get_property(dp, "reg", NULL);
82         dp->irq_trans->data = (void *) regs[2].phys_addr;
83 }
84
85 #define sabre_read(__reg) \
86 ({      u64 __ret; \
87         __asm__ __volatile__("ldxa [%1] %2, %0" \
88                              : "=r" (__ret) \
89                              : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \
90                              : "memory"); \
91         __ret; \
92 })
93
94 struct sabre_irq_data {
95         unsigned long controller_regs;
96         unsigned int pci_first_busno;
97 };
98 #define SABRE_CONFIGSPACE       0x001000000UL
99 #define SABRE_WRSYNC            0x1c20UL
100
101 #define SABRE_CONFIG_BASE(CONFIG_SPACE) \
102         (CONFIG_SPACE | (1UL << 24))
103 #define SABRE_CONFIG_ENCODE(BUS, DEVFN, REG)    \
104         (((unsigned long)(BUS)   << 16) |       \
105          ((unsigned long)(DEVFN) << 8)  |       \
106          ((unsigned long)(REG)))
107
108 /* When a device lives behind a bridge deeper in the PCI bus topology
109  * than APB, a special sequence must run to make sure all pending DMA
110  * transfers at the time of IRQ delivery are visible in the coherency
111  * domain by the cpu.  This sequence is to perform a read on the far
112  * side of the non-APB bridge, then perform a read of Sabre's DMA
113  * write-sync register.
114  */
115 static void sabre_wsync_handler(unsigned int ino, void *_arg1, void *_arg2)
116 {
117         unsigned int phys_hi = (unsigned int) (unsigned long) _arg1;
118         struct sabre_irq_data *irq_data = _arg2;
119         unsigned long controller_regs = irq_data->controller_regs;
120         unsigned long sync_reg = controller_regs + SABRE_WRSYNC;
121         unsigned long config_space = controller_regs + SABRE_CONFIGSPACE;
122         unsigned int bus, devfn;
123         u16 _unused;
124
125         config_space = SABRE_CONFIG_BASE(config_space);
126
127         bus = (phys_hi >> 16) & 0xff;
128         devfn = (phys_hi >> 8) & 0xff;
129
130         config_space |= SABRE_CONFIG_ENCODE(bus, devfn, 0x00);
131
132         __asm__ __volatile__("membar #Sync\n\t"
133                              "lduha [%1] %2, %0\n\t"
134                              "membar #Sync"
135                              : "=r" (_unused)
136                              : "r" ((u16 *) config_space),
137                                "i" (ASI_PHYS_BYPASS_EC_E_L)
138                              : "memory");
139
140         sabre_read(sync_reg);
141 }
142
143 #define SABRE_IMAP_A_SLOT0      0x0c00UL
144 #define SABRE_IMAP_B_SLOT0      0x0c20UL
145 #define SABRE_ICLR_A_SLOT0      0x1400UL
146 #define SABRE_ICLR_B_SLOT0      0x1480UL
147 #define SABRE_ICLR_SCSI         0x1800UL
148 #define SABRE_ICLR_ETH          0x1808UL
149 #define SABRE_ICLR_BPP          0x1810UL
150 #define SABRE_ICLR_AU_REC       0x1818UL
151 #define SABRE_ICLR_AU_PLAY      0x1820UL
152 #define SABRE_ICLR_PFAIL        0x1828UL
153 #define SABRE_ICLR_KMS          0x1830UL
154 #define SABRE_ICLR_FLPY         0x1838UL
155 #define SABRE_ICLR_SHW          0x1840UL
156 #define SABRE_ICLR_KBD          0x1848UL
157 #define SABRE_ICLR_MS           0x1850UL
158 #define SABRE_ICLR_SER          0x1858UL
159 #define SABRE_ICLR_UE           0x1870UL
160 #define SABRE_ICLR_CE           0x1878UL
161 #define SABRE_ICLR_PCIERR       0x1880UL
162
163 static unsigned long sabre_pcislot_imap_offset(unsigned long ino)
164 {
165         unsigned int bus =  (ino & 0x10) >> 4;
166         unsigned int slot = (ino & 0x0c) >> 2;
167
168         if (bus == 0)
169                 return SABRE_IMAP_A_SLOT0 + (slot * 8);
170         else
171                 return SABRE_IMAP_B_SLOT0 + (slot * 8);
172 }
173
174 #define SABRE_OBIO_IMAP_BASE    0x1000UL
175 #define SABRE_ONBOARD_IRQ_BASE  0x20
176 #define sabre_onboard_imap_offset(__ino) \
177         (SABRE_OBIO_IMAP_BASE + (((__ino) & 0x1f) << 3))
178
179 #define sabre_iclr_offset(ino)                                        \
180         ((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) :  \
181                         (SABRE_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))
182
183 static int sabre_device_needs_wsync(struct device_node *dp)
184 {
185         struct device_node *parent = dp->parent;
186         const char *parent_model, *parent_compat;
187
188         /* This traversal up towards the root is meant to
189          * handle two cases:
190          *
191          * 1) non-PCI bus sitting under PCI, such as 'ebus'
192          * 2) the PCI controller interrupts themselves, which
193          *    will use the sabre_irq_build but do not need
194          *    the DMA synchronization handling
195          */
196         while (parent) {
197                 if (of_node_is_type(parent, "pci"))
198                         break;
199                 parent = parent->parent;
200         }
201
202         if (!parent)
203                 return 0;
204
205         parent_model = of_get_property(parent,
206                                        "model", NULL);
207         if (parent_model &&
208             (!strcmp(parent_model, "SUNW,sabre") ||
209              !strcmp(parent_model, "SUNW,simba")))
210                 return 0;
211
212         parent_compat = of_get_property(parent,
213                                         "compatible", NULL);
214         if (parent_compat &&
215             (!strcmp(parent_compat, "pci108e,a000") ||
216              !strcmp(parent_compat, "pci108e,a001")))
217                 return 0;
218
219         return 1;
220 }
221
222 static unsigned int sabre_irq_build(struct device_node *dp,
223                                     unsigned int ino,
224                                     void *_data)
225 {
226         struct sabre_irq_data *irq_data = _data;
227         unsigned long controller_regs = irq_data->controller_regs;
228         const struct linux_prom_pci_registers *regs;
229         unsigned long imap, iclr;
230         unsigned long imap_off, iclr_off;
231         int inofixup = 0;
232         int irq;
233
234         ino &= 0x3f;
235         if (ino < SABRE_ONBOARD_IRQ_BASE) {
236                 /* PCI slot */
237                 imap_off = sabre_pcislot_imap_offset(ino);
238         } else {
239                 /* onboard device */
240                 imap_off = sabre_onboard_imap_offset(ino);
241         }
242
243         /* Now build the IRQ bucket. */
244         imap = controller_regs + imap_off;
245
246         iclr_off = sabre_iclr_offset(ino);
247         iclr = controller_regs + iclr_off;
248
249         if ((ino & 0x20) == 0)
250                 inofixup = ino & 0x03;
251
252         irq = build_irq(inofixup, iclr, imap);
253
254         /* If the parent device is a PCI<->PCI bridge other than
255          * APB, we have to install a pre-handler to ensure that
256          * all pending DMA is drained before the interrupt handler
257          * is run.
258          */
259         regs = of_get_property(dp, "reg", NULL);
260         if (regs && sabre_device_needs_wsync(dp)) {
261                 irq_install_pre_handler(irq,
262                                         sabre_wsync_handler,
263                                         (void *) (long) regs->phys_hi,
264                                         (void *) irq_data);
265         }
266
267         return irq;
268 }
269
270 static void __init sabre_irq_trans_init(struct device_node *dp)
271 {
272         const struct linux_prom64_registers *regs;
273         struct sabre_irq_data *irq_data;
274         const u32 *busrange;
275
276         dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
277         dp->irq_trans->irq_build = sabre_irq_build;
278
279         irq_data = prom_early_alloc(sizeof(struct sabre_irq_data));
280
281         regs = of_get_property(dp, "reg", NULL);
282         irq_data->controller_regs = regs[0].phys_addr;
283
284         busrange = of_get_property(dp, "bus-range", NULL);
285         irq_data->pci_first_busno = busrange[0];
286
287         dp->irq_trans->data = irq_data;
288 }
289
290 /* SCHIZO interrupt mapping support.  Unlike Psycho, for this controller the
291  * imap/iclr registers are per-PBM.
292  */
293 #define SCHIZO_IMAP_BASE        0x1000UL
294 #define SCHIZO_ICLR_BASE        0x1400UL
295
296 static unsigned long schizo_imap_offset(unsigned long ino)
297 {
298         return SCHIZO_IMAP_BASE + (ino * 8UL);
299 }
300
301 static unsigned long schizo_iclr_offset(unsigned long ino)
302 {
303         return SCHIZO_ICLR_BASE + (ino * 8UL);
304 }
305
306 static unsigned long schizo_ino_to_iclr(unsigned long pbm_regs,
307                                         unsigned int ino)
308 {
309
310         return pbm_regs + schizo_iclr_offset(ino);
311 }
312
313 static unsigned long schizo_ino_to_imap(unsigned long pbm_regs,
314                                         unsigned int ino)
315 {
316         return pbm_regs + schizo_imap_offset(ino);
317 }
318
319 #define schizo_read(__reg) \
320 ({      u64 __ret; \
321         __asm__ __volatile__("ldxa [%1] %2, %0" \
322                              : "=r" (__ret) \
323                              : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \
324                              : "memory"); \
325         __ret; \
326 })
327 #define schizo_write(__reg, __val) \
328         __asm__ __volatile__("stxa %0, [%1] %2" \
329                              : /* no outputs */ \
330                              : "r" (__val), "r" (__reg), \
331                                "i" (ASI_PHYS_BYPASS_EC_E) \
332                              : "memory")
333
334 static void tomatillo_wsync_handler(unsigned int ino, void *_arg1, void *_arg2)
335 {
336         unsigned long sync_reg = (unsigned long) _arg2;
337         u64 mask = 1UL << (ino & IMAP_INO);
338         u64 val;
339         int limit;
340
341         schizo_write(sync_reg, mask);
342
343         limit = 100000;
344         val = 0;
345         while (--limit) {
346                 val = schizo_read(sync_reg);
347                 if (!(val & mask))
348                         break;
349         }
350         if (limit <= 0) {
351                 printk("tomatillo_wsync_handler: DMA won't sync [%llx:%llx]\n",
352                        val, mask);
353         }
354
355         if (_arg1) {
356                 static unsigned char cacheline[64]
357                         __attribute__ ((aligned (64)));
358
359                 __asm__ __volatile__("rd %%fprs, %0\n\t"
360                                      "or %0, %4, %1\n\t"
361                                      "wr %1, 0x0, %%fprs\n\t"
362                                      "stda %%f0, [%5] %6\n\t"
363                                      "wr %0, 0x0, %%fprs\n\t"
364                                      "membar #Sync"
365                                      : "=&r" (mask), "=&r" (val)
366                                      : "0" (mask), "1" (val),
367                                      "i" (FPRS_FEF), "r" (&cacheline[0]),
368                                      "i" (ASI_BLK_COMMIT_P));
369         }
370 }
371
372 struct schizo_irq_data {
373         unsigned long pbm_regs;
374         unsigned long sync_reg;
375         u32 portid;
376         int chip_version;
377 };
378
379 static unsigned int schizo_irq_build(struct device_node *dp,
380                                      unsigned int ino,
381                                      void *_data)
382 {
383         struct schizo_irq_data *irq_data = _data;
384         unsigned long pbm_regs = irq_data->pbm_regs;
385         unsigned long imap, iclr;
386         int ign_fixup;
387         int irq;
388         int is_tomatillo;
389
390         ino &= 0x3f;
391
392         /* Now build the IRQ bucket. */
393         imap = schizo_ino_to_imap(pbm_regs, ino);
394         iclr = schizo_ino_to_iclr(pbm_regs, ino);
395
396         /* On Schizo, no inofixup occurs.  This is because each
397          * INO has it's own IMAP register.  On Psycho and Sabre
398          * there is only one IMAP register for each PCI slot even
399          * though four different INOs can be generated by each
400          * PCI slot.
401          *
402          * But, for JBUS variants (essentially, Tomatillo), we have
403          * to fixup the lowest bit of the interrupt group number.
404          */
405         ign_fixup = 0;
406
407         is_tomatillo = (irq_data->sync_reg != 0UL);
408
409         if (is_tomatillo) {
410                 if (irq_data->portid & 1)
411                         ign_fixup = (1 << 6);
412         }
413
414         irq = build_irq(ign_fixup, iclr, imap);
415
416         if (is_tomatillo) {
417                 irq_install_pre_handler(irq,
418                                         tomatillo_wsync_handler,
419                                         ((irq_data->chip_version <= 4) ?
420                                          (void *) 1 : (void *) 0),
421                                         (void *) irq_data->sync_reg);
422         }
423
424         return irq;
425 }
426
427 static void __init __schizo_irq_trans_init(struct device_node *dp,
428                                            int is_tomatillo)
429 {
430         const struct linux_prom64_registers *regs;
431         struct schizo_irq_data *irq_data;
432
433         dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
434         dp->irq_trans->irq_build = schizo_irq_build;
435
436         irq_data = prom_early_alloc(sizeof(struct schizo_irq_data));
437
438         regs = of_get_property(dp, "reg", NULL);
439         dp->irq_trans->data = irq_data;
440
441         irq_data->pbm_regs = regs[0].phys_addr;
442         if (is_tomatillo)
443                 irq_data->sync_reg = regs[3].phys_addr + 0x1a18UL;
444         else
445                 irq_data->sync_reg = 0UL;
446         irq_data->portid = of_getintprop_default(dp, "portid", 0);
447         irq_data->chip_version = of_getintprop_default(dp, "version#", 0);
448 }
449
450 static void __init schizo_irq_trans_init(struct device_node *dp)
451 {
452         __schizo_irq_trans_init(dp, 0);
453 }
454
455 static void __init tomatillo_irq_trans_init(struct device_node *dp)
456 {
457         __schizo_irq_trans_init(dp, 1);
458 }
459
460 static unsigned int pci_sun4v_irq_build(struct device_node *dp,
461                                         unsigned int devino,
462                                         void *_data)
463 {
464         u32 devhandle = (u32) (unsigned long) _data;
465
466         return sun4v_build_irq(devhandle, devino);
467 }
468
469 static void __init pci_sun4v_irq_trans_init(struct device_node *dp)
470 {
471         const struct linux_prom64_registers *regs;
472
473         dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
474         dp->irq_trans->irq_build = pci_sun4v_irq_build;
475
476         regs = of_get_property(dp, "reg", NULL);
477         dp->irq_trans->data = (void *) (unsigned long)
478                 ((regs->phys_addr >> 32UL) & 0x0fffffff);
479 }
480
481 struct fire_irq_data {
482         unsigned long pbm_regs;
483         u32 portid;
484 };
485
486 #define FIRE_IMAP_BASE  0x001000
487 #define FIRE_ICLR_BASE  0x001400
488
489 static unsigned long fire_imap_offset(unsigned long ino)
490 {
491         return FIRE_IMAP_BASE + (ino * 8UL);
492 }
493
494 static unsigned long fire_iclr_offset(unsigned long ino)
495 {
496         return FIRE_ICLR_BASE + (ino * 8UL);
497 }
498
499 static unsigned long fire_ino_to_iclr(unsigned long pbm_regs,
500                                             unsigned int ino)
501 {
502         return pbm_regs + fire_iclr_offset(ino);
503 }
504
505 static unsigned long fire_ino_to_imap(unsigned long pbm_regs,
506                                             unsigned int ino)
507 {
508         return pbm_regs + fire_imap_offset(ino);
509 }
510
511 static unsigned int fire_irq_build(struct device_node *dp,
512                                          unsigned int ino,
513                                          void *_data)
514 {
515         struct fire_irq_data *irq_data = _data;
516         unsigned long pbm_regs = irq_data->pbm_regs;
517         unsigned long imap, iclr;
518         unsigned long int_ctrlr;
519
520         ino &= 0x3f;
521
522         /* Now build the IRQ bucket. */
523         imap = fire_ino_to_imap(pbm_regs, ino);
524         iclr = fire_ino_to_iclr(pbm_regs, ino);
525
526         /* Set the interrupt controller number.  */
527         int_ctrlr = 1 << 6;
528         upa_writeq(int_ctrlr, imap);
529
530         /* The interrupt map registers do not have an INO field
531          * like other chips do.  They return zero in the INO
532          * field, and the interrupt controller number is controlled
533          * in bits 6 to 9.  So in order for build_irq() to get
534          * the INO right we pass it in as part of the fixup
535          * which will get added to the map register zero value
536          * read by build_irq().
537          */
538         ino |= (irq_data->portid << 6);
539         ino -= int_ctrlr;
540         return build_irq(ino, iclr, imap);
541 }
542
543 static void __init fire_irq_trans_init(struct device_node *dp)
544 {
545         const struct linux_prom64_registers *regs;
546         struct fire_irq_data *irq_data;
547
548         dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
549         dp->irq_trans->irq_build = fire_irq_build;
550
551         irq_data = prom_early_alloc(sizeof(struct fire_irq_data));
552
553         regs = of_get_property(dp, "reg", NULL);
554         dp->irq_trans->data = irq_data;
555
556         irq_data->pbm_regs = regs[0].phys_addr;
557         irq_data->portid = of_getintprop_default(dp, "portid", 0);
558 }
559 #endif /* CONFIG_PCI */
560
561 #ifdef CONFIG_SBUS
562 /* INO number to IMAP register offset for SYSIO external IRQ's.
563  * This should conform to both Sunfire/Wildfire server and Fusion
564  * desktop designs.
565  */
566 #define SYSIO_IMAP_SLOT0        0x2c00UL
567 #define SYSIO_IMAP_SLOT1        0x2c08UL
568 #define SYSIO_IMAP_SLOT2        0x2c10UL
569 #define SYSIO_IMAP_SLOT3        0x2c18UL
570 #define SYSIO_IMAP_SCSI         0x3000UL
571 #define SYSIO_IMAP_ETH          0x3008UL
572 #define SYSIO_IMAP_BPP          0x3010UL
573 #define SYSIO_IMAP_AUDIO        0x3018UL
574 #define SYSIO_IMAP_PFAIL        0x3020UL
575 #define SYSIO_IMAP_KMS          0x3028UL
576 #define SYSIO_IMAP_FLPY         0x3030UL
577 #define SYSIO_IMAP_SHW          0x3038UL
578 #define SYSIO_IMAP_KBD          0x3040UL
579 #define SYSIO_IMAP_MS           0x3048UL
580 #define SYSIO_IMAP_SER          0x3050UL
581 #define SYSIO_IMAP_TIM0         0x3060UL
582 #define SYSIO_IMAP_TIM1         0x3068UL
583 #define SYSIO_IMAP_UE           0x3070UL
584 #define SYSIO_IMAP_CE           0x3078UL
585 #define SYSIO_IMAP_SBERR        0x3080UL
586 #define SYSIO_IMAP_PMGMT        0x3088UL
587 #define SYSIO_IMAP_GFX          0x3090UL
588 #define SYSIO_IMAP_EUPA         0x3098UL
589
590 #define bogon     ((unsigned long) -1)
591 static unsigned long sysio_irq_offsets[] = {
592         /* SBUS Slot 0 --> 3, level 1 --> 7 */
593         SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0,
594         SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0,
595         SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1,
596         SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1,
597         SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2,
598         SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2,
599         SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3,
600         SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3,
601
602         /* Onboard devices (not relevant/used on SunFire). */
603         SYSIO_IMAP_SCSI,
604         SYSIO_IMAP_ETH,
605         SYSIO_IMAP_BPP,
606         bogon,
607         SYSIO_IMAP_AUDIO,
608         SYSIO_IMAP_PFAIL,
609         bogon,
610         bogon,
611         SYSIO_IMAP_KMS,
612         SYSIO_IMAP_FLPY,
613         SYSIO_IMAP_SHW,
614         SYSIO_IMAP_KBD,
615         SYSIO_IMAP_MS,
616         SYSIO_IMAP_SER,
617         bogon,
618         bogon,
619         SYSIO_IMAP_TIM0,
620         SYSIO_IMAP_TIM1,
621         bogon,
622         bogon,
623         SYSIO_IMAP_UE,
624         SYSIO_IMAP_CE,
625         SYSIO_IMAP_SBERR,
626         SYSIO_IMAP_PMGMT,
627         SYSIO_IMAP_GFX,
628         SYSIO_IMAP_EUPA,
629 };
630
631 #undef bogon
632
633 #define NUM_SYSIO_OFFSETS ARRAY_SIZE(sysio_irq_offsets)
634
635 /* Convert Interrupt Mapping register pointer to associated
636  * Interrupt Clear register pointer, SYSIO specific version.
637  */
638 #define SYSIO_ICLR_UNUSED0      0x3400UL
639 #define SYSIO_ICLR_SLOT0        0x3408UL
640 #define SYSIO_ICLR_SLOT1        0x3448UL
641 #define SYSIO_ICLR_SLOT2        0x3488UL
642 #define SYSIO_ICLR_SLOT3        0x34c8UL
643 static unsigned long sysio_imap_to_iclr(unsigned long imap)
644 {
645         unsigned long diff = SYSIO_ICLR_UNUSED0 - SYSIO_IMAP_SLOT0;
646         return imap + diff;
647 }
648
649 static unsigned int sbus_of_build_irq(struct device_node *dp,
650                                       unsigned int ino,
651                                       void *_data)
652 {
653         unsigned long reg_base = (unsigned long) _data;
654         const struct linux_prom_registers *regs;
655         unsigned long imap, iclr;
656         int sbus_slot = 0;
657         int sbus_level = 0;
658
659         ino &= 0x3f;
660
661         regs = of_get_property(dp, "reg", NULL);
662         if (regs)
663                 sbus_slot = regs->which_io;
664
665         if (ino < 0x20)
666                 ino += (sbus_slot * 8);
667
668         imap = sysio_irq_offsets[ino];
669         if (imap == ((unsigned long)-1)) {
670                 prom_printf("get_irq_translations: Bad SYSIO INO[%x]\n",
671                             ino);
672                 prom_halt();
673         }
674         imap += reg_base;
675
676         /* SYSIO inconsistency.  For external SLOTS, we have to select
677          * the right ICLR register based upon the lower SBUS irq level
678          * bits.
679          */
680         if (ino >= 0x20) {
681                 iclr = sysio_imap_to_iclr(imap);
682         } else {
683                 sbus_level = ino & 0x7;
684
685                 switch(sbus_slot) {
686                 case 0:
687                         iclr = reg_base + SYSIO_ICLR_SLOT0;
688                         break;
689                 case 1:
690                         iclr = reg_base + SYSIO_ICLR_SLOT1;
691                         break;
692                 case 2:
693                         iclr = reg_base + SYSIO_ICLR_SLOT2;
694                         break;
695                 default:
696                 case 3:
697                         iclr = reg_base + SYSIO_ICLR_SLOT3;
698                         break;
699                 }
700
701                 iclr += ((unsigned long)sbus_level - 1UL) * 8UL;
702         }
703         return build_irq(sbus_level, iclr, imap);
704 }
705
706 static void __init sbus_irq_trans_init(struct device_node *dp)
707 {
708         const struct linux_prom64_registers *regs;
709
710         dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
711         dp->irq_trans->irq_build = sbus_of_build_irq;
712
713         regs = of_get_property(dp, "reg", NULL);
714         dp->irq_trans->data = (void *) (unsigned long) regs->phys_addr;
715 }
716 #endif /* CONFIG_SBUS */
717
718
719 static unsigned int central_build_irq(struct device_node *dp,
720                                       unsigned int ino,
721                                       void *_data)
722 {
723         struct device_node *central_dp = _data;
724         struct platform_device *central_op = of_find_device_by_node(central_dp);
725         struct resource *res;
726         unsigned long imap, iclr;
727         u32 tmp;
728
729         if (of_node_name_eq(dp, "eeprom")) {
730                 res = &central_op->resource[5];
731         } else if (of_node_name_eq(dp, "zs")) {
732                 res = &central_op->resource[4];
733         } else if (of_node_name_eq(dp, "clock-board")) {
734                 res = &central_op->resource[3];
735         } else {
736                 return ino;
737         }
738
739         imap = res->start + 0x00UL;
740         iclr = res->start + 0x10UL;
741
742         /* Set the INO state to idle, and disable.  */
743         upa_writel(0, iclr);
744         upa_readl(iclr);
745
746         tmp = upa_readl(imap);
747         tmp &= ~0x80000000;
748         upa_writel(tmp, imap);
749
750         return build_irq(0, iclr, imap);
751 }
752
753 static void __init central_irq_trans_init(struct device_node *dp)
754 {
755         dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
756         dp->irq_trans->irq_build = central_build_irq;
757
758         dp->irq_trans->data = dp;
759 }
760
761 struct irq_trans {
762         const char *name;
763         void (*init)(struct device_node *);
764 };
765
766 #ifdef CONFIG_PCI
767 static struct irq_trans __initdata pci_irq_trans_table[] = {
768         { "SUNW,sabre", sabre_irq_trans_init },
769         { "pci108e,a000", sabre_irq_trans_init },
770         { "pci108e,a001", sabre_irq_trans_init },
771         { "SUNW,psycho", psycho_irq_trans_init },
772         { "pci108e,8000", psycho_irq_trans_init },
773         { "SUNW,schizo", schizo_irq_trans_init },
774         { "pci108e,8001", schizo_irq_trans_init },
775         { "SUNW,schizo+", schizo_irq_trans_init },
776         { "pci108e,8002", schizo_irq_trans_init },
777         { "SUNW,tomatillo", tomatillo_irq_trans_init },
778         { "pci108e,a801", tomatillo_irq_trans_init },
779         { "SUNW,sun4v-pci", pci_sun4v_irq_trans_init },
780         { "pciex108e,80f0", fire_irq_trans_init },
781 };
782 #endif
783
784 static unsigned int sun4v_vdev_irq_build(struct device_node *dp,
785                                          unsigned int devino,
786                                          void *_data)
787 {
788         u32 devhandle = (u32) (unsigned long) _data;
789
790         return sun4v_build_irq(devhandle, devino);
791 }
792
793 static void __init sun4v_vdev_irq_trans_init(struct device_node *dp)
794 {
795         const struct linux_prom64_registers *regs;
796
797         dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
798         dp->irq_trans->irq_build = sun4v_vdev_irq_build;
799
800         regs = of_get_property(dp, "reg", NULL);
801         dp->irq_trans->data = (void *) (unsigned long)
802                 ((regs->phys_addr >> 32UL) & 0x0fffffff);
803 }
804
805 void __init irq_trans_init(struct device_node *dp)
806 {
807 #ifdef CONFIG_PCI
808         const char *model;
809         int i;
810 #endif
811
812 #ifdef CONFIG_PCI
813         model = of_get_property(dp, "model", NULL);
814         if (!model)
815                 model = of_get_property(dp, "compatible", NULL);
816         if (model) {
817                 for (i = 0; i < ARRAY_SIZE(pci_irq_trans_table); i++) {
818                         struct irq_trans *t = &pci_irq_trans_table[i];
819
820                         if (!strcmp(model, t->name)) {
821                                 t->init(dp);
822                                 return;
823                         }
824                 }
825         }
826 #endif
827 #ifdef CONFIG_SBUS
828         if (of_node_name_eq(dp, "sbus") ||
829             of_node_name_eq(dp, "sbi")) {
830                 sbus_irq_trans_init(dp);
831                 return;
832         }
833 #endif
834         if (of_node_name_eq(dp, "fhc") &&
835             of_node_name_eq(dp->parent, "central")) {
836                 central_irq_trans_init(dp);
837                 return;
838         }
839         if (of_node_name_eq(dp, "virtual-devices") ||
840             of_node_name_eq(dp, "niu")) {
841                 sun4v_vdev_irq_trans_init(dp);
842                 return;
843         }
844 }