1 /* 2 * PCIMT specific code 3 * 4 * This file is subject to the terms and conditions of the GNU General Public 5 * License. See the file "COPYING" in the main directory of this archive 6 * for more details. 7 * 8 * Copyright (C) 1996, 97, 98, 2000, 03, 04, 06 Ralf Baechle (ralf@linux-mips.org) 9 * Copyright (C) 2006,2007 Thomas Bogendoerfer (tsbogend@alpha.franken.de) 10 */ 11 12 #include <linux/init.h> 13 #include <linux/interrupt.h> 14 #include <linux/pci.h> 15 #include <linux/serial_8250.h> 16 17 #include <asm/sni.h> 18 #include <asm/time.h> 19 #include <asm/i8259.h> 20 #include <asm/irq_cpu.h> 21 22 #define cacheconf (*(volatile unsigned int *)PCIMT_CACHECONF) 23 #define invspace (*(volatile unsigned int *)PCIMT_INVSPACE) 24 25 static void __init sni_pcimt_sc_init(void) 26 { 27 unsigned int scsiz, sc_size; 28 29 scsiz = cacheconf & 7; 30 if (scsiz == 0) { 31 printk("Second level cache is deactived.\n"); 32 return; 33 } 34 if (scsiz >= 6) { 35 printk("Invalid second level cache size configured, " 36 "deactivating second level cache.\n"); 37 cacheconf = 0; 38 return; 39 } 40 41 sc_size = 128 << scsiz; 42 printk("%dkb second level cache detected, deactivating.\n", sc_size); 43 cacheconf = 0; 44 } 45 46 47 /* 48 * A bit more gossip about the iron we're running on ... 49 */ 50 static inline void sni_pcimt_detect(void) 51 { 52 char boardtype[80]; 53 unsigned char csmsr; 54 char *p = boardtype; 55 unsigned int asic; 56 57 csmsr = *(volatile unsigned char *)PCIMT_CSMSR; 58 59 p += sprintf(p, "%s PCI", (csmsr & 0x80) ? "RM200" : "RM300"); 60 if ((csmsr & 0x80) == 0) 61 p += sprintf(p, ", board revision %s", 62 (csmsr & 0x20) ? "D" : "C"); 63 asic = csmsr & 0x80; 64 asic = (csmsr & 0x08) ? asic : !asic; 65 p += sprintf(p, ", ASIC PCI Rev %s", asic ? "1.0" : "1.1"); 66 printk("%s.\n", boardtype); 67 } 68 69 #define PORT(_base,_irq) \ 70 { \ 71 .iobase = _base, \ 72 .irq = _irq, \ 73 .uartclk = 1843200, \ 74 .iotype = UPIO_PORT, \ 75 .flags = UPF_BOOT_AUTOCONF, \ 76 } 77 78 static struct plat_serial8250_port pcimt_data[] = { 79 PORT(0x3f8, 4), 80 PORT(0x2f8, 3), 81 { }, 82 }; 83 84 static struct platform_device pcimt_serial8250_device = { 85 .name = "serial8250", 86 .id = PLAT8250_DEV_PLATFORM, 87 .dev = { 88 .platform_data = pcimt_data, 89 }, 90 }; 91 92 static struct resource pcimt_cmos_rsrc[] = { 93 { 94 .start = 0x70, 95 .end = 0x71, 96 .flags = IORESOURCE_IO 97 }, 98 { 99 .start = 8, 100 .end = 8, 101 .flags = IORESOURCE_IRQ 102 } 103 }; 104 105 static struct platform_device pcimt_cmos_device = { 106 .name = "rtc_cmos", 107 .num_resources = ARRAY_SIZE(pcimt_cmos_rsrc), 108 .resource = pcimt_cmos_rsrc 109 }; 110 111 112 static struct resource sni_io_resource = { 113 .start = 0x00000000UL, 114 .end = 0x03bfffffUL, 115 .name = "PCIMT IO MEM", 116 .flags = IORESOURCE_IO, 117 }; 118 119 static struct resource pcimt_io_resources[] = { 120 { 121 .start = 0x00, 122 .end = 0x1f, 123 .name = "dma1", 124 .flags = IORESOURCE_BUSY 125 }, { 126 .start = 0x40, 127 .end = 0x5f, 128 .name = "timer", 129 .flags = IORESOURCE_BUSY 130 }, { 131 .start = 0x60, 132 .end = 0x6f, 133 .name = "keyboard", 134 .flags = IORESOURCE_BUSY 135 }, { 136 .start = 0x80, 137 .end = 0x8f, 138 .name = "dma page reg", 139 .flags = IORESOURCE_BUSY 140 }, { 141 .start = 0xc0, 142 .end = 0xdf, 143 .name = "dma2", 144 .flags = IORESOURCE_BUSY 145 }, { 146 .start = 0xcfc, 147 .end = 0xcff, 148 .name = "PCI config data", 149 .flags = IORESOURCE_BUSY 150 } 151 }; 152 153 static struct resource pcimt_mem_resources[] = { 154 { 155 /* 156 * this region should only be 4 bytes long, 157 * but it's 16MB on all RM300C I've checked 158 */ 159 .start = 0x1a000000, 160 .end = 0x1affffff, 161 .name = "PCI INT ACK", 162 .flags = IORESOURCE_BUSY 163 } 164 }; 165 166 static struct resource sni_mem_resource = { 167 .start = 0x18000000UL, 168 .end = 0x1fbfffffUL, 169 .name = "PCIMT PCI MEM", 170 .flags = IORESOURCE_MEM 171 }; 172 173 static void __init sni_pcimt_resource_init(void) 174 { 175 int i; 176 177 /* request I/O space for devices used on all i[345]86 PCs */ 178 for (i = 0; i < ARRAY_SIZE(pcimt_io_resources); i++) 179 request_resource(&sni_io_resource, pcimt_io_resources + i); 180 /* request MEM space for devices used on all i[345]86 PCs */ 181 for (i = 0; i < ARRAY_SIZE(pcimt_mem_resources); i++) 182 request_resource(&sni_mem_resource, pcimt_mem_resources + i); 183 } 184 185 extern struct pci_ops sni_pcimt_ops; 186 187 static struct pci_controller sni_controller = { 188 .pci_ops = &sni_pcimt_ops, 189 .mem_resource = &sni_mem_resource, 190 .mem_offset = 0x00000000UL, 191 .io_resource = &sni_io_resource, 192 .io_offset = 0x00000000UL, 193 .io_map_base = SNI_PORT_BASE 194 }; 195 196 static void enable_pcimt_irq(unsigned int irq) 197 { 198 unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2); 199 200 *(volatile u8 *) PCIMT_IRQSEL |= mask; 201 } 202 203 void disable_pcimt_irq(unsigned int irq) 204 { 205 unsigned int mask = ~(1 << (irq - PCIMT_IRQ_INT2)); 206 207 *(volatile u8 *) PCIMT_IRQSEL &= mask; 208 } 209 210 static void end_pcimt_irq(unsigned int irq) 211 { 212 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 213 enable_pcimt_irq(irq); 214 } 215 216 static struct irq_chip pcimt_irq_type = { 217 .typename = "PCIMT", 218 .ack = disable_pcimt_irq, 219 .mask = disable_pcimt_irq, 220 .mask_ack = disable_pcimt_irq, 221 .unmask = enable_pcimt_irq, 222 .end = end_pcimt_irq, 223 }; 224 225 /* 226 * hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug 227 * button interrupts. Later ... 228 */ 229 static void pcimt_hwint0(void) 230 { 231 panic("Received int0 but no handler yet ..."); 232 } 233 234 /* 235 * hwint 1 deals with EISA and SCSI interrupts, 236 * 237 * The EISA_INT bit in CSITPEND is high active, all others are low active. 238 */ 239 static void pcimt_hwint1(void) 240 { 241 u8 pend = *(volatile char *)PCIMT_CSITPEND; 242 unsigned long flags; 243 244 if (pend & IT_EISA) { 245 int irq; 246 /* 247 * Note: ASIC PCI's builtin interrupt acknowledge feature is 248 * broken. Using it may result in loss of some or all i8259 249 * interrupts, so don't use PCIMT_INT_ACKNOWLEDGE ... 250 */ 251 irq = i8259_irq(); 252 if (unlikely(irq < 0)) 253 return; 254 255 do_IRQ(irq); 256 } 257 258 if (!(pend & IT_SCSI)) { 259 flags = read_c0_status(); 260 clear_c0_status(ST0_IM); 261 do_IRQ(PCIMT_IRQ_SCSI); 262 write_c0_status(flags); 263 } 264 } 265 266 /* 267 * hwint 3 should deal with the PCI A - D interrupts, 268 */ 269 static void pcimt_hwint3(void) 270 { 271 u8 pend = *(volatile char *)PCIMT_CSITPEND; 272 int irq; 273 274 pend &= (IT_INTA | IT_INTB | IT_INTC | IT_INTD); 275 pend ^= (IT_INTA | IT_INTB | IT_INTC | IT_INTD); 276 clear_c0_status(IE_IRQ3); 277 irq = PCIMT_IRQ_INT2 + ffs(pend) - 1; 278 do_IRQ(irq); 279 set_c0_status(IE_IRQ3); 280 } 281 282 static void sni_pcimt_hwint(void) 283 { 284 u32 pending = read_c0_cause() & read_c0_status(); 285 286 if (pending & C_IRQ5) 287 do_IRQ(MIPS_CPU_IRQ_BASE + 7); 288 else if (pending & C_IRQ4) 289 do_IRQ(MIPS_CPU_IRQ_BASE + 6); 290 else if (pending & C_IRQ3) 291 pcimt_hwint3(); 292 else if (pending & C_IRQ1) 293 pcimt_hwint1(); 294 else if (pending & C_IRQ0) { 295 pcimt_hwint0(); 296 } 297 } 298 299 void __init sni_pcimt_irq_init(void) 300 { 301 int i; 302 303 *(volatile u8 *) PCIMT_IRQSEL = IT_ETH | IT_EISA; 304 mips_cpu_irq_init(); 305 /* Actually we've got more interrupts to handle ... */ 306 for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_SCSI; i++) 307 set_irq_chip(i, &pcimt_irq_type); 308 sni_hwint = sni_pcimt_hwint; 309 change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ3); 310 } 311 312 void __init sni_pcimt_init(void) 313 { 314 sni_pcimt_detect(); 315 sni_pcimt_sc_init(); 316 ioport_resource.end = sni_io_resource.end; 317 #ifdef CONFIG_PCI 318 PCIBIOS_MIN_IO = 0x9000; 319 register_pci_controller(&sni_controller); 320 #endif 321 sni_pcimt_resource_init(); 322 } 323 324 static int __init snirm_pcimt_setup_devinit(void) 325 { 326 switch (sni_brd_type) { 327 case SNI_BRD_PCI_MTOWER: 328 case SNI_BRD_PCI_DESKTOP: 329 case SNI_BRD_PCI_MTOWER_CPLUS: 330 platform_device_register(&pcimt_serial8250_device); 331 platform_device_register(&pcimt_cmos_device); 332 break; 333 } 334 335 return 0; 336 } 337 338 device_initcall(snirm_pcimt_setup_devinit); 339