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 void __init sni_pcit_resource_init(void) 132 { 133 int i; 134 135 /* request I/O space for devices used on all i[345]86 PCs */ 136 for (i = 0; i < ARRAY_SIZE(pcit_io_resources); i++) 137 request_resource(&sni_io_resource, pcit_io_resources + i); 138 } 139 140 141 extern struct pci_ops sni_pcit_ops; 142 143 #ifdef CONFIG_PCI 144 static struct resource sni_mem_resource = { 145 .start = 0x18000000UL, 146 .end = 0x1fbfffffUL, 147 .name = "PCIT PCI MEM", 148 .flags = IORESOURCE_MEM 149 }; 150 151 static struct pci_controller sni_pcit_controller = { 152 .pci_ops = &sni_pcit_ops, 153 .mem_resource = &sni_mem_resource, 154 .mem_offset = 0x00000000UL, 155 .io_resource = &sni_io_resource, 156 .io_offset = 0x00000000UL, 157 .io_map_base = SNI_PORT_BASE 158 }; 159 #endif /* CONFIG_PCI */ 160 161 static void enable_pcit_irq(struct irq_data *d) 162 { 163 u32 mask = 1 << (d->irq - SNI_PCIT_INT_START + 24); 164 165 *(volatile u32 *)SNI_PCIT_INT_REG |= mask; 166 } 167 168 void disable_pcit_irq(struct irq_data *d) 169 { 170 u32 mask = 1 << (d->irq - SNI_PCIT_INT_START + 24); 171 172 *(volatile u32 *)SNI_PCIT_INT_REG &= ~mask; 173 } 174 175 static struct irq_chip pcit_irq_type = { 176 .name = "PCIT", 177 .irq_mask = disable_pcit_irq, 178 .irq_unmask = enable_pcit_irq, 179 }; 180 181 static void pcit_hwint1(void) 182 { 183 u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG; 184 int irq; 185 186 clear_c0_status(IE_IRQ1); 187 irq = ffs((pending >> 16) & 0x7f); 188 189 if (likely(irq > 0)) 190 do_IRQ(irq + SNI_PCIT_INT_START - 1); 191 set_c0_status(IE_IRQ1); 192 } 193 194 static void pcit_hwint0(void) 195 { 196 u32 pending = *(volatile u32 *)SNI_PCIT_INT_REG; 197 int irq; 198 199 clear_c0_status(IE_IRQ0); 200 irq = ffs((pending >> 16) & 0x3f); 201 202 if (likely(irq > 0)) 203 do_IRQ(irq + SNI_PCIT_INT_START - 1); 204 set_c0_status(IE_IRQ0); 205 } 206 207 static void sni_pcit_hwint(void) 208 { 209 u32 pending = read_c0_cause() & read_c0_status(); 210 211 if (pending & C_IRQ1) 212 pcit_hwint1(); 213 else if (pending & C_IRQ2) 214 do_IRQ(MIPS_CPU_IRQ_BASE + 4); 215 else if (pending & C_IRQ3) 216 do_IRQ(MIPS_CPU_IRQ_BASE + 5); 217 else if (pending & C_IRQ5) 218 do_IRQ(MIPS_CPU_IRQ_BASE + 7); 219 } 220 221 static void sni_pcit_hwint_cplus(void) 222 { 223 u32 pending = read_c0_cause() & read_c0_status(); 224 225 if (pending & C_IRQ0) 226 pcit_hwint0(); 227 else if (pending & C_IRQ1) 228 do_IRQ(MIPS_CPU_IRQ_BASE + 3); 229 else if (pending & C_IRQ2) 230 do_IRQ(MIPS_CPU_IRQ_BASE + 4); 231 else if (pending & C_IRQ3) 232 do_IRQ(MIPS_CPU_IRQ_BASE + 5); 233 else if (pending & C_IRQ5) 234 do_IRQ(MIPS_CPU_IRQ_BASE + 7); 235 } 236 237 void __init sni_pcit_irq_init(void) 238 { 239 int i; 240 241 mips_cpu_irq_init(); 242 for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++) 243 irq_set_chip_and_handler(i, &pcit_irq_type, handle_level_irq); 244 *(volatile u32 *)SNI_PCIT_INT_REG = 0; 245 sni_hwint = sni_pcit_hwint; 246 change_c0_status(ST0_IM, IE_IRQ1); 247 if (request_irq(SNI_PCIT_INT_START + 6, sni_isa_irq_handler, 0, "ISA", 248 NULL)) 249 pr_err("Failed to register ISA interrupt\n"); 250 } 251 252 void __init sni_pcit_cplus_irq_init(void) 253 { 254 int i; 255 256 mips_cpu_irq_init(); 257 for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++) 258 irq_set_chip_and_handler(i, &pcit_irq_type, handle_level_irq); 259 *(volatile u32 *)SNI_PCIT_INT_REG = 0x40000000; 260 sni_hwint = sni_pcit_hwint_cplus; 261 change_c0_status(ST0_IM, IE_IRQ0); 262 if (request_irq(MIPS_CPU_IRQ_BASE + 3, sni_isa_irq_handler, 0, "ISA", 263 NULL)) 264 pr_err("Failed to register ISA interrupt\n"); 265 } 266 267 void __init sni_pcit_init(void) 268 { 269 ioport_resource.end = sni_io_resource.end; 270 #ifdef CONFIG_PCI 271 PCIBIOS_MIN_IO = 0x9000; 272 register_pci_controller(&sni_pcit_controller); 273 #endif 274 sni_pcit_resource_init(); 275 } 276 277 static int __init snirm_pcit_setup_devinit(void) 278 { 279 switch (sni_brd_type) { 280 case SNI_BRD_PCI_TOWER: 281 platform_device_register(&pcit_serial8250_device); 282 platform_device_register(&pcit_cmos_device); 283 platform_device_register(&pcit_pcspeaker_pdev); 284 break; 285 286 case SNI_BRD_PCI_TOWER_CPLUS: 287 platform_device_register(&pcit_cplus_serial8250_device); 288 platform_device_register(&pcit_cmos_device); 289 platform_device_register(&pcit_pcspeaker_pdev); 290 break; 291 } 292 return 0; 293 } 294 295 device_initcall(snirm_pcit_setup_devinit); 296
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.