Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | /* * linux/arch/alpha/kernel/sys_rx164.c * * Copyright (C) 1995 David A Rusling * Copyright (C) 1996 Jay A Estabrook * Copyright (C) 1998, 1999 Richard Henderson * * Code supporting the RX164 (PCA56+POLARIS). */ #include <linux/kernel.h> #include <linux/types.h> #include <linux/mm.h> #include <linux/sched.h> #include <linux/pci.h> #include <linux/init.h> #include <asm/ptrace.h> #include <asm/system.h> #include <asm/dma.h> #include <asm/irq.h> #include <asm/bitops.h> #include <asm/mmu_context.h> #include <asm/io.h> #include <asm/pgtable.h> #include <asm/core_polaris.h> #include "proto.h" #include "irq_impl.h" #include "pci_impl.h" #include "machvec_impl.h" /* Note mask bit is true for ENABLED irqs. */ static unsigned long cached_irq_mask; /* Bus 0, Device 0. Nothing else matters, since we invoke the POLARIS routines directly. */ static struct pci_dev rx164_system; static inline void rx164_update_irq_hw(unsigned long mask) { unsigned int temp; polaris_write_config_dword(&rx164_system, 0x74, mask); polaris_read_config_dword(&rx164_system, 0x74, &temp); } static inline void rx164_enable_irq(unsigned int irq) { rx164_update_irq_hw(cached_irq_mask |= 1UL << (irq - 16)); } static void rx164_disable_irq(unsigned int irq) { rx164_update_irq_hw(cached_irq_mask &= ~(1UL << (irq - 16))); } static unsigned int rx164_startup_irq(unsigned int irq) { rx164_enable_irq(irq); return 0; } static void rx164_end_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) rx164_enable_irq(irq); } static struct hw_interrupt_type rx164_irq_type = { typename: "RX164", startup: rx164_startup_irq, shutdown: rx164_disable_irq, enable: rx164_enable_irq, disable: rx164_disable_irq, ack: rx164_disable_irq, end: rx164_end_irq, }; static void rx164_device_interrupt(unsigned long vector, struct pt_regs *regs) { unsigned int temp; unsigned long pld; long i; /* Read the interrupt summary register. On Polaris, this is the DIRR register in PCI config space (offset 0x84). */ polaris_read_config_dword(&rx164_system, 0x84, &temp); pld = temp; /* * Now for every possible bit set, work through them and call * the appropriate interrupt handler. */ while (pld) { i = ffz(~pld); pld &= pld - 1; /* clear least bit set */ if (i == 20) { isa_no_iack_sc_device_interrupt(vector, regs); } else { handle_irq(16+i, regs); } } } static void __init rx164_init_irq(void) { long i; rx164_update_irq_hw(0); for (i = 16; i < 40; ++i) { irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL; irq_desc[i].handler = &rx164_irq_type; } init_i8259a_irqs(); common_init_isa_dma(); setup_irq(16+20, &isa_cascade_irqaction); } /* * The RX164 changed its interrupt routing between pass1 and pass2... * * PASS1: * * Slot IDSEL INTA INTB INTC INTD * 0 6 5 10 15 20 * 1 7 4 9 14 19 * 2 5 3 8 13 18 * 3 9 2 7 12 17 * 4 10 1 6 11 16 * * PASS2: * Slot IDSEL INTA INTB INTC INTD * 0 5 1 7 12 17 * 1 6 2 8 13 18 * 2 8 3 9 14 19 * 3 9 4 10 15 20 * 4 10 5 11 16 6 * */ /* * IdSel * 5 32 bit PCI option slot 0 * 6 64 bit PCI option slot 1 * 7 PCI-ISA bridge * 7 64 bit PCI option slot 2 * 9 32 bit PCI option slot 3 * 10 PCI-PCI bridge * */ static int __init rx164_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { #if 0 static char irq_tab_pass1[6][5] __initdata = { /*INT INTA INTB INTC INTD */ { 16+3, 16+3, 16+8, 16+13, 16+18}, /* IdSel 5, slot 2 */ { 16+5, 16+5, 16+10, 16+15, 16+20}, /* IdSel 6, slot 0 */ { 16+4, 16+4, 16+9, 16+14, 16+19}, /* IdSel 7, slot 1 */ { -1, -1, -1, -1, -1}, /* IdSel 8, PCI/ISA bridge */ { 16+2, 16+2, 16+7, 16+12, 16+17}, /* IdSel 9, slot 3 */ { 16+1, 16+1, 16+6, 16+11, 16+16}, /* IdSel 10, slot 4 */ }; #else static char irq_tab[6][5] __initdata = { /*INT INTA INTB INTC INTD */ { 16+0, 16+0, 16+6, 16+11, 16+16}, /* IdSel 5, slot 0 */ { 16+1, 16+1, 16+7, 16+12, 16+17}, /* IdSel 6, slot 1 */ { -1, -1, -1, -1, -1}, /* IdSel 7, PCI/ISA bridge */ { 16+2, 16+2, 16+8, 16+13, 16+18}, /* IdSel 8, slot 2 */ { 16+3, 16+3, 16+9, 16+14, 16+19}, /* IdSel 9, slot 3 */ { 16+4, 16+4, 16+10, 16+15, 16+5}, /* IdSel 10, PCI-PCI */ }; #endif const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5; /* JRP - Need to figure out how to distinguish pass1 from pass2, and use the correct table. */ return COMMON_TABLE_LOOKUP; } /* * The System Vector */ struct alpha_machine_vector rx164_mv __initmv = { vector_name: "RX164", DO_EV5_MMU, DO_DEFAULT_RTC, DO_POLARIS_IO, DO_POLARIS_BUS, machine_check: polaris_machine_check, max_dma_address: ALPHA_MAX_DMA_ADDRESS, min_io_address: DEFAULT_IO_BASE, min_mem_address: DEFAULT_MEM_BASE, nr_irqs: 40, device_interrupt: rx164_device_interrupt, init_arch: polaris_init_arch, init_irq: rx164_init_irq, init_rtc: common_init_rtc, init_pci: common_init_pci, kill_arch: NULL, pci_map_irq: rx164_map_irq, pci_swizzle: common_swizzle, }; ALIAS_MV(rx164) |