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 25static 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 */ 50static 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 78static struct plat_serial8250_port pcimt_data[] = { 79 PORT(0x3f8, 4), 80 PORT(0x2f8, 3), 81 { }, 82}; 83 84static struct platform_device pcimt_serial8250_device = { 85 .name = "serial8250", 86 .id = PLAT8250_DEV_PLATFORM, 87 .dev = { 88 .platform_data = pcimt_data, 89 }, 90}; 91 92static 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 105static 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 112static struct resource sni_io_resource = { 113 .start = 0x00000000UL, 114 .end = 0x03bfffffUL, 115 .name = "PCIMT IO MEM", 116 .flags = IORESOURCE_IO, 117}; 118 119static 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 153static 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 166static struct resource sni_mem_resource = { 167 .start = 0x18000000UL, 168 .end = 0x1fbfffffUL, 169 .name = "PCIMT PCI MEM", 170 .flags = IORESOURCE_MEM 171}; 172 173static 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 185extern struct pci_ops sni_pcimt_ops; 186 187static 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 196static 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 203void 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 210static 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 216static struct irq_chip pcimt_irq_type = { 217 .name = "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 */ 229static 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 */ 239static 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 */ 269static 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 282static 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 299void __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_and_handler(i, &pcimt_irq_type, handle_level_irq); 308 sni_hwint = sni_pcimt_hwint; 309 change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ3); 310} 311 312void __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 324static 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 338device_initcall(snirm_pcimt_setup_devinit); 339