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/irq.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/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, 0), 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 pcit_cmos_rsrc[] = { 62 { 63 .start = 0x70, 64 .end = 0x71, 65 .flags = IORESOURCE_IO 66 }, 67 { 68 .start = 8, 69 .end = 8, 70 .flags = IORESOURCE_IRQ 71 } 72 }; 73 74 static struct platform_device pcit_cmos_device = { 75 .name = "rtc_cmos", 76 .num_resources = ARRAY_SIZE(pcit_cmos_rsrc), 77 .resource = pcit_cmos_rsrc 78 }; 79 80 static struct platform_device pcit_pcspeaker_pdev = { 81 .name = "pcspkr", 82 .id = -1, 83 }; 84 85 static struct resource sni_io_resource = { 86 .start = 0x00000000UL, 87 .end = 0x03bfffffUL, 88 .name = "PCIT IO", 89 .flags = IORESOURCE_IO, 90 }; 91 92 static struct resource pcit_io_resources[] = { 93 { 94 .start = 0x00, 95 .end = 0x1f, 96 .name = "dma1", 97 .flags = IORESOURCE_BUSY 98 }, { 99 .start = 0x40, 100 .end = 0x5f, 101 .name = "timer", 102 .flags = IORESOURCE_BUSY 103 }, { 104 .start = 0x60, 105 .end = 0x6f, 106 .name = "keyboard", 107 .flags = IORESOURCE_BUSY 108 }, { 109 .start = 0x80, 110 .end = 0x8f, 111 .name = "dma page reg", 112 .flags = IORESOURCE_BUSY 113 }, { 114 .start = 0xc0, 115 .end = 0xdf, 116 .name = "dma2", 117 .flags = IORESOURCE_BUSY 118 }, { 119 .start = 0xcf8, 120 .end = 0xcfb, 121 .name = "PCI config addr", 122 .flags = IORESOURCE_BUSY 123 }, { 124 .start = 0xcfc, 125 .end = 0xcff, 126 .name = "PCI config data", 127 .flags = IORESOURCE_BUSY 128 } 129 }; 130 131 static struct resource sni_mem_resource = { 132 .start = 0x18000000UL, 133 .end = 0x1fbfffffUL, 134 .name = "PCIT PCI MEM", 135 .flags = IORESOURCE_MEM 136 }; 137 138 static void __init sni_pcit_resource_init(void) 139 { 140 int i; 141 142 /* request I/O space for devices used on all i[345]86 PCs */ 143 for (i = 0; i < ARRAY_SIZE(pcit_io_resources); i++) 144 request_resource(&sni_io_resource, pcit_io_resources + i); 145 } 146 147 148 extern struct pci_ops sni_pcit_ops; 149 150 static struct pci_controller sni_pcit_controller = { 151 .pci_ops = &sni_pcit_ops, 152 .mem_resource = &sni_mem_resource, 153 .mem_offset = 0x00000000UL, 154 .io_resource = &sni_io_resource, 155 .io_offset = 0x00000000UL, 156 .io_map_base = SNI_PORT_BASE 157 }; 158 159 static void enable_pcit_irq(unsigned int irq) 160 { 161 u32 mask = 1 << (irq - SNI_PCIT_INT_START + 24); 162 163 *(volatile u32 *)SNI_PCIT_INT_REG |= mask; 164 } 165 166 void disable_pcit_irq(unsigned int irq) 167 { 168 u32 mask = 1 << (irq - SNI_PCIT_INT_START + 24); 169 170 *(volatile u32 *)SNI_PCIT_INT_REG &= ~mask; 171 } 172 173 void end_pcit_irq(unsigned int irq) 174 { 175 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 176 enable_pcit_irq(irq); 177 } 178 179 static struct irq_chip pcit_irq_type = { 180 .name = "PCIT", 181 .ack = disable_pcit_irq, 182 .mask = disable_pcit_irq, 183 .mask_ack = disable_pcit_irq, 184 .unmask = enable_pcit_irq, 185 .end = end_pcit_irq, 186 }; 187 188 static void pcit_hwint1(void) 189 { 190 u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG; 191 int irq; 192 193 clear_c0_status(IE_IRQ1); 194 irq = ffs((pending >> 16) & 0x7f); 195 196 if (likely(irq > 0)) 197 do_IRQ(irq + SNI_PCIT_INT_START - 1); 198 set_c0_status(IE_IRQ1); 199 } 200 201 static void pcit_hwint0(void) 202 { 203 u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG; 204 int irq; 205 206 clear_c0_status(IE_IRQ0); 207 irq = ffs((pending >> 16) & 0x3f); 208 209 if (likely(irq > 0)) 210 do_IRQ(irq + SNI_PCIT_INT_START - 1); 211 set_c0_status(IE_IRQ0); 212 } 213 214 static void sni_pcit_hwint(void) 215 { 216 u32 pending = read_c0_cause() & read_c0_status(); 217 218 if (pending & C_IRQ1) 219 pcit_hwint1(); 220 else if (pending & C_IRQ2) 221 do_IRQ(MIPS_CPU_IRQ_BASE + 4); 222 else if (pending & C_IRQ3) 223 do_IRQ(MIPS_CPU_IRQ_BASE + 5); 224 else if (pending & C_IRQ5) 225 do_IRQ(MIPS_CPU_IRQ_BASE + 7); 226 } 227 228 static void sni_pcit_hwint_cplus(void) 229 { 230 u32 pending = read_c0_cause() & read_c0_status(); 231 232 if (pending & C_IRQ0) 233 pcit_hwint0(); 234 else if (pending & C_IRQ1) 235 do_IRQ(MIPS_CPU_IRQ_BASE + 3); 236 else if (pending & C_IRQ2) 237 do_IRQ(MIPS_CPU_IRQ_BASE + 4); 238 else if (pending & C_IRQ3) 239 do_IRQ(MIPS_CPU_IRQ_BASE + 5); 240 else if (pending & C_IRQ5) 241 do_IRQ(MIPS_CPU_IRQ_BASE + 7); 242 } 243 244 void __init sni_pcit_irq_init(void) 245 { 246 int i; 247 248 mips_cpu_irq_init(); 249 for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++) 250 set_irq_chip_and_handler(i, &pcit_irq_type, handle_level_irq); 251 *(volatile u32 *)SNI_PCIT_INT_REG = 0; 252 sni_hwint = sni_pcit_hwint; 253 change_c0_status(ST0_IM, IE_IRQ1); 254 setup_irq(SNI_PCIT_INT_START + 6, &sni_isa_irq); 255 } 256 257 void __init sni_pcit_cplus_irq_init(void) 258 { 259 int i; 260 261 mips_cpu_irq_init(); 262 for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++) 263 set_irq_chip_and_handler(i, &pcit_irq_type, handle_level_irq); 264 *(volatile u32 *)SNI_PCIT_INT_REG = 0x40000000; 265 sni_hwint = sni_pcit_hwint_cplus; 266 change_c0_status(ST0_IM, IE_IRQ0); 267 setup_irq(MIPS_CPU_IRQ_BASE + 3, &sni_isa_irq); 268 } 269 270 void __init sni_pcit_init(void) 271 { 272 ioport_resource.end = sni_io_resource.end; 273 #ifdef CONFIG_PCI 274 PCIBIOS_MIN_IO = 0x9000; 275 register_pci_controller(&sni_pcit_controller); 276 #endif 277 sni_pcit_resource_init(); 278 } 279 280 static int __init snirm_pcit_setup_devinit(void) 281 { 282 switch (sni_brd_type) { 283 case SNI_BRD_PCI_TOWER: 284 platform_device_register(&pcit_serial8250_device); 285 platform_device_register(&pcit_cmos_device); 286 platform_device_register(&pcit_pcspeaker_pdev); 287 break; 288 289 case SNI_BRD_PCI_TOWER_CPLUS: 290 platform_device_register(&pcit_cplus_serial8250_device); 291 platform_device_register(&pcit_cmos_device); 292 platform_device_register(&pcit_pcspeaker_pdev); 293 break; 294 } 295 return 0; 296 } 297 298 device_initcall(snirm_pcit_setup_devinit); 299