root/arch/sparc/kernel/prom_irqtrans.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. psycho_pcislot_imap_offset
  2. psycho_irq_build
  3. psycho_irq_trans_init
  4. sabre_wsync_handler
  5. sabre_pcislot_imap_offset
  6. sabre_device_needs_wsync
  7. sabre_irq_build
  8. sabre_irq_trans_init
  9. schizo_imap_offset
  10. schizo_iclr_offset
  11. schizo_ino_to_iclr
  12. schizo_ino_to_imap
  13. tomatillo_wsync_handler
  14. schizo_irq_build
  15. __schizo_irq_trans_init
  16. schizo_irq_trans_init
  17. tomatillo_irq_trans_init
  18. pci_sun4v_irq_build
  19. pci_sun4v_irq_trans_init
  20. fire_imap_offset
  21. fire_iclr_offset
  22. fire_ino_to_iclr
  23. fire_ino_to_imap
  24. fire_irq_build
  25. fire_irq_trans_init
  26. sysio_imap_to_iclr
  27. sbus_of_build_irq
  28. sbus_irq_trans_init
  29. central_build_irq
  30. central_irq_trans_init
  31. sun4v_vdev_irq_build
  32. sun4v_vdev_irq_trans_init
  33. irq_trans_init

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

/* [<][>][^][v][top][bottom][index][help] */