0001
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
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
0055 imap_off = psycho_pcislot_imap_offset(ino);
0056 } else {
0057
0058 imap_off = psycho_onboard_imap_offset(ino);
0059 }
0060
0061
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
0108
0109
0110
0111
0112
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
0188
0189
0190
0191
0192
0193
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
0236 imap_off = sabre_pcislot_imap_offset(ino);
0237 } else {
0238
0239 imap_off = sabre_onboard_imap_offset(ino);
0240 }
0241
0242
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
0254
0255
0256
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
0290
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 : \
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
0392 imap = schizo_ino_to_imap(pbm_regs, ino);
0393 iclr = schizo_ino_to_iclr(pbm_regs, ino);
0394
0395
0396
0397
0398
0399
0400
0401
0402
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
0522 imap = fire_ino_to_imap(pbm_regs, ino);
0523 iclr = fire_ino_to_iclr(pbm_regs, ino);
0524
0525
0526 int_ctrlr = 1 << 6;
0527 upa_writeq(int_ctrlr, imap);
0528
0529
0530
0531
0532
0533
0534
0535
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
0559
0560 #ifdef CONFIG_SBUS
0561
0562
0563
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
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
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
0635
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
0676
0677
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
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 = ¢ral_op->resource[5];
0730 } else if (of_node_name_eq(dp, "zs")) {
0731 res = ¢ral_op->resource[4];
0732 } else if (of_node_name_eq(dp, "clock-board")) {
0733 res = ¢ral_op->resource[3];
0734 } else {
0735 return ino;
0736 }
0737
0738 imap = res->start + 0x00UL;
0739 iclr = res->start + 0x10UL;
0740
0741
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 }