1 /* 2 * PCI Tower 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) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de) 9 */ 10 11 #include <linux/init.h> 12 #include <linux/interrupt.h> 13 #include <linux/pci.h> 14 #include <linux/serial_8250.h> 15 16 #include <asm/mc146818-time.h> 17 #include <asm/sni.h> 18 #include <asm/time.h> 19 #include <asm/irq_cpu.h> 20 21 22 #define PORT(_base,_irq) \ 23 { \ 24 .iobase = _base, \ 25 .irq = _irq, \ 26 .uartclk = 1843200, \ 27 .iotype = UPIO_PORT, \ 28 .flags = UPF_BOOT_AUTOCONF, \ 29 } 30 31 static struct plat_serial8250_port pcit_data[] = { 32 PORT(0x3f8, 0), 33 PORT(0x2f8, 3), 34 { }, 35 }; 36 37 static struct platform_device pcit_serial8250_device = { 38 .name = "serial8250", 39 .id = PLAT8250_DEV_PLATFORM, 40 .dev = { 41 .platform_data = pcit_data, 42 }, 43 }; 44 45 static struct plat_serial8250_port pcit_cplus_data[] = { 46 PORT(0x3f8, 4), 47 PORT(0x2f8, 3), 48 PORT(0x3e8, 4), 49 PORT(0x2e8, 3), 50 { }, 51 }; 52 53 static struct platform_device pcit_cplus_serial8250_device = { 54 .name = "serial8250", 55 .id = PLAT8250_DEV_PLATFORM, 56 .dev = { 57 .platform_data = pcit_cplus_data, 58 }, 59 }; 60 61 static struct resource sni_io_resource = { 62 .start = 0x00001000UL, 63 .end = 0x03bfffffUL, 64 .name = "PCIT IO MEM", 65 .flags = IORESOURCE_IO, 66 }; 67 68 static struct resource pcit_io_resources[] = { 69 { 70 .start = 0x00, 71 .end = 0x1f, 72 .name = "dma1", 73 .flags = IORESOURCE_BUSY 74 }, { 75 .start = 0x40, 76 .end = 0x5f, 77 .name = "timer", 78 .flags = IORESOURCE_BUSY 79 }, { 80 .start = 0x60, 81 .end = 0x6f, 82 .name = "keyboard", 83 .flags = IORESOURCE_BUSY 84 }, { 85 .start = 0x80, 86 .end = 0x8f, 87 .name = "dma page reg", 88 .flags = IORESOURCE_BUSY 89 }, { 90 .start = 0xc0, 91 .end = 0xdf, 92 .name = "dma2", 93 .flags = IORESOURCE_BUSY 94 }, { 95 .start = 0xcfc, 96 .end = 0xcff, 97 .name = "PCI config data", 98 .flags = IORESOURCE_BUSY 99 } 100 }; 101 102 static struct resource sni_mem_resource = { 103 .start = 0x10000000UL, 104 .end = 0xffffffffUL, 105 .name = "PCIT PCI MEM", 106 .flags = IORESOURCE_MEM 107 }; 108 109 /* 110 * The RM200/RM300 has a few holes in it's PCI/EISA memory address space used 111 * for other purposes. Be paranoid and allocate all of the before the PCI 112 * code gets a chance to to map anything else there ... 113 * 114 * This leaves the following areas available: 115 * 116 * 0x10000000 - 0x1009ffff (640kB) PCI/EISA/ISA Bus Memory 117 * 0x10100000 - 0x13ffffff ( 15MB) PCI/EISA/ISA Bus Memory 118 * 0x18000000 - 0x1fbfffff (124MB) PCI/EISA Bus Memory 119 * 0x1ff08000 - 0x1ffeffff (816kB) PCI/EISA Bus Memory 120 * 0xa0000000 - 0xffffffff (1.5GB) PCI/EISA Bus Memory 121 */ 122 static struct resource pcit_mem_resources[] = { 123 { 124 .start = 0x14000000, 125 .end = 0x17bfffff, 126 .name = "PCI IO", 127 .flags = IORESOURCE_BUSY 128 }, { 129 .start = 0x17c00000, 130 .end = 0x17ffffff, 131 .name = "Cache Replacement Area", 132 .flags = IORESOURCE_BUSY 133 }, { 134 .start = 0x180a0000, 135 .end = 0x180bffff, 136 .name = "Video RAM area", 137 .flags = IORESOURCE_BUSY 138 }, { 139 .start = 0x180c0000, 140 .end = 0x180fffff, 141 .name = "ISA Reserved", 142 .flags = IORESOURCE_BUSY 143 }, { 144 .start = 0x19000000, 145 .end = 0x1fbfffff, 146 .name = "PCI MEM", 147 .flags = IORESOURCE_BUSY 148 }, { 149 .start = 0x1fc00000, 150 .end = 0x1fc7ffff, 151 .name = "Boot PROM", 152 .flags = IORESOURCE_BUSY 153 }, { 154 .start = 0x1fc80000, 155 .end = 0x1fcfffff, 156 .name = "Diag PROM", 157 .flags = IORESOURCE_BUSY 158 }, { 159 .start = 0x1fd00000, 160 .end = 0x1fdfffff, 161 .name = "X-Bus", 162 .flags = IORESOURCE_BUSY 163 }, { 164 .start = 0x1fe00000, 165 .end = 0x1fefffff, 166 .name = "BIOS map", 167 .flags = IORESOURCE_BUSY 168 }, { 169 .start = 0x1ff00000, 170 .end = 0x1ff7ffff, 171 .name = "NVRAM / EEPROM", 172 .flags = IORESOURCE_BUSY 173 }, { 174 .start = 0x1fff0000, 175 .end = 0x1fffefff, 176 .name = "MAUI ASIC", 177 .flags = IORESOURCE_BUSY 178 }, { 179 .start = 0x1ffff000, 180 .end = 0x1fffffff, 181 .name = "MP Agent", 182 .flags = IORESOURCE_BUSY 183 }, { 184 .start = 0x20000000, 185 .end = 0x9fffffff, 186 .name = "Main Memory", 187 .flags = IORESOURCE_BUSY 188 } 189 }; 190 191 static void __init sni_pcit_resource_init(void) 192 { 193 int i; 194 195 /* request I/O space for devices used on all i[345]86 PCs */ 196 for (i = 0; i < ARRAY_SIZE(pcit_io_resources); i++) 197 request_resource(&ioport_resource, pcit_io_resources + i); 198 199 /* request mem space for pcimt-specific devices */ 200 for (i = 0; i < ARRAY_SIZE(pcit_mem_resources); i++) 201 request_resource(&sni_mem_resource, pcit_mem_resources + i); 202 203 ioport_resource.end = sni_io_resource.end; 204 } 205 206 207 extern struct pci_ops sni_pcit_ops; 208 209 static struct pci_controller sni_pcit_controller = { 210 .pci_ops = &sni_pcit_ops, 211 .mem_resource = &sni_mem_resource, 212 .mem_offset = 0x10000000UL, 213 .io_resource = &sni_io_resource, 214 .io_offset = 0x00000000UL 215 }; 216 217 static void enable_pcit_irq(unsigned int irq) 218 { 219 u32 mask = 1 << (irq - SNI_PCIT_INT_START + 24); 220 221 *(volatile u32 *)SNI_PCIT_INT_REG |= mask; 222 } 223 224 void disable_pcit_irq(unsigned int irq) 225 { 226 u32 mask = 1 << (irq - SNI_PCIT_INT_START + 24); 227 228 *(volatile u32 *)SNI_PCIT_INT_REG &= ~mask; 229 } 230 231 void end_pcit_irq(unsigned int irq) 232 { 233 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 234 enable_pcit_irq(irq); 235 } 236 237 static struct irq_chip pcit_irq_type = { 238 .typename = "PCIT", 239 .ack = disable_pcit_irq, 240 .mask = disable_pcit_irq, 241 .mask_ack = disable_pcit_irq, 242 .unmask = enable_pcit_irq, 243 .end = end_pcit_irq, 244 }; 245 246 static void pcit_hwint1(void) 247 { 248 u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG; 249 int irq; 250 251 clear_c0_status(IE_IRQ1); 252 irq = ffs((pending >> 16) & 0x7f); 253 254 if (likely(irq > 0)) 255 do_IRQ (irq + SNI_PCIT_INT_START - 1); 256 set_c0_status (IE_IRQ1); 257 } 258 259 static void pcit_hwint0(void) 260 { 261 u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG; 262 int irq; 263 264 clear_c0_status(IE_IRQ0); 265 irq = ffs((pending >> 16) & 0x7f); 266 267 if (likely(irq > 0)) 268 do_IRQ (irq + SNI_PCIT_INT_START - 1); 269 set_c0_status (IE_IRQ0); 270 } 271 272 static void sni_pcit_hwint(void) 273 { 274 u32 pending = (read_c0_cause() & read_c0_status()); 275 276 if (pending & C_IRQ1) 277 pcit_hwint1(); 278 else if (pending & C_IRQ2) 279 do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 4); 280 else if (pending & C_IRQ3) 281 do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 5); 282 else if (pending & C_IRQ5) 283 do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 7); 284 } 285 286 static void sni_pcit_hwint_cplus(void) 287 { 288 u32 pending = (read_c0_cause() & read_c0_status()); 289 290 if (pending & C_IRQ0) 291 pcit_hwint0(); 292 else if (pending & C_IRQ2) 293 do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 4); 294 else if (pending & C_IRQ3) 295 do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 5); 296 else if (pending & C_IRQ5) 297 do_IRQ (SNI_MIPS_IRQ_CPU_BASE + 7); 298 } 299 300 void __init sni_pcit_irq_init(void) 301 { 302 int i; 303 304 mips_cpu_irq_init(); 305 for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++) 306 set_irq_chip(i, &pcit_irq_type); 307 *(volatile u32 *)SNI_PCIT_INT_REG = 0; 308 sni_hwint = sni_pcit_hwint; 309 change_c0_status(ST0_IM, IE_IRQ1); 310 setup_irq (SNI_PCIT_INT_START + 6, &sni_isa_irq); 311 } 312 313 void __init sni_pcit_cplus_irq_init(void) 314 { 315 int i; 316 317 mips_cpu_irq_init(); 318 for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++) 319 set_irq_chip(i, &pcit_irq_type); 320 *(volatile u32 *)SNI_PCIT_INT_REG = 0; 321 sni_hwint = sni_pcit_hwint_cplus; 322 change_c0_status(ST0_IM, IE_IRQ0); 323 setup_irq (SNI_PCIT_INT_START + 6, &sni_isa_irq); 324 } 325 326 void sni_pcit_init(void) 327 { 328 sni_pcit_resource_init(); 329 rtc_mips_get_time = mc146818_get_cmos_time; 330 rtc_mips_set_time = mc146818_set_rtc_mmss; 331 board_time_init = sni_cpu_time_init; 332 #ifdef CONFIG_PCI 333 register_pci_controller(&sni_pcit_controller); 334 #endif 335 } 336 337 static int __init snirm_pcit_setup_devinit(void) 338 { 339 switch (sni_brd_type) { 340 case SNI_BRD_PCI_TOWER: 341 platform_device_register(&pcit_serial8250_device); 342 break; 343 344 case SNI_BRD_PCI_TOWER_CPLUS: 345 platform_device_register(&pcit_cplus_serial8250_device); 346 break; 347 } 348 return 0; 349 } 350 351 device_initcall(snirm_pcit_setup_devinit); 352