Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/kernel.h>
0003 #include <linux/string.h>
0004 #include <linux/init.h>
0005 #include <linux/of.h>
0006 #include <linux/of_platform.h>
0007 
0008 #include <asm/oplib.h>
0009 #include <asm/prom.h>
0010 #include <asm/irq.h>
0011 #include <asm/upa.h>
0012 
0013 #include "prom.h"
0014 
0015 #ifdef CONFIG_PCI
0016 /* PSYCHO interrupt mapping support. */
0017 #define PSYCHO_IMAP_A_SLOT0 0x0c00UL
0018 #define PSYCHO_IMAP_B_SLOT0 0x0c20UL
0019 static unsigned long psycho_pcislot_imap_offset(unsigned long ino)
0020 {
0021     unsigned int bus =  (ino & 0x10) >> 4;
0022     unsigned int slot = (ino & 0x0c) >> 2;
0023 
0024     if (bus == 0)
0025         return PSYCHO_IMAP_A_SLOT0 + (slot * 8);
0026     else
0027         return PSYCHO_IMAP_B_SLOT0 + (slot * 8);
0028 }
0029 
0030 #define PSYCHO_OBIO_IMAP_BASE   0x1000UL
0031 
0032 #define PSYCHO_ONBOARD_IRQ_BASE     0x20
0033 #define psycho_onboard_imap_offset(__ino) \
0034     (PSYCHO_OBIO_IMAP_BASE + (((__ino) & 0x1f) << 3))
0035 
0036 #define PSYCHO_ICLR_A_SLOT0 0x1400UL
0037 #define PSYCHO_ICLR_SCSI    0x1800UL
0038 
0039 #define psycho_iclr_offset(ino)                       \
0040     ((ino & 0x20) ? (PSYCHO_ICLR_SCSI + (((ino) & 0x1f) << 3)) :  \
0041             (PSYCHO_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))
0042 
0043 static unsigned int psycho_irq_build(struct device_node *dp,
0044                      unsigned int ino,
0045                      void *_data)
0046 {
0047     unsigned long controller_regs = (unsigned long) _data;
0048     unsigned long imap, iclr;
0049     unsigned long imap_off, iclr_off;
0050     int inofixup = 0;
0051 
0052     ino &= 0x3f;
0053     if (ino < PSYCHO_ONBOARD_IRQ_BASE) {
0054         /* PCI slot */
0055         imap_off = psycho_pcislot_imap_offset(ino);
0056     } else {
0057         /* Onboard device */
0058         imap_off = psycho_onboard_imap_offset(ino);
0059     }
0060 
0061     /* Now build the IRQ bucket. */
0062     imap = controller_regs + imap_off;
0063 
0064     iclr_off = psycho_iclr_offset(ino);
0065     iclr = controller_regs + iclr_off;
0066 
0067     if ((ino & 0x20) == 0)
0068         inofixup = ino & 0x03;
0069 
0070     return build_irq(inofixup, iclr, imap);
0071 }
0072 
0073 static void __init psycho_irq_trans_init(struct device_node *dp)
0074 {
0075     const struct linux_prom64_registers *regs;
0076 
0077     dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
0078     dp->irq_trans->irq_build = psycho_irq_build;
0079 
0080     regs = of_get_property(dp, "reg", NULL);
0081     dp->irq_trans->data = (void *) regs[2].phys_addr;
0082 }
0083 
0084 #define sabre_read(__reg) \
0085 ({  u64 __ret; \
0086     __asm__ __volatile__("ldxa [%1] %2, %0" \
0087                  : "=r" (__ret) \
0088                  : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \
0089                  : "memory"); \
0090     __ret; \
0091 })
0092 
0093 struct sabre_irq_data {
0094     unsigned long controller_regs;
0095     unsigned int pci_first_busno;
0096 };
0097 #define SABRE_CONFIGSPACE   0x001000000UL
0098 #define SABRE_WRSYNC        0x1c20UL
0099 
0100 #define SABRE_CONFIG_BASE(CONFIG_SPACE) \
0101     (CONFIG_SPACE | (1UL << 24))
0102 #define SABRE_CONFIG_ENCODE(BUS, DEVFN, REG)    \
0103     (((unsigned long)(BUS)   << 16) |   \
0104      ((unsigned long)(DEVFN) << 8)  |   \
0105      ((unsigned long)(REG)))
0106 
0107 /* When a device lives behind a bridge deeper in the PCI bus topology
0108  * than APB, a special sequence must run to make sure all pending DMA
0109  * transfers at the time of IRQ delivery are visible in the coherency
0110  * domain by the cpu.  This sequence is to perform a read on the far
0111  * side of the non-APB bridge, then perform a read of Sabre's DMA
0112  * write-sync register.
0113  */
0114 static void sabre_wsync_handler(unsigned int ino, void *_arg1, void *_arg2)
0115 {
0116     unsigned int phys_hi = (unsigned int) (unsigned long) _arg1;
0117     struct sabre_irq_data *irq_data = _arg2;
0118     unsigned long controller_regs = irq_data->controller_regs;
0119     unsigned long sync_reg = controller_regs + SABRE_WRSYNC;
0120     unsigned long config_space = controller_regs + SABRE_CONFIGSPACE;
0121     unsigned int bus, devfn;
0122     u16 _unused;
0123 
0124     config_space = SABRE_CONFIG_BASE(config_space);
0125 
0126     bus = (phys_hi >> 16) & 0xff;
0127     devfn = (phys_hi >> 8) & 0xff;
0128 
0129     config_space |= SABRE_CONFIG_ENCODE(bus, devfn, 0x00);
0130 
0131     __asm__ __volatile__("membar #Sync\n\t"
0132                  "lduha [%1] %2, %0\n\t"
0133                  "membar #Sync"
0134                  : "=r" (_unused)
0135                  : "r" ((u16 *) config_space),
0136                    "i" (ASI_PHYS_BYPASS_EC_E_L)
0137                  : "memory");
0138 
0139     sabre_read(sync_reg);
0140 }
0141 
0142 #define SABRE_IMAP_A_SLOT0  0x0c00UL
0143 #define SABRE_IMAP_B_SLOT0  0x0c20UL
0144 #define SABRE_ICLR_A_SLOT0  0x1400UL
0145 #define SABRE_ICLR_B_SLOT0  0x1480UL
0146 #define SABRE_ICLR_SCSI     0x1800UL
0147 #define SABRE_ICLR_ETH      0x1808UL
0148 #define SABRE_ICLR_BPP      0x1810UL
0149 #define SABRE_ICLR_AU_REC   0x1818UL
0150 #define SABRE_ICLR_AU_PLAY  0x1820UL
0151 #define SABRE_ICLR_PFAIL    0x1828UL
0152 #define SABRE_ICLR_KMS      0x1830UL
0153 #define SABRE_ICLR_FLPY     0x1838UL
0154 #define SABRE_ICLR_SHW      0x1840UL
0155 #define SABRE_ICLR_KBD      0x1848UL
0156 #define SABRE_ICLR_MS       0x1850UL
0157 #define SABRE_ICLR_SER      0x1858UL
0158 #define SABRE_ICLR_UE       0x1870UL
0159 #define SABRE_ICLR_CE       0x1878UL
0160 #define SABRE_ICLR_PCIERR   0x1880UL
0161 
0162 static unsigned long sabre_pcislot_imap_offset(unsigned long ino)
0163 {
0164     unsigned int bus =  (ino & 0x10) >> 4;
0165     unsigned int slot = (ino & 0x0c) >> 2;
0166 
0167     if (bus == 0)
0168         return SABRE_IMAP_A_SLOT0 + (slot * 8);
0169     else
0170         return SABRE_IMAP_B_SLOT0 + (slot * 8);
0171 }
0172 
0173 #define SABRE_OBIO_IMAP_BASE    0x1000UL
0174 #define SABRE_ONBOARD_IRQ_BASE  0x20
0175 #define sabre_onboard_imap_offset(__ino) \
0176     (SABRE_OBIO_IMAP_BASE + (((__ino) & 0x1f) << 3))
0177 
0178 #define sabre_iclr_offset(ino)                        \
0179     ((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) :  \
0180             (SABRE_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))
0181 
0182 static int sabre_device_needs_wsync(struct device_node *dp)
0183 {
0184     struct device_node *parent = dp->parent;
0185     const char *parent_model, *parent_compat;
0186 
0187     /* This traversal up towards the root is meant to
0188      * handle two cases:
0189      *
0190      * 1) non-PCI bus sitting under PCI, such as 'ebus'
0191      * 2) the PCI controller interrupts themselves, which
0192      *    will use the sabre_irq_build but do not need
0193      *    the DMA synchronization handling
0194      */
0195     while (parent) {
0196         if (of_node_is_type(parent, "pci"))
0197             break;
0198         parent = parent->parent;
0199     }
0200 
0201     if (!parent)
0202         return 0;
0203 
0204     parent_model = of_get_property(parent,
0205                        "model", NULL);
0206     if (parent_model &&
0207         (!strcmp(parent_model, "SUNW,sabre") ||
0208          !strcmp(parent_model, "SUNW,simba")))
0209         return 0;
0210 
0211     parent_compat = of_get_property(parent,
0212                     "compatible", NULL);
0213     if (parent_compat &&
0214         (!strcmp(parent_compat, "pci108e,a000") ||
0215          !strcmp(parent_compat, "pci108e,a001")))
0216         return 0;
0217 
0218     return 1;
0219 }
0220 
0221 static unsigned int sabre_irq_build(struct device_node *dp,
0222                     unsigned int ino,
0223                     void *_data)
0224 {
0225     struct sabre_irq_data *irq_data = _data;
0226     unsigned long controller_regs = irq_data->controller_regs;
0227     const struct linux_prom_pci_registers *regs;
0228     unsigned long imap, iclr;
0229     unsigned long imap_off, iclr_off;
0230     int inofixup = 0;
0231     int irq;
0232 
0233     ino &= 0x3f;
0234     if (ino < SABRE_ONBOARD_IRQ_BASE) {
0235         /* PCI slot */
0236         imap_off = sabre_pcislot_imap_offset(ino);
0237     } else {
0238         /* onboard device */
0239         imap_off = sabre_onboard_imap_offset(ino);
0240     }
0241 
0242     /* Now build the IRQ bucket. */
0243     imap = controller_regs + imap_off;
0244 
0245     iclr_off = sabre_iclr_offset(ino);
0246     iclr = controller_regs + iclr_off;
0247 
0248     if ((ino & 0x20) == 0)
0249         inofixup = ino & 0x03;
0250 
0251     irq = build_irq(inofixup, iclr, imap);
0252 
0253     /* If the parent device is a PCI<->PCI bridge other than
0254      * APB, we have to install a pre-handler to ensure that
0255      * all pending DMA is drained before the interrupt handler
0256      * is run.
0257      */
0258     regs = of_get_property(dp, "reg", NULL);
0259     if (regs && sabre_device_needs_wsync(dp)) {
0260         irq_install_pre_handler(irq,
0261                     sabre_wsync_handler,
0262                     (void *) (long) regs->phys_hi,
0263                     (void *) irq_data);
0264     }
0265 
0266     return irq;
0267 }
0268 
0269 static void __init sabre_irq_trans_init(struct device_node *dp)
0270 {
0271     const struct linux_prom64_registers *regs;
0272     struct sabre_irq_data *irq_data;
0273     const u32 *busrange;
0274 
0275     dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
0276     dp->irq_trans->irq_build = sabre_irq_build;
0277 
0278     irq_data = prom_early_alloc(sizeof(struct sabre_irq_data));
0279 
0280     regs = of_get_property(dp, "reg", NULL);
0281     irq_data->controller_regs = regs[0].phys_addr;
0282 
0283     busrange = of_get_property(dp, "bus-range", NULL);
0284     irq_data->pci_first_busno = busrange[0];
0285 
0286     dp->irq_trans->data = irq_data;
0287 }
0288 
0289 /* SCHIZO interrupt mapping support.  Unlike Psycho, for this controller the
0290  * imap/iclr registers are per-PBM.
0291  */
0292 #define SCHIZO_IMAP_BASE    0x1000UL
0293 #define SCHIZO_ICLR_BASE    0x1400UL
0294 
0295 static unsigned long schizo_imap_offset(unsigned long ino)
0296 {
0297     return SCHIZO_IMAP_BASE + (ino * 8UL);
0298 }
0299 
0300 static unsigned long schizo_iclr_offset(unsigned long ino)
0301 {
0302     return SCHIZO_ICLR_BASE + (ino * 8UL);
0303 }
0304 
0305 static unsigned long schizo_ino_to_iclr(unsigned long pbm_regs,
0306                     unsigned int ino)
0307 {
0308 
0309     return pbm_regs + schizo_iclr_offset(ino);
0310 }
0311 
0312 static unsigned long schizo_ino_to_imap(unsigned long pbm_regs,
0313                     unsigned int ino)
0314 {
0315     return pbm_regs + schizo_imap_offset(ino);
0316 }
0317 
0318 #define schizo_read(__reg) \
0319 ({  u64 __ret; \
0320     __asm__ __volatile__("ldxa [%1] %2, %0" \
0321                  : "=r" (__ret) \
0322                  : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \
0323                  : "memory"); \
0324     __ret; \
0325 })
0326 #define schizo_write(__reg, __val) \
0327     __asm__ __volatile__("stxa %0, [%1] %2" \
0328                  : /* no outputs */ \
0329                  : "r" (__val), "r" (__reg), \
0330                    "i" (ASI_PHYS_BYPASS_EC_E) \
0331                  : "memory")
0332 
0333 static void tomatillo_wsync_handler(unsigned int ino, void *_arg1, void *_arg2)
0334 {
0335     unsigned long sync_reg = (unsigned long) _arg2;
0336     u64 mask = 1UL << (ino & IMAP_INO);
0337     u64 val;
0338     int limit;
0339 
0340     schizo_write(sync_reg, mask);
0341 
0342     limit = 100000;
0343     val = 0;
0344     while (--limit) {
0345         val = schizo_read(sync_reg);
0346         if (!(val & mask))
0347             break;
0348     }
0349     if (limit <= 0) {
0350         printk("tomatillo_wsync_handler: DMA won't sync [%llx:%llx]\n",
0351                val, mask);
0352     }
0353 
0354     if (_arg1) {
0355         static unsigned char cacheline[64]
0356             __attribute__ ((aligned (64)));
0357 
0358         __asm__ __volatile__("rd %%fprs, %0\n\t"
0359                      "or %0, %4, %1\n\t"
0360                      "wr %1, 0x0, %%fprs\n\t"
0361                      "stda %%f0, [%5] %6\n\t"
0362                      "wr %0, 0x0, %%fprs\n\t"
0363                      "membar #Sync"
0364                      : "=&r" (mask), "=&r" (val)
0365                      : "0" (mask), "1" (val),
0366                      "i" (FPRS_FEF), "r" (&cacheline[0]),
0367                      "i" (ASI_BLK_COMMIT_P));
0368     }
0369 }
0370 
0371 struct schizo_irq_data {
0372     unsigned long pbm_regs;
0373     unsigned long sync_reg;
0374     u32 portid;
0375     int chip_version;
0376 };
0377 
0378 static unsigned int schizo_irq_build(struct device_node *dp,
0379                      unsigned int ino,
0380                      void *_data)
0381 {
0382     struct schizo_irq_data *irq_data = _data;
0383     unsigned long pbm_regs = irq_data->pbm_regs;
0384     unsigned long imap, iclr;
0385     int ign_fixup;
0386     int irq;
0387     int is_tomatillo;
0388 
0389     ino &= 0x3f;
0390 
0391     /* Now build the IRQ bucket. */
0392     imap = schizo_ino_to_imap(pbm_regs, ino);
0393     iclr = schizo_ino_to_iclr(pbm_regs, ino);
0394 
0395     /* On Schizo, no inofixup occurs.  This is because each
0396      * INO has it's own IMAP register.  On Psycho and Sabre
0397      * there is only one IMAP register for each PCI slot even
0398      * though four different INOs can be generated by each
0399      * PCI slot.
0400      *
0401      * But, for JBUS variants (essentially, Tomatillo), we have
0402      * to fixup the lowest bit of the interrupt group number.
0403      */
0404     ign_fixup = 0;
0405 
0406     is_tomatillo = (irq_data->sync_reg != 0UL);
0407 
0408     if (is_tomatillo) {
0409         if (irq_data->portid & 1)
0410             ign_fixup = (1 << 6);
0411     }
0412 
0413     irq = build_irq(ign_fixup, iclr, imap);
0414 
0415     if (is_tomatillo) {
0416         irq_install_pre_handler(irq,
0417                     tomatillo_wsync_handler,
0418                     ((irq_data->chip_version <= 4) ?
0419                      (void *) 1 : (void *) 0),
0420                     (void *) irq_data->sync_reg);
0421     }
0422 
0423     return irq;
0424 }
0425 
0426 static void __init __schizo_irq_trans_init(struct device_node *dp,
0427                        int is_tomatillo)
0428 {
0429     const struct linux_prom64_registers *regs;
0430     struct schizo_irq_data *irq_data;
0431 
0432     dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
0433     dp->irq_trans->irq_build = schizo_irq_build;
0434 
0435     irq_data = prom_early_alloc(sizeof(struct schizo_irq_data));
0436 
0437     regs = of_get_property(dp, "reg", NULL);
0438     dp->irq_trans->data = irq_data;
0439 
0440     irq_data->pbm_regs = regs[0].phys_addr;
0441     if (is_tomatillo)
0442         irq_data->sync_reg = regs[3].phys_addr + 0x1a18UL;
0443     else
0444         irq_data->sync_reg = 0UL;
0445     irq_data->portid = of_getintprop_default(dp, "portid", 0);
0446     irq_data->chip_version = of_getintprop_default(dp, "version#", 0);
0447 }
0448 
0449 static void __init schizo_irq_trans_init(struct device_node *dp)
0450 {
0451     __schizo_irq_trans_init(dp, 0);
0452 }
0453 
0454 static void __init tomatillo_irq_trans_init(struct device_node *dp)
0455 {
0456     __schizo_irq_trans_init(dp, 1);
0457 }
0458 
0459 static unsigned int pci_sun4v_irq_build(struct device_node *dp,
0460                     unsigned int devino,
0461                     void *_data)
0462 {
0463     u32 devhandle = (u32) (unsigned long) _data;
0464 
0465     return sun4v_build_irq(devhandle, devino);
0466 }
0467 
0468 static void __init pci_sun4v_irq_trans_init(struct device_node *dp)
0469 {
0470     const struct linux_prom64_registers *regs;
0471 
0472     dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
0473     dp->irq_trans->irq_build = pci_sun4v_irq_build;
0474 
0475     regs = of_get_property(dp, "reg", NULL);
0476     dp->irq_trans->data = (void *) (unsigned long)
0477         ((regs->phys_addr >> 32UL) & 0x0fffffff);
0478 }
0479 
0480 struct fire_irq_data {
0481     unsigned long pbm_regs;
0482     u32 portid;
0483 };
0484 
0485 #define FIRE_IMAP_BASE  0x001000
0486 #define FIRE_ICLR_BASE  0x001400
0487 
0488 static unsigned long fire_imap_offset(unsigned long ino)
0489 {
0490     return FIRE_IMAP_BASE + (ino * 8UL);
0491 }
0492 
0493 static unsigned long fire_iclr_offset(unsigned long ino)
0494 {
0495     return FIRE_ICLR_BASE + (ino * 8UL);
0496 }
0497 
0498 static unsigned long fire_ino_to_iclr(unsigned long pbm_regs,
0499                         unsigned int ino)
0500 {
0501     return pbm_regs + fire_iclr_offset(ino);
0502 }
0503 
0504 static unsigned long fire_ino_to_imap(unsigned long pbm_regs,
0505                         unsigned int ino)
0506 {
0507     return pbm_regs + fire_imap_offset(ino);
0508 }
0509 
0510 static unsigned int fire_irq_build(struct device_node *dp,
0511                      unsigned int ino,
0512                      void *_data)
0513 {
0514     struct fire_irq_data *irq_data = _data;
0515     unsigned long pbm_regs = irq_data->pbm_regs;
0516     unsigned long imap, iclr;
0517     unsigned long int_ctrlr;
0518 
0519     ino &= 0x3f;
0520 
0521     /* Now build the IRQ bucket. */
0522     imap = fire_ino_to_imap(pbm_regs, ino);
0523     iclr = fire_ino_to_iclr(pbm_regs, ino);
0524 
0525     /* Set the interrupt controller number.  */
0526     int_ctrlr = 1 << 6;
0527     upa_writeq(int_ctrlr, imap);
0528 
0529     /* The interrupt map registers do not have an INO field
0530      * like other chips do.  They return zero in the INO
0531      * field, and the interrupt controller number is controlled
0532      * in bits 6 to 9.  So in order for build_irq() to get
0533      * the INO right we pass it in as part of the fixup
0534      * which will get added to the map register zero value
0535      * read by build_irq().
0536      */
0537     ino |= (irq_data->portid << 6);
0538     ino -= int_ctrlr;
0539     return build_irq(ino, iclr, imap);
0540 }
0541 
0542 static void __init fire_irq_trans_init(struct device_node *dp)
0543 {
0544     const struct linux_prom64_registers *regs;
0545     struct fire_irq_data *irq_data;
0546 
0547     dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
0548     dp->irq_trans->irq_build = fire_irq_build;
0549 
0550     irq_data = prom_early_alloc(sizeof(struct fire_irq_data));
0551 
0552     regs = of_get_property(dp, "reg", NULL);
0553     dp->irq_trans->data = irq_data;
0554 
0555     irq_data->pbm_regs = regs[0].phys_addr;
0556     irq_data->portid = of_getintprop_default(dp, "portid", 0);
0557 }
0558 #endif /* CONFIG_PCI */
0559 
0560 #ifdef CONFIG_SBUS
0561 /* INO number to IMAP register offset for SYSIO external IRQ's.
0562  * This should conform to both Sunfire/Wildfire server and Fusion
0563  * desktop designs.
0564  */
0565 #define SYSIO_IMAP_SLOT0    0x2c00UL
0566 #define SYSIO_IMAP_SLOT1    0x2c08UL
0567 #define SYSIO_IMAP_SLOT2    0x2c10UL
0568 #define SYSIO_IMAP_SLOT3    0x2c18UL
0569 #define SYSIO_IMAP_SCSI     0x3000UL
0570 #define SYSIO_IMAP_ETH      0x3008UL
0571 #define SYSIO_IMAP_BPP      0x3010UL
0572 #define SYSIO_IMAP_AUDIO    0x3018UL
0573 #define SYSIO_IMAP_PFAIL    0x3020UL
0574 #define SYSIO_IMAP_KMS      0x3028UL
0575 #define SYSIO_IMAP_FLPY     0x3030UL
0576 #define SYSIO_IMAP_SHW      0x3038UL
0577 #define SYSIO_IMAP_KBD      0x3040UL
0578 #define SYSIO_IMAP_MS       0x3048UL
0579 #define SYSIO_IMAP_SER      0x3050UL
0580 #define SYSIO_IMAP_TIM0     0x3060UL
0581 #define SYSIO_IMAP_TIM1     0x3068UL
0582 #define SYSIO_IMAP_UE       0x3070UL
0583 #define SYSIO_IMAP_CE       0x3078UL
0584 #define SYSIO_IMAP_SBERR    0x3080UL
0585 #define SYSIO_IMAP_PMGMT    0x3088UL
0586 #define SYSIO_IMAP_GFX      0x3090UL
0587 #define SYSIO_IMAP_EUPA     0x3098UL
0588 
0589 #define bogon     ((unsigned long) -1)
0590 static unsigned long sysio_irq_offsets[] = {
0591     /* SBUS Slot 0 --> 3, level 1 --> 7 */
0592     SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0,
0593     SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0,
0594     SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1,
0595     SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1,
0596     SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2,
0597     SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2,
0598     SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3,
0599     SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3,
0600 
0601     /* Onboard devices (not relevant/used on SunFire). */
0602     SYSIO_IMAP_SCSI,
0603     SYSIO_IMAP_ETH,
0604     SYSIO_IMAP_BPP,
0605     bogon,
0606     SYSIO_IMAP_AUDIO,
0607     SYSIO_IMAP_PFAIL,
0608     bogon,
0609     bogon,
0610     SYSIO_IMAP_KMS,
0611     SYSIO_IMAP_FLPY,
0612     SYSIO_IMAP_SHW,
0613     SYSIO_IMAP_KBD,
0614     SYSIO_IMAP_MS,
0615     SYSIO_IMAP_SER,
0616     bogon,
0617     bogon,
0618     SYSIO_IMAP_TIM0,
0619     SYSIO_IMAP_TIM1,
0620     bogon,
0621     bogon,
0622     SYSIO_IMAP_UE,
0623     SYSIO_IMAP_CE,
0624     SYSIO_IMAP_SBERR,
0625     SYSIO_IMAP_PMGMT,
0626     SYSIO_IMAP_GFX,
0627     SYSIO_IMAP_EUPA,
0628 };
0629 
0630 #undef bogon
0631 
0632 #define NUM_SYSIO_OFFSETS ARRAY_SIZE(sysio_irq_offsets)
0633 
0634 /* Convert Interrupt Mapping register pointer to associated
0635  * Interrupt Clear register pointer, SYSIO specific version.
0636  */
0637 #define SYSIO_ICLR_UNUSED0  0x3400UL
0638 #define SYSIO_ICLR_SLOT0    0x3408UL
0639 #define SYSIO_ICLR_SLOT1    0x3448UL
0640 #define SYSIO_ICLR_SLOT2    0x3488UL
0641 #define SYSIO_ICLR_SLOT3    0x34c8UL
0642 static unsigned long sysio_imap_to_iclr(unsigned long imap)
0643 {
0644     unsigned long diff = SYSIO_ICLR_UNUSED0 - SYSIO_IMAP_SLOT0;
0645     return imap + diff;
0646 }
0647 
0648 static unsigned int sbus_of_build_irq(struct device_node *dp,
0649                       unsigned int ino,
0650                       void *_data)
0651 {
0652     unsigned long reg_base = (unsigned long) _data;
0653     const struct linux_prom_registers *regs;
0654     unsigned long imap, iclr;
0655     int sbus_slot = 0;
0656     int sbus_level = 0;
0657 
0658     ino &= 0x3f;
0659 
0660     regs = of_get_property(dp, "reg", NULL);
0661     if (regs)
0662         sbus_slot = regs->which_io;
0663 
0664     if (ino < 0x20)
0665         ino += (sbus_slot * 8);
0666 
0667     imap = sysio_irq_offsets[ino];
0668     if (imap == ((unsigned long)-1)) {
0669         prom_printf("get_irq_translations: Bad SYSIO INO[%x]\n",
0670                 ino);
0671         prom_halt();
0672     }
0673     imap += reg_base;
0674 
0675     /* SYSIO inconsistency.  For external SLOTS, we have to select
0676      * the right ICLR register based upon the lower SBUS irq level
0677      * bits.
0678      */
0679     if (ino >= 0x20) {
0680         iclr = sysio_imap_to_iclr(imap);
0681     } else {
0682         sbus_level = ino & 0x7;
0683 
0684         switch(sbus_slot) {
0685         case 0:
0686             iclr = reg_base + SYSIO_ICLR_SLOT0;
0687             break;
0688         case 1:
0689             iclr = reg_base + SYSIO_ICLR_SLOT1;
0690             break;
0691         case 2:
0692             iclr = reg_base + SYSIO_ICLR_SLOT2;
0693             break;
0694         default:
0695         case 3:
0696             iclr = reg_base + SYSIO_ICLR_SLOT3;
0697             break;
0698         }
0699 
0700         iclr += ((unsigned long)sbus_level - 1UL) * 8UL;
0701     }
0702     return build_irq(sbus_level, iclr, imap);
0703 }
0704 
0705 static void __init sbus_irq_trans_init(struct device_node *dp)
0706 {
0707     const struct linux_prom64_registers *regs;
0708 
0709     dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
0710     dp->irq_trans->irq_build = sbus_of_build_irq;
0711 
0712     regs = of_get_property(dp, "reg", NULL);
0713     dp->irq_trans->data = (void *) (unsigned long) regs->phys_addr;
0714 }
0715 #endif /* CONFIG_SBUS */
0716 
0717 
0718 static unsigned int central_build_irq(struct device_node *dp,
0719                       unsigned int ino,
0720                       void *_data)
0721 {
0722     struct device_node *central_dp = _data;
0723     struct platform_device *central_op = of_find_device_by_node(central_dp);
0724     struct resource *res;
0725     unsigned long imap, iclr;
0726     u32 tmp;
0727 
0728     if (of_node_name_eq(dp, "eeprom")) {
0729         res = &central_op->resource[5];
0730     } else if (of_node_name_eq(dp, "zs")) {
0731         res = &central_op->resource[4];
0732     } else if (of_node_name_eq(dp, "clock-board")) {
0733         res = &central_op->resource[3];
0734     } else {
0735         return ino;
0736     }
0737 
0738     imap = res->start + 0x00UL;
0739     iclr = res->start + 0x10UL;
0740 
0741     /* Set the INO state to idle, and disable.  */
0742     upa_writel(0, iclr);
0743     upa_readl(iclr);
0744 
0745     tmp = upa_readl(imap);
0746     tmp &= ~0x80000000;
0747     upa_writel(tmp, imap);
0748 
0749     return build_irq(0, iclr, imap);
0750 }
0751 
0752 static void __init central_irq_trans_init(struct device_node *dp)
0753 {
0754     dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
0755     dp->irq_trans->irq_build = central_build_irq;
0756 
0757     dp->irq_trans->data = dp;
0758 }
0759 
0760 struct irq_trans {
0761     const char *name;
0762     void (*init)(struct device_node *);
0763 };
0764 
0765 #ifdef CONFIG_PCI
0766 static struct irq_trans __initdata pci_irq_trans_table[] = {
0767     { "SUNW,sabre", sabre_irq_trans_init },
0768     { "pci108e,a000", sabre_irq_trans_init },
0769     { "pci108e,a001", sabre_irq_trans_init },
0770     { "SUNW,psycho", psycho_irq_trans_init },
0771     { "pci108e,8000", psycho_irq_trans_init },
0772     { "SUNW,schizo", schizo_irq_trans_init },
0773     { "pci108e,8001", schizo_irq_trans_init },
0774     { "SUNW,schizo+", schizo_irq_trans_init },
0775     { "pci108e,8002", schizo_irq_trans_init },
0776     { "SUNW,tomatillo", tomatillo_irq_trans_init },
0777     { "pci108e,a801", tomatillo_irq_trans_init },
0778     { "SUNW,sun4v-pci", pci_sun4v_irq_trans_init },
0779     { "pciex108e,80f0", fire_irq_trans_init },
0780 };
0781 #endif
0782 
0783 static unsigned int sun4v_vdev_irq_build(struct device_node *dp,
0784                      unsigned int devino,
0785                      void *_data)
0786 {
0787     u32 devhandle = (u32) (unsigned long) _data;
0788 
0789     return sun4v_build_irq(devhandle, devino);
0790 }
0791 
0792 static void __init sun4v_vdev_irq_trans_init(struct device_node *dp)
0793 {
0794     const struct linux_prom64_registers *regs;
0795 
0796     dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller));
0797     dp->irq_trans->irq_build = sun4v_vdev_irq_build;
0798 
0799     regs = of_get_property(dp, "reg", NULL);
0800     dp->irq_trans->data = (void *) (unsigned long)
0801         ((regs->phys_addr >> 32UL) & 0x0fffffff);
0802 }
0803 
0804 void __init irq_trans_init(struct device_node *dp)
0805 {
0806 #ifdef CONFIG_PCI
0807     const char *model;
0808     int i;
0809 #endif
0810 
0811 #ifdef CONFIG_PCI
0812     model = of_get_property(dp, "model", NULL);
0813     if (!model)
0814         model = of_get_property(dp, "compatible", NULL);
0815     if (model) {
0816         for (i = 0; i < ARRAY_SIZE(pci_irq_trans_table); i++) {
0817             struct irq_trans *t = &pci_irq_trans_table[i];
0818 
0819             if (!strcmp(model, t->name)) {
0820                 t->init(dp);
0821                 return;
0822             }
0823         }
0824     }
0825 #endif
0826 #ifdef CONFIG_SBUS
0827     if (of_node_name_eq(dp, "sbus") ||
0828         of_node_name_eq(dp, "sbi")) {
0829         sbus_irq_trans_init(dp);
0830         return;
0831     }
0832 #endif
0833     if (of_node_name_eq(dp, "fhc") &&
0834         of_node_name_eq(dp->parent, "central")) {
0835         central_irq_trans_init(dp);
0836         return;
0837     }
0838     if (of_node_name_eq(dp, "virtual-devices") ||
0839         of_node_name_eq(dp, "niu")) {
0840         sun4v_vdev_irq_trans_init(dp);
0841         return;
0842     }
0843 }