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