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