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(struct irq_data *d) 160 { 161 u32 mask = 1 << (d->irq - SNI_PCIT_INT_START + 24); 162 163 *(volatile u32 *)SNI_PCIT_INT_REG |= mask; 164 } 165 166 void disable_pcit_irq(struct irq_data *d) 167 { 168 u32 mask = 1 << (d->irq - SNI_PCIT_INT_START + 24); 169 170 *(volatile u32 *)SNI_PCIT_INT_REG &= ~mask; 171 } 172 173 static struct irq_chip pcit_irq_type = { 174 .name = "PCIT", 175 .irq_mask = disable_pcit_irq, 176 .irq_unmask = enable_pcit_irq, 177 }; 178 179 static void pcit_hwint1(void) 180 { 181 u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG; 182 int irq; 183 184 clear_c0_status(IE_IRQ1); 185 irq = ffs((pending >> 16) & 0x7f); 186 187 if (likely(irq > 0)) 188 do_IRQ(irq + SNI_PCIT_INT_START - 1); 189 set_c0_status(IE_IRQ1); 190 } 191 192 static void pcit_hwint0(void) 193 { 194 u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG; 195 int irq; 196 197 clear_c0_status(IE_IRQ0); 198 irq = ffs((pending >> 16) & 0x3f); 199 200 if (likely(irq > 0)) 201 do_IRQ(irq + SNI_PCIT_INT_START - 1); 202 set_c0_status(IE_IRQ0); 203 } 204 205 static void sni_pcit_hwint(void) 206 { 207 u32 pending = read_c0_cause() & read_c0_status(); 208 209 if (pending & C_IRQ1) 210 pcit_hwint1(); 211 else if (pending & C_IRQ2) 212 do_IRQ(MIPS_CPU_IRQ_BASE + 4); 213 else if (pending & C_IRQ3) 214 do_IRQ(MIPS_CPU_IRQ_BASE + 5); 215 else if (pending & C_IRQ5) 216 do_IRQ(MIPS_CPU_IRQ_BASE + 7); 217 } 218 219 static void sni_pcit_hwint_cplus(void) 220 { 221 u32 pending = read_c0_cause() & read_c0_status(); 222 223 if (pending & C_IRQ0) 224 pcit_hwint0(); 225 else if (pending & C_IRQ1) 226 do_IRQ(MIPS_CPU_IRQ_BASE + 3); 227 else if (pending & C_IRQ2) 228 do_IRQ(MIPS_CPU_IRQ_BASE + 4); 229 else if (pending & C_IRQ3) 230 do_IRQ(MIPS_CPU_IRQ_BASE + 5); 231 else if (pending & C_IRQ5) 232 do_IRQ(MIPS_CPU_IRQ_BASE + 7); 233 } 234 235 void __init sni_pcit_irq_init(void) 236 { 237 int i; 238 239 mips_cpu_irq_init(); 240 for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++) 241 irq_set_chip_and_handler(i, &pcit_irq_type, handle_level_irq); 242 *(volatile u32 *)SNI_PCIT_INT_REG = 0; 243 sni_hwint = sni_pcit_hwint; 244 change_c0_status(ST0_IM, IE_IRQ1); 245 setup_irq(SNI_PCIT_INT_START + 6, &sni_isa_irq); 246 } 247 248 void __init sni_pcit_cplus_irq_init(void) 249 { 250 int i; 251 252 mips_cpu_irq_init(); 253 for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++) 254 irq_set_chip_and_handler(i, &pcit_irq_type, handle_level_irq); 255 *(volatile u32 *)SNI_PCIT_INT_REG = 0x40000000; 256 sni_hwint = sni_pcit_hwint_cplus; 257 change_c0_status(ST0_IM, IE_IRQ0); 258 setup_irq(MIPS_CPU_IRQ_BASE + 3, &sni_isa_irq); 259 } 260 261 void __init sni_pcit_init(void) 262 { 263 ioport_resource.end = sni_io_resource.end; 264 #ifdef CONFIG_PCI 265 PCIBIOS_MIN_IO = 0x9000; 266 register_pci_controller(&sni_pcit_controller); 267 #endif 268 sni_pcit_resource_init(); 269 } 270 271 static int __init snirm_pcit_setup_devinit(void) 272 { 273 switch (sni_brd_type) { 274 case SNI_BRD_PCI_TOWER: 275 platform_device_register(&pcit_serial8250_device); 276 platform_device_register(&pcit_cmos_device); 277 platform_device_register(&pcit_pcspeaker_pdev); 278 break; 279 280 case SNI_BRD_PCI_TOWER_CPLUS: 281 platform_device_register(&pcit_cplus_serial8250_device); 282 platform_device_register(&pcit_cmos_device); 283 platform_device_register(&pcit_pcspeaker_pdev); 284 break; 285 } 286 return 0; 287 } 288 289 device_initcall(snirm_pcit_setup_devinit); 290