diff options
Diffstat (limited to 'arch/ppc/platforms/lopec.c')
-rw-r--r-- | arch/ppc/platforms/lopec.c | 411 |
1 files changed, 411 insertions, 0 deletions
diff --git a/arch/ppc/platforms/lopec.c b/arch/ppc/platforms/lopec.c new file mode 100644 index 000000000000..a5569525e0af --- /dev/null +++ b/arch/ppc/platforms/lopec.c | |||
@@ -0,0 +1,411 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/lopec.c | ||
3 | * | ||
4 | * Setup routines for the Motorola LoPEC. | ||
5 | * | ||
6 | * Author: Dan Cox | ||
7 | * Maintainer: Tom Rini <trini@kernel.crashing.org> | ||
8 | * | ||
9 | * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under | ||
10 | * the terms of the GNU General Public License version 2. This program | ||
11 | * is licensed "as is" without any warranty of any kind, whether express | ||
12 | * or implied. | ||
13 | */ | ||
14 | |||
15 | #include <linux/config.h> | ||
16 | #include <linux/types.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/pci_ids.h> | ||
19 | #include <linux/ioport.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/ide.h> | ||
22 | #include <linux/seq_file.h> | ||
23 | #include <linux/initrd.h> | ||
24 | #include <linux/console.h> | ||
25 | #include <linux/root_dev.h> | ||
26 | #include <linux/pci.h> | ||
27 | |||
28 | #include <asm/machdep.h> | ||
29 | #include <asm/pci-bridge.h> | ||
30 | #include <asm/io.h> | ||
31 | #include <asm/open_pic.h> | ||
32 | #include <asm/i8259.h> | ||
33 | #include <asm/todc.h> | ||
34 | #include <asm/bootinfo.h> | ||
35 | #include <asm/mpc10x.h> | ||
36 | #include <asm/hw_irq.h> | ||
37 | #include <asm/prep_nvram.h> | ||
38 | #include <asm/kgdb.h> | ||
39 | |||
40 | /* | ||
41 | * Define all of the IRQ senses and polarities. Taken from the | ||
42 | * LoPEC Programmer's Reference Guide. | ||
43 | */ | ||
44 | static u_char lopec_openpic_initsenses[16] __initdata = { | ||
45 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 0 */ | ||
46 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 1 */ | ||
47 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 2 */ | ||
48 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 3 */ | ||
49 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 4 */ | ||
50 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 5 */ | ||
51 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 6 */ | ||
52 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 7 */ | ||
53 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 8 */ | ||
54 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 9 */ | ||
55 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 10 */ | ||
56 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 11 */ | ||
57 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 12 */ | ||
58 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 13 */ | ||
59 | (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE), /* IRQ 14 */ | ||
60 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE) /* IRQ 15 */ | ||
61 | }; | ||
62 | |||
63 | static inline int __init | ||
64 | lopec_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
65 | { | ||
66 | int irq; | ||
67 | static char pci_irq_table[][4] = { | ||
68 | {16, 0, 0, 0}, /* ID 11 - Winbond */ | ||
69 | {22, 0, 0, 0}, /* ID 12 - SCSI */ | ||
70 | {0, 0, 0, 0}, /* ID 13 - nothing */ | ||
71 | {17, 0, 0, 0}, /* ID 14 - 82559 Ethernet */ | ||
72 | {27, 0, 0, 0}, /* ID 15 - USB */ | ||
73 | {23, 0, 0, 0}, /* ID 16 - PMC slot 1 */ | ||
74 | {24, 0, 0, 0}, /* ID 17 - PMC slot 2 */ | ||
75 | {25, 0, 0, 0}, /* ID 18 - PCI slot */ | ||
76 | {0, 0, 0, 0}, /* ID 19 - nothing */ | ||
77 | {0, 0, 0, 0}, /* ID 20 - nothing */ | ||
78 | {0, 0, 0, 0}, /* ID 21 - nothing */ | ||
79 | {0, 0, 0, 0}, /* ID 22 - nothing */ | ||
80 | {0, 0, 0, 0}, /* ID 23 - nothing */ | ||
81 | {0, 0, 0, 0}, /* ID 24 - PMC slot 1b */ | ||
82 | {0, 0, 0, 0}, /* ID 25 - nothing */ | ||
83 | {0, 0, 0, 0} /* ID 26 - PMC Slot 2b */ | ||
84 | }; | ||
85 | const long min_idsel = 11, max_idsel = 26, irqs_per_slot = 4; | ||
86 | |||
87 | irq = PCI_IRQ_TABLE_LOOKUP; | ||
88 | if (!irq) | ||
89 | return 0; | ||
90 | |||
91 | return irq; | ||
92 | } | ||
93 | |||
94 | static void __init | ||
95 | lopec_setup_winbond_83553(struct pci_controller *hose) | ||
96 | { | ||
97 | int devfn; | ||
98 | |||
99 | devfn = PCI_DEVFN(11,0); | ||
100 | |||
101 | /* IDE interrupt routing (primary 14, secondary 15) */ | ||
102 | early_write_config_byte(hose, 0, devfn, 0x43, 0xef); | ||
103 | /* PCI interrupt routing */ | ||
104 | early_write_config_word(hose, 0, devfn, 0x44, 0x0000); | ||
105 | |||
106 | /* ISA-PCI address decoder */ | ||
107 | early_write_config_byte(hose, 0, devfn, 0x48, 0xf0); | ||
108 | |||
109 | /* RTC, kb, not used in PPC */ | ||
110 | early_write_config_byte(hose, 0, devfn, 0x4d, 0x00); | ||
111 | early_write_config_byte(hose, 0, devfn, 0x4e, 0x04); | ||
112 | devfn = PCI_DEVFN(11, 1); | ||
113 | early_write_config_byte(hose, 0, devfn, 0x09, 0x8f); | ||
114 | early_write_config_dword(hose, 0, devfn, 0x40, 0x00ff0011); | ||
115 | } | ||
116 | |||
117 | static void __init | ||
118 | lopec_find_bridges(void) | ||
119 | { | ||
120 | struct pci_controller *hose; | ||
121 | |||
122 | hose = pcibios_alloc_controller(); | ||
123 | if (!hose) | ||
124 | return; | ||
125 | |||
126 | hose->first_busno = 0; | ||
127 | hose->last_busno = 0xff; | ||
128 | |||
129 | if (mpc10x_bridge_init(hose, MPC10X_MEM_MAP_B, MPC10X_MEM_MAP_B, | ||
130 | MPC10X_MAPB_EUMB_BASE) == 0) { | ||
131 | |||
132 | hose->mem_resources[0].end = 0xffffffff; | ||
133 | lopec_setup_winbond_83553(hose); | ||
134 | hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); | ||
135 | ppc_md.pci_swizzle = common_swizzle; | ||
136 | ppc_md.pci_map_irq = lopec_map_irq; | ||
137 | } | ||
138 | } | ||
139 | |||
140 | static int | ||
141 | lopec_show_cpuinfo(struct seq_file *m) | ||
142 | { | ||
143 | seq_printf(m, "machine\t\t: Motorola LoPEC\n"); | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static u32 | ||
148 | lopec_irq_canonicalize(u32 irq) | ||
149 | { | ||
150 | if (irq == 2) | ||
151 | return 9; | ||
152 | else | ||
153 | return irq; | ||
154 | } | ||
155 | |||
156 | static void | ||
157 | lopec_restart(char *cmd) | ||
158 | { | ||
159 | #define LOPEC_SYSSTAT1 0xffe00000 | ||
160 | /* force a hard reset, if possible */ | ||
161 | unsigned char reg = *((unsigned char *) LOPEC_SYSSTAT1); | ||
162 | reg |= 0x80; | ||
163 | *((unsigned char *) LOPEC_SYSSTAT1) = reg; | ||
164 | |||
165 | local_irq_disable(); | ||
166 | while(1); | ||
167 | #undef LOPEC_SYSSTAT1 | ||
168 | } | ||
169 | |||
170 | static void | ||
171 | lopec_halt(void) | ||
172 | { | ||
173 | local_irq_disable(); | ||
174 | while(1); | ||
175 | } | ||
176 | |||
177 | static void | ||
178 | lopec_power_off(void) | ||
179 | { | ||
180 | lopec_halt(); | ||
181 | } | ||
182 | |||
183 | #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) | ||
184 | int lopec_ide_ports_known = 0; | ||
185 | static unsigned long lopec_ide_regbase[MAX_HWIFS]; | ||
186 | static unsigned long lopec_ide_ctl_regbase[MAX_HWIFS]; | ||
187 | static unsigned long lopec_idedma_regbase; | ||
188 | |||
189 | static void | ||
190 | lopec_ide_probe(void) | ||
191 | { | ||
192 | struct pci_dev *dev = pci_get_device(PCI_VENDOR_ID_WINBOND, | ||
193 | PCI_DEVICE_ID_WINBOND_82C105, | ||
194 | NULL); | ||
195 | lopec_ide_ports_known = 1; | ||
196 | |||
197 | if (dev) { | ||
198 | lopec_ide_regbase[0] = dev->resource[0].start; | ||
199 | lopec_ide_regbase[1] = dev->resource[2].start; | ||
200 | lopec_ide_ctl_regbase[0] = dev->resource[1].start; | ||
201 | lopec_ide_ctl_regbase[1] = dev->resource[3].start; | ||
202 | lopec_idedma_regbase = dev->resource[4].start; | ||
203 | pci_dev_put(dev); | ||
204 | } | ||
205 | } | ||
206 | |||
207 | static int | ||
208 | lopec_ide_default_irq(unsigned long base) | ||
209 | { | ||
210 | if (lopec_ide_ports_known == 0) | ||
211 | lopec_ide_probe(); | ||
212 | |||
213 | if (base == lopec_ide_regbase[0]) | ||
214 | return 14; | ||
215 | else if (base == lopec_ide_regbase[1]) | ||
216 | return 15; | ||
217 | else | ||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static unsigned long | ||
222 | lopec_ide_default_io_base(int index) | ||
223 | { | ||
224 | if (lopec_ide_ports_known == 0) | ||
225 | lopec_ide_probe(); | ||
226 | return lopec_ide_regbase[index]; | ||
227 | } | ||
228 | |||
229 | static void __init | ||
230 | lopec_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data, | ||
231 | unsigned long ctl, int *irq) | ||
232 | { | ||
233 | unsigned long reg = data; | ||
234 | uint alt_status_base; | ||
235 | int i; | ||
236 | |||
237 | for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) | ||
238 | hw->io_ports[i] = reg++; | ||
239 | |||
240 | if (data == lopec_ide_regbase[0]) { | ||
241 | alt_status_base = lopec_ide_ctl_regbase[0] + 2; | ||
242 | hw->irq = 14; | ||
243 | } else if (data == lopec_ide_regbase[1]) { | ||
244 | alt_status_base = lopec_ide_ctl_regbase[1] + 2; | ||
245 | hw->irq = 15; | ||
246 | } else { | ||
247 | alt_status_base = 0; | ||
248 | hw->irq = 0; | ||
249 | } | ||
250 | |||
251 | if (ctl) | ||
252 | hw->io_ports[IDE_CONTROL_OFFSET] = ctl; | ||
253 | else | ||
254 | hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base; | ||
255 | |||
256 | if (irq != NULL) | ||
257 | *irq = hw->irq; | ||
258 | |||
259 | } | ||
260 | #endif /* BLK_DEV_IDE */ | ||
261 | |||
262 | static void __init | ||
263 | lopec_init_IRQ(void) | ||
264 | { | ||
265 | int i; | ||
266 | |||
267 | /* | ||
268 | * Provide the open_pic code with the correct table of interrupts. | ||
269 | */ | ||
270 | OpenPIC_InitSenses = lopec_openpic_initsenses; | ||
271 | OpenPIC_NumInitSenses = sizeof(lopec_openpic_initsenses); | ||
272 | |||
273 | mpc10x_set_openpic(); | ||
274 | |||
275 | /* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */ | ||
276 | openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade", | ||
277 | &i8259_irq); | ||
278 | |||
279 | /* Map i8259 interrupts */ | ||
280 | for(i = 0; i < NUM_8259_INTERRUPTS; i++) | ||
281 | irq_desc[i].handler = &i8259_pic; | ||
282 | |||
283 | /* | ||
284 | * The EPIC allows for a read in the range of 0xFEF00000 -> | ||
285 | * 0xFEFFFFFF to generate a PCI interrupt-acknowledge transaction. | ||
286 | */ | ||
287 | i8259_init(0xfef00000); | ||
288 | } | ||
289 | |||
290 | static int __init | ||
291 | lopec_request_io(void) | ||
292 | { | ||
293 | outb(0x00, 0x4d0); | ||
294 | outb(0xc0, 0x4d1); | ||
295 | |||
296 | request_region(0x00, 0x20, "dma1"); | ||
297 | request_region(0x20, 0x20, "pic1"); | ||
298 | request_region(0x40, 0x20, "timer"); | ||
299 | request_region(0x80, 0x10, "dma page reg"); | ||
300 | request_region(0xa0, 0x20, "pic2"); | ||
301 | request_region(0xc0, 0x20, "dma2"); | ||
302 | |||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | device_initcall(lopec_request_io); | ||
307 | |||
308 | static void __init | ||
309 | lopec_map_io(void) | ||
310 | { | ||
311 | io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO); | ||
312 | io_block_mapping(0xb0000000, 0xb0000000, 0x10000000, _PAGE_IO); | ||
313 | } | ||
314 | |||
315 | /* | ||
316 | * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1. | ||
317 | */ | ||
318 | static __inline__ void | ||
319 | lopec_set_bat(void) | ||
320 | { | ||
321 | mb(); | ||
322 | mtspr(SPRN_DBAT1U, 0xf8000ffe); | ||
323 | mtspr(SPRN_DBAT1L, 0xf800002a); | ||
324 | mb(); | ||
325 | } | ||
326 | |||
327 | TODC_ALLOC(); | ||
328 | |||
329 | static void __init | ||
330 | lopec_setup_arch(void) | ||
331 | { | ||
332 | |||
333 | TODC_INIT(TODC_TYPE_MK48T37, 0, 0, | ||
334 | ioremap(0xffe80000, 0x8000), 8); | ||
335 | |||
336 | loops_per_jiffy = 100000000/HZ; | ||
337 | |||
338 | lopec_find_bridges(); | ||
339 | |||
340 | #ifdef CONFIG_BLK_DEV_INITRD | ||
341 | if (initrd_start) | ||
342 | ROOT_DEV = Root_RAM0; | ||
343 | else | ||
344 | #elif defined(CONFIG_ROOT_NFS) | ||
345 | ROOT_DEV = Root_NFS; | ||
346 | #elif defined(CONFIG_BLK_DEV_IDEDISK) | ||
347 | ROOT_DEV = Root_HDA1; | ||
348 | #else | ||
349 | ROOT_DEV = Root_SDA1; | ||
350 | #endif | ||
351 | |||
352 | #ifdef CONFIG_PPCBUG_NVRAM | ||
353 | /* Read in NVRAM data */ | ||
354 | init_prep_nvram(); | ||
355 | |||
356 | /* if no bootargs, look in NVRAM */ | ||
357 | if ( cmd_line[0] == '\0' ) { | ||
358 | char *bootargs; | ||
359 | bootargs = prep_nvram_get_var("bootargs"); | ||
360 | if (bootargs != NULL) { | ||
361 | strcpy(cmd_line, bootargs); | ||
362 | /* again.. */ | ||
363 | strcpy(saved_command_line, cmd_line); | ||
364 | } | ||
365 | } | ||
366 | #endif | ||
367 | } | ||
368 | |||
369 | void __init | ||
370 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
371 | unsigned long r6, unsigned long r7) | ||
372 | { | ||
373 | parse_bootinfo(find_bootinfo()); | ||
374 | lopec_set_bat(); | ||
375 | |||
376 | isa_io_base = MPC10X_MAPB_ISA_IO_BASE; | ||
377 | isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE; | ||
378 | pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET; | ||
379 | ISA_DMA_THRESHOLD = 0x00ffffff; | ||
380 | DMA_MODE_READ = 0x44; | ||
381 | DMA_MODE_WRITE = 0x48; | ||
382 | |||
383 | ppc_md.setup_arch = lopec_setup_arch; | ||
384 | ppc_md.show_cpuinfo = lopec_show_cpuinfo; | ||
385 | ppc_md.irq_canonicalize = lopec_irq_canonicalize; | ||
386 | ppc_md.init_IRQ = lopec_init_IRQ; | ||
387 | ppc_md.get_irq = openpic_get_irq; | ||
388 | |||
389 | ppc_md.restart = lopec_restart; | ||
390 | ppc_md.power_off = lopec_power_off; | ||
391 | ppc_md.halt = lopec_halt; | ||
392 | |||
393 | ppc_md.setup_io_mappings = lopec_map_io; | ||
394 | |||
395 | ppc_md.time_init = todc_time_init; | ||
396 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
397 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
398 | ppc_md.calibrate_decr = todc_calibrate_decr; | ||
399 | |||
400 | ppc_md.nvram_read_val = todc_direct_read_val; | ||
401 | ppc_md.nvram_write_val = todc_direct_write_val; | ||
402 | |||
403 | #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) | ||
404 | ppc_ide_md.default_irq = lopec_ide_default_irq; | ||
405 | ppc_ide_md.default_io_base = lopec_ide_default_io_base; | ||
406 | ppc_ide_md.ide_init_hwif = lopec_ide_init_hwif_ports; | ||
407 | #endif | ||
408 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
409 | ppc_md.progress = gen550_progress; | ||
410 | #endif | ||
411 | } | ||