11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * linux/arch/alpha/kernel/sys_eb64p.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 1995 David A Rusling 51da177e4SLinus Torvalds * Copyright (C) 1996 Jay A Estabrook 61da177e4SLinus Torvalds * Copyright (C) 1998, 1999 Richard Henderson 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * Code supporting the EB64+ and EB66. 91da177e4SLinus Torvalds */ 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds #include <linux/kernel.h> 121da177e4SLinus Torvalds #include <linux/types.h> 131da177e4SLinus Torvalds #include <linux/mm.h> 141da177e4SLinus Torvalds #include <linux/sched.h> 151da177e4SLinus Torvalds #include <linux/pci.h> 161da177e4SLinus Torvalds #include <linux/init.h> 171da177e4SLinus Torvalds #include <linux/bitops.h> 181da177e4SLinus Torvalds 191da177e4SLinus Torvalds #include <asm/ptrace.h> 201da177e4SLinus Torvalds #include <asm/system.h> 211da177e4SLinus Torvalds #include <asm/dma.h> 221da177e4SLinus Torvalds #include <asm/irq.h> 231da177e4SLinus Torvalds #include <asm/mmu_context.h> 241da177e4SLinus Torvalds #include <asm/io.h> 251da177e4SLinus Torvalds #include <asm/pgtable.h> 261da177e4SLinus Torvalds #include <asm/core_apecs.h> 271da177e4SLinus Torvalds #include <asm/core_lca.h> 281da177e4SLinus Torvalds #include <asm/hwrpb.h> 291da177e4SLinus Torvalds #include <asm/tlbflush.h> 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds #include "proto.h" 321da177e4SLinus Torvalds #include "irq_impl.h" 331da177e4SLinus Torvalds #include "pci_impl.h" 341da177e4SLinus Torvalds #include "machvec_impl.h" 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds 371da177e4SLinus Torvalds /* Note mask bit is true for DISABLED irqs. */ 381da177e4SLinus Torvalds static unsigned int cached_irq_mask = -1; 391da177e4SLinus Torvalds 401da177e4SLinus Torvalds static inline void 411da177e4SLinus Torvalds eb64p_update_irq_hw(unsigned int irq, unsigned long mask) 421da177e4SLinus Torvalds { 431da177e4SLinus Torvalds outb(mask >> (irq >= 24 ? 24 : 16), (irq >= 24 ? 0x27 : 0x26)); 441da177e4SLinus Torvalds } 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds static inline void 471da177e4SLinus Torvalds eb64p_enable_irq(unsigned int irq) 481da177e4SLinus Torvalds { 491da177e4SLinus Torvalds eb64p_update_irq_hw(irq, cached_irq_mask &= ~(1 << irq)); 501da177e4SLinus Torvalds } 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds static void 531da177e4SLinus Torvalds eb64p_disable_irq(unsigned int irq) 541da177e4SLinus Torvalds { 551da177e4SLinus Torvalds eb64p_update_irq_hw(irq, cached_irq_mask |= 1 << irq); 561da177e4SLinus Torvalds } 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds static unsigned int 591da177e4SLinus Torvalds eb64p_startup_irq(unsigned int irq) 601da177e4SLinus Torvalds { 611da177e4SLinus Torvalds eb64p_enable_irq(irq); 621da177e4SLinus Torvalds return 0; /* never anything pending */ 631da177e4SLinus Torvalds } 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds static void 661da177e4SLinus Torvalds eb64p_end_irq(unsigned int irq) 671da177e4SLinus Torvalds { 681da177e4SLinus Torvalds if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 691da177e4SLinus Torvalds eb64p_enable_irq(irq); 701da177e4SLinus Torvalds } 711da177e4SLinus Torvalds 7244377f62SThomas Gleixner static struct irq_chip eb64p_irq_type = { 738ab1221cSThomas Gleixner .name = "EB64P", 741da177e4SLinus Torvalds .startup = eb64p_startup_irq, 751da177e4SLinus Torvalds .shutdown = eb64p_disable_irq, 761da177e4SLinus Torvalds .enable = eb64p_enable_irq, 771da177e4SLinus Torvalds .disable = eb64p_disable_irq, 781da177e4SLinus Torvalds .ack = eb64p_disable_irq, 791da177e4SLinus Torvalds .end = eb64p_end_irq, 801da177e4SLinus Torvalds }; 811da177e4SLinus Torvalds 821da177e4SLinus Torvalds static void 837ca56053SAl Viro eb64p_device_interrupt(unsigned long vector) 841da177e4SLinus Torvalds { 851da177e4SLinus Torvalds unsigned long pld; 861da177e4SLinus Torvalds unsigned int i; 871da177e4SLinus Torvalds 881da177e4SLinus Torvalds /* Read the interrupt summary registers */ 891da177e4SLinus Torvalds pld = inb(0x26) | (inb(0x27) << 8); 901da177e4SLinus Torvalds 911da177e4SLinus Torvalds /* 921da177e4SLinus Torvalds * Now, for every possible bit set, work through 931da177e4SLinus Torvalds * them and call the appropriate interrupt handler. 941da177e4SLinus Torvalds */ 951da177e4SLinus Torvalds while (pld) { 961da177e4SLinus Torvalds i = ffz(~pld); 971da177e4SLinus Torvalds pld &= pld - 1; /* clear least bit set */ 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds if (i == 5) { 1007ca56053SAl Viro isa_device_interrupt(vector); 1011da177e4SLinus Torvalds } else { 1023dbb8c62SAl Viro handle_irq(16 + i); 1031da177e4SLinus Torvalds } 1041da177e4SLinus Torvalds } 1051da177e4SLinus Torvalds } 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds static void __init 1081da177e4SLinus Torvalds eb64p_init_irq(void) 1091da177e4SLinus Torvalds { 1101da177e4SLinus Torvalds long i; 1111da177e4SLinus Torvalds 1121da177e4SLinus Torvalds #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_CABRIOLET) 1131da177e4SLinus Torvalds /* 1141da177e4SLinus Torvalds * CABRIO SRM may not set variation correctly, so here we test 1151da177e4SLinus Torvalds * the high word of the interrupt summary register for the RAZ 1161da177e4SLinus Torvalds * bits, and hope that a true EB64+ would read all ones... 1171da177e4SLinus Torvalds */ 1181da177e4SLinus Torvalds if (inw(0x806) != 0xffff) { 1191da177e4SLinus Torvalds extern struct alpha_machine_vector cabriolet_mv; 1201da177e4SLinus Torvalds 1211da177e4SLinus Torvalds printk("Detected Cabriolet: correcting HWRPB.\n"); 1221da177e4SLinus Torvalds 1231da177e4SLinus Torvalds hwrpb->sys_variation |= 2L << 10; 1241da177e4SLinus Torvalds hwrpb_update_checksum(hwrpb); 1251da177e4SLinus Torvalds 1261da177e4SLinus Torvalds alpha_mv = cabriolet_mv; 1271da177e4SLinus Torvalds alpha_mv.init_irq(); 1281da177e4SLinus Torvalds return; 1291da177e4SLinus Torvalds } 1301da177e4SLinus Torvalds #endif /* GENERIC */ 1311da177e4SLinus Torvalds 1321da177e4SLinus Torvalds outb(0xff, 0x26); 1331da177e4SLinus Torvalds outb(0xff, 0x27); 1341da177e4SLinus Torvalds 1351da177e4SLinus Torvalds init_i8259a_irqs(); 1361da177e4SLinus Torvalds 1371da177e4SLinus Torvalds for (i = 16; i < 32; ++i) { 1381da177e4SLinus Torvalds irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL; 139d1bef4edSIngo Molnar irq_desc[i].chip = &eb64p_irq_type; 1401da177e4SLinus Torvalds } 1411da177e4SLinus Torvalds 1421da177e4SLinus Torvalds common_init_isa_dma(); 1431da177e4SLinus Torvalds setup_irq(16+5, &isa_cascade_irqaction); 1441da177e4SLinus Torvalds } 1451da177e4SLinus Torvalds 1461da177e4SLinus Torvalds /* 1471da177e4SLinus Torvalds * PCI Fixup configuration. 1481da177e4SLinus Torvalds * 1491da177e4SLinus Torvalds * There are two 8 bit external summary registers as follows: 1501da177e4SLinus Torvalds * 1511da177e4SLinus Torvalds * Summary @ 0x26: 1521da177e4SLinus Torvalds * Bit Meaning 1531da177e4SLinus Torvalds * 0 Interrupt Line A from slot 0 1541da177e4SLinus Torvalds * 1 Interrupt Line A from slot 1 1551da177e4SLinus Torvalds * 2 Interrupt Line B from slot 0 1561da177e4SLinus Torvalds * 3 Interrupt Line B from slot 1 1571da177e4SLinus Torvalds * 4 Interrupt Line C from slot 0 1581da177e4SLinus Torvalds * 5 Interrupt line from the two ISA PICs 1591da177e4SLinus Torvalds * 6 Tulip 1601da177e4SLinus Torvalds * 7 NCR SCSI 1611da177e4SLinus Torvalds * 1621da177e4SLinus Torvalds * Summary @ 0x27 1631da177e4SLinus Torvalds * Bit Meaning 1641da177e4SLinus Torvalds * 0 Interrupt Line C from slot 1 1651da177e4SLinus Torvalds * 1 Interrupt Line D from slot 0 1661da177e4SLinus Torvalds * 2 Interrupt Line D from slot 1 1671da177e4SLinus Torvalds * 3 RAZ 1681da177e4SLinus Torvalds * 4 RAZ 1691da177e4SLinus Torvalds * 5 RAZ 1701da177e4SLinus Torvalds * 6 RAZ 1711da177e4SLinus Torvalds * 7 RAZ 1721da177e4SLinus Torvalds * 1731da177e4SLinus Torvalds * The device to slot mapping looks like: 1741da177e4SLinus Torvalds * 1751da177e4SLinus Torvalds * Slot Device 1761da177e4SLinus Torvalds * 5 NCR SCSI controller 1771da177e4SLinus Torvalds * 6 PCI on board slot 0 1781da177e4SLinus Torvalds * 7 PCI on board slot 1 1791da177e4SLinus Torvalds * 8 Intel SIO PCI-ISA bridge chip 1801da177e4SLinus Torvalds * 9 Tulip - DECchip 21040 Ethernet controller 1811da177e4SLinus Torvalds * 1821da177e4SLinus Torvalds * 1831da177e4SLinus Torvalds * This two layered interrupt approach means that we allocate IRQ 16 and 1841da177e4SLinus Torvalds * above for PCI interrupts. The IRQ relates to which bit the interrupt 1851da177e4SLinus Torvalds * comes in on. This makes interrupt processing much easier. 1861da177e4SLinus Torvalds */ 1871da177e4SLinus Torvalds 1881da177e4SLinus Torvalds static int __init 1891da177e4SLinus Torvalds eb64p_map_irq(struct pci_dev *dev, u8 slot, u8 pin) 1901da177e4SLinus Torvalds { 1911da177e4SLinus Torvalds static char irq_tab[5][5] __initdata = { 1921da177e4SLinus Torvalds /*INT INTA INTB INTC INTD */ 1931da177e4SLinus Torvalds {16+7, 16+7, 16+7, 16+7, 16+7}, /* IdSel 5, slot ?, ?? */ 1941da177e4SLinus Torvalds {16+0, 16+0, 16+2, 16+4, 16+9}, /* IdSel 6, slot ?, ?? */ 1951da177e4SLinus Torvalds {16+1, 16+1, 16+3, 16+8, 16+10}, /* IdSel 7, slot ?, ?? */ 1961da177e4SLinus Torvalds { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */ 1971da177e4SLinus Torvalds {16+6, 16+6, 16+6, 16+6, 16+6}, /* IdSel 9, TULIP */ 1981da177e4SLinus Torvalds }; 1991da177e4SLinus Torvalds const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5; 2001da177e4SLinus Torvalds return COMMON_TABLE_LOOKUP; 2011da177e4SLinus Torvalds } 2021da177e4SLinus Torvalds 2031da177e4SLinus Torvalds 2041da177e4SLinus Torvalds /* 2051da177e4SLinus Torvalds * The System Vector 2061da177e4SLinus Torvalds */ 2071da177e4SLinus Torvalds 2081da177e4SLinus Torvalds #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB64P) 2091da177e4SLinus Torvalds struct alpha_machine_vector eb64p_mv __initmv = { 2101da177e4SLinus Torvalds .vector_name = "EB64+", 2111da177e4SLinus Torvalds DO_EV4_MMU, 2121da177e4SLinus Torvalds DO_DEFAULT_RTC, 2131da177e4SLinus Torvalds DO_APECS_IO, 2141da177e4SLinus Torvalds .machine_check = apecs_machine_check, 2151da177e4SLinus Torvalds .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, 2161da177e4SLinus Torvalds .min_io_address = DEFAULT_IO_BASE, 2171da177e4SLinus Torvalds .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE, 2181da177e4SLinus Torvalds 2191da177e4SLinus Torvalds .nr_irqs = 32, 2201da177e4SLinus Torvalds .device_interrupt = eb64p_device_interrupt, 2211da177e4SLinus Torvalds 2221da177e4SLinus Torvalds .init_arch = apecs_init_arch, 2231da177e4SLinus Torvalds .init_irq = eb64p_init_irq, 2241da177e4SLinus Torvalds .init_rtc = common_init_rtc, 2251da177e4SLinus Torvalds .init_pci = common_init_pci, 2261da177e4SLinus Torvalds .kill_arch = NULL, 2271da177e4SLinus Torvalds .pci_map_irq = eb64p_map_irq, 2281da177e4SLinus Torvalds .pci_swizzle = common_swizzle, 2291da177e4SLinus Torvalds }; 2301da177e4SLinus Torvalds ALIAS_MV(eb64p) 2311da177e4SLinus Torvalds #endif 2321da177e4SLinus Torvalds 2331da177e4SLinus Torvalds #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB66) 2341da177e4SLinus Torvalds struct alpha_machine_vector eb66_mv __initmv = { 2351da177e4SLinus Torvalds .vector_name = "EB66", 2361da177e4SLinus Torvalds DO_EV4_MMU, 2371da177e4SLinus Torvalds DO_DEFAULT_RTC, 2381da177e4SLinus Torvalds DO_LCA_IO, 2391da177e4SLinus Torvalds .machine_check = lca_machine_check, 2401da177e4SLinus Torvalds .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS, 2411da177e4SLinus Torvalds .min_io_address = DEFAULT_IO_BASE, 2421da177e4SLinus Torvalds .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE, 2431da177e4SLinus Torvalds 2441da177e4SLinus Torvalds .nr_irqs = 32, 2451da177e4SLinus Torvalds .device_interrupt = eb64p_device_interrupt, 2461da177e4SLinus Torvalds 2471da177e4SLinus Torvalds .init_arch = lca_init_arch, 2481da177e4SLinus Torvalds .init_irq = eb64p_init_irq, 2491da177e4SLinus Torvalds .init_rtc = common_init_rtc, 2501da177e4SLinus Torvalds .init_pci = common_init_pci, 2511da177e4SLinus Torvalds .pci_map_irq = eb64p_map_irq, 2521da177e4SLinus Torvalds .pci_swizzle = common_swizzle, 2531da177e4SLinus Torvalds }; 2541da177e4SLinus Torvalds ALIAS_MV(eb66) 2551da177e4SLinus Torvalds #endif 256