^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Basic EISA bus support for the SGI Indigo-2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * (C) 2002 Pascal Dameme <netinet@freesurf.fr>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * and Marc Zyngier <mzyngier@freesurf.fr>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * This code is released under both the GPL version 2 and BSD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * licenses. Either license may be used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * This code offers a very basic support for this EISA bus present in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * the SGI Indigo-2. It currently only supports PIO (forget about DMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * for the time being). This is enough for a low-end ethernet card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * but forget about your favorite SCSI card...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * TODO :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * - Fix bugs...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * - Add ISA support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * - Add DMA (yeah, right...).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * - Fix more bugs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/eisa.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/kernel_stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <asm/mipsregs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <asm/addrspace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <asm/processor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <asm/sgi/ioc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <asm/sgi/mc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <asm/sgi/ip22.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <asm/i8259.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* I2 has four EISA slots. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define IP22_EISA_MAX_SLOTS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define EISA_MAX_IRQ 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define EIU_MODE_REG 0x0001ffc0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define EIU_STAT_REG 0x0001ffc4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define EIU_PREMPT_REG 0x0001ffc8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define EIU_QUIET_REG 0x0001ffcc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define EIU_INTRPT_ACK 0x00010004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static char __init *decode_eisa_sig(unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static char sig_str[EISA_SIG_LEN] __initdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) u8 sig[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) u16 rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) sig[i] = inb(addr + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (!i && (sig[0] & 0x80))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) sig_str[0] = ((sig[0] >> 2) & 0x1f) + ('A' - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) sig_str[1] = (((sig[0] & 3) << 3) | (sig[1] >> 5)) + ('A' - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) sig_str[2] = (sig[1] & 0x1f) + ('A' - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) rev = (sig[2] << 8) | sig[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) sprintf(sig_str + 3, "%04X", rev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return sig_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static irqreturn_t ip22_eisa_intr(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) u8 eisa_irq = inb(EIU_INTRPT_ACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) inb(EISA_DMA1_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) inb(EISA_DMA2_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (eisa_irq < EISA_MAX_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) do_IRQ(eisa_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* Oops, Bad Stuff Happened... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) printk(KERN_ERR "eisa_irq %d out of bound\n", eisa_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) outb(0x20, EISA_INT2_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) outb(0x20, EISA_INT1_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int __init ip22_eisa_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) int i, c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) char *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) printk(KERN_INFO "EISA: bus not present.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) printk(KERN_INFO "EISA: Probing bus...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) for (c = 0, i = 1; i <= IP22_EISA_MAX_SLOTS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if ((str = decode_eisa_sig(0x1000 * i + EISA_VENDOR_ID_OFFSET))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) printk(KERN_INFO "EISA: slot %d : %s detected.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) i, str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) c++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) printk(KERN_INFO "EISA: Detected %d card%s.\n", c, c < 2 ? "" : "s");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #ifdef CONFIG_ISA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) printk(KERN_INFO "ISA support compiled in.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* Warning : BlackMagicAhead(tm).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) Please wave your favorite dead chicken over the busses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* First say hello to the EIU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) outl(0x0000FFFF, EIU_PREMPT_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) outl(1, EIU_QUIET_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) outl(0x40f3c07F, EIU_MODE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* Now be nice to the EISA chipset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) outb(1, EISA_EXT_NMI_RESET_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) udelay(50); /* Wait long enough for the dust to settle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) outb(0, EISA_EXT_NMI_RESET_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) outb(0, EISA_DMA2_WRITE_SINGLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) init_i8259_irqs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (request_irq(SGI_EISA_IRQ, ip22_eisa_intr, 0, "EISA", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) pr_err("Failed to request irq %d (EISA)\n", SGI_EISA_IRQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) EISA_bus = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }