11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Basic EISA bus support for the SGI Indigo-2. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * (C) 2002 Pascal Dameme <netinet@freesurf.fr> 51da177e4SLinus Torvalds * and Marc Zyngier <mzyngier@freesurf.fr> 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * This code is released under both the GPL version 2 and BSD 81da177e4SLinus Torvalds * licenses. Either license may be used. 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * This code offers a very basic support for this EISA bus present in 111da177e4SLinus Torvalds * the SGI Indigo-2. It currently only supports PIO (forget about DMA 121da177e4SLinus Torvalds * for the time being). This is enough for a low-end ethernet card, 131da177e4SLinus Torvalds * but forget about your favorite SCSI card... 141da177e4SLinus Torvalds * 151da177e4SLinus Torvalds * TODO : 161da177e4SLinus Torvalds * - Fix bugs... 171da177e4SLinus Torvalds * - Add ISA support 181da177e4SLinus Torvalds * - Add DMA (yeah, right...). 191da177e4SLinus Torvalds * - Fix more bugs. 201da177e4SLinus Torvalds */ 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds #include <linux/eisa.h> 231da177e4SLinus Torvalds #include <linux/types.h> 241da177e4SLinus Torvalds #include <linux/init.h> 251da177e4SLinus Torvalds #include <linux/irq.h> 261da177e4SLinus Torvalds #include <linux/kernel_stat.h> 271da177e4SLinus Torvalds #include <linux/signal.h> 281da177e4SLinus Torvalds #include <linux/sched.h> 291da177e4SLinus Torvalds #include <linux/interrupt.h> 301da177e4SLinus Torvalds #include <linux/delay.h> 3137c8c642SThiemo Seufer #include <asm/io.h> 321da177e4SLinus Torvalds #include <asm/irq.h> 331da177e4SLinus Torvalds #include <asm/mipsregs.h> 341da177e4SLinus Torvalds #include <asm/addrspace.h> 351da177e4SLinus Torvalds #include <asm/processor.h> 361da177e4SLinus Torvalds #include <asm/sgi/ioc.h> 371da177e4SLinus Torvalds #include <asm/sgi/mc.h> 381da177e4SLinus Torvalds #include <asm/sgi/ip22.h> 3968de4803SThomas Bogendoerfer #include <asm/i8259.h> 401da177e4SLinus Torvalds 4137c8c642SThiemo Seufer /* I2 has four EISA slots. */ 4237c8c642SThiemo Seufer #define IP22_EISA_MAX_SLOTS 4 431da177e4SLinus Torvalds #define EISA_MAX_IRQ 16 441da177e4SLinus Torvalds 4537c8c642SThiemo Seufer #define EIU_MODE_REG 0x0001ffc0 4637c8c642SThiemo Seufer #define EIU_STAT_REG 0x0001ffc4 4737c8c642SThiemo Seufer #define EIU_PREMPT_REG 0x0001ffc8 4837c8c642SThiemo Seufer #define EIU_QUIET_REG 0x0001ffcc 4937c8c642SThiemo Seufer #define EIU_INTRPT_ACK 0x00010004 501da177e4SLinus Torvalds 5137c8c642SThiemo Seufer static char __init *decode_eisa_sig(unsigned long addr) 521da177e4SLinus Torvalds { 53599a8945SDmitri Vorobiev static char sig_str[EISA_SIG_LEN] __initdata; 5437c8c642SThiemo Seufer u8 sig[4]; 551da177e4SLinus Torvalds u16 rev; 5637c8c642SThiemo Seufer int i; 571da177e4SLinus Torvalds 5837c8c642SThiemo Seufer for (i = 0; i < 4; i++) { 5937c8c642SThiemo Seufer sig[i] = inb(addr + i); 6037c8c642SThiemo Seufer 6137c8c642SThiemo Seufer if (!i && (sig[0] & 0x80)) 621da177e4SLinus Torvalds return NULL; 6337c8c642SThiemo Seufer } 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds sig_str[0] = ((sig[0] >> 2) & 0x1f) + ('A' - 1); 661da177e4SLinus Torvalds sig_str[1] = (((sig[0] & 3) << 3) | (sig[1] >> 5)) + ('A' - 1); 671da177e4SLinus Torvalds sig_str[2] = (sig[1] & 0x1f) + ('A' - 1); 681da177e4SLinus Torvalds rev = (sig[2] << 8) | sig[3]; 691da177e4SLinus Torvalds sprintf(sig_str + 3, "%04X", rev); 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds return sig_str; 721da177e4SLinus Torvalds } 731da177e4SLinus Torvalds 74937a8015SRalf Baechle static irqreturn_t ip22_eisa_intr(int irq, void *dev_id) 751da177e4SLinus Torvalds { 761da177e4SLinus Torvalds u8 eisa_irq; 771da177e4SLinus Torvalds u8 dma1, dma2; 781da177e4SLinus Torvalds 7937c8c642SThiemo Seufer eisa_irq = inb(EIU_INTRPT_ACK); 8037c8c642SThiemo Seufer dma1 = inb(EISA_DMA1_STATUS); 8137c8c642SThiemo Seufer dma2 = inb(EISA_DMA2_STATUS); 821da177e4SLinus Torvalds 8337c8c642SThiemo Seufer if (eisa_irq < EISA_MAX_IRQ) { 84937a8015SRalf Baechle do_IRQ(eisa_irq); 8537c8c642SThiemo Seufer return IRQ_HANDLED; 8637c8c642SThiemo Seufer } 8737c8c642SThiemo Seufer 881da177e4SLinus Torvalds /* Oops, Bad Stuff Happened... */ 891da177e4SLinus Torvalds printk(KERN_ERR "eisa_irq %d out of bound\n", eisa_irq); 901da177e4SLinus Torvalds 9137c8c642SThiemo Seufer outb(0x20, EISA_INT2_CTRL); 9237c8c642SThiemo Seufer outb(0x20, EISA_INT1_CTRL); 93937a8015SRalf Baechle 9437c8c642SThiemo Seufer return IRQ_NONE; 951da177e4SLinus Torvalds } 961da177e4SLinus Torvalds 971da177e4SLinus Torvalds static struct irqaction eisa_action = { 981da177e4SLinus Torvalds .handler = ip22_eisa_intr, 991da177e4SLinus Torvalds .name = "EISA", 1001da177e4SLinus Torvalds }; 1011da177e4SLinus Torvalds 1021da177e4SLinus Torvalds int __init ip22_eisa_init(void) 1031da177e4SLinus Torvalds { 1041da177e4SLinus Torvalds int i, c; 1051da177e4SLinus Torvalds char *str; 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) { 1081da177e4SLinus Torvalds printk(KERN_INFO "EISA: bus not present.\n"); 1091da177e4SLinus Torvalds return 1; 1101da177e4SLinus Torvalds } 1111da177e4SLinus Torvalds 1121da177e4SLinus Torvalds printk(KERN_INFO "EISA: Probing bus...\n"); 11337c8c642SThiemo Seufer for (c = 0, i = 1; i <= IP22_EISA_MAX_SLOTS; i++) { 11437c8c642SThiemo Seufer if ((str = decode_eisa_sig(0x1000 * i + EISA_VENDOR_ID_OFFSET))) { 1151da177e4SLinus Torvalds printk(KERN_INFO "EISA: slot %d : %s detected.\n", 1161da177e4SLinus Torvalds i, str); 1171da177e4SLinus Torvalds c++; 1181da177e4SLinus Torvalds } 1191da177e4SLinus Torvalds } 1201da177e4SLinus Torvalds printk(KERN_INFO "EISA: Detected %d card%s.\n", c, c < 2 ? "" : "s"); 1211da177e4SLinus Torvalds #ifdef CONFIG_ISA 1221da177e4SLinus Torvalds printk(KERN_INFO "ISA support compiled in.\n"); 1231da177e4SLinus Torvalds #endif 1241da177e4SLinus Torvalds 1251da177e4SLinus Torvalds /* Warning : BlackMagicAhead(tm). 1261da177e4SLinus Torvalds Please wave your favorite dead chicken over the busses */ 1271da177e4SLinus Torvalds 1281da177e4SLinus Torvalds /* First say hello to the EIU */ 12937c8c642SThiemo Seufer outl(0x0000FFFF, EIU_PREMPT_REG); 13037c8c642SThiemo Seufer outl(1, EIU_QUIET_REG); 13137c8c642SThiemo Seufer outl(0x40f3c07F, EIU_MODE_REG); 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds /* Now be nice to the EISA chipset */ 13437c8c642SThiemo Seufer outb(1, EISA_EXT_NMI_RESET_CTRL); 13537c8c642SThiemo Seufer udelay(50); /* Wait long enough for the dust to settle */ 13637c8c642SThiemo Seufer outb(0, EISA_EXT_NMI_RESET_CTRL); 13737c8c642SThiemo Seufer outb(0, EISA_DMA2_WRITE_SINGLE); 1381da177e4SLinus Torvalds 13968de4803SThomas Bogendoerfer init_i8259_irqs(); 1401da177e4SLinus Torvalds 1411da177e4SLinus Torvalds /* Cannot use request_irq because of kmalloc not being ready at such 1421da177e4SLinus Torvalds * an early stage. Yes, I've been bitten... */ 1431da177e4SLinus Torvalds setup_irq(SGI_EISA_IRQ, &eisa_action); 1441da177e4SLinus Torvalds 1451da177e4SLinus Torvalds EISA_bus = 1; 1461da177e4SLinus Torvalds return 0; 1471da177e4SLinus Torvalds } 148