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