]>
Commit | Line | Data |
---|---|---|
497799d3 MP |
1 | /* |
2 | * arch/ppc/platforms/4xx/bamboo.c | |
3 | * | |
4 | * Bamboo board specific routines | |
5 | * | |
6 | * Wade Farnsworth <wfarnsworth@mvista.com> | |
7 | * Copyright 2004 MontaVista Software Inc. | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify it | |
10 | * under the terms of the GNU General Public License as published by the | |
11 | * Free Software Foundation; either version 2 of the License, or (at your | |
12 | * option) any later version. | |
13 | */ | |
14 | ||
15 | #include <linux/config.h> | |
16 | #include <linux/stddef.h> | |
17 | #include <linux/kernel.h> | |
18 | #include <linux/init.h> | |
19 | #include <linux/errno.h> | |
20 | #include <linux/reboot.h> | |
21 | #include <linux/pci.h> | |
22 | #include <linux/kdev_t.h> | |
23 | #include <linux/types.h> | |
24 | #include <linux/major.h> | |
25 | #include <linux/blkdev.h> | |
26 | #include <linux/console.h> | |
27 | #include <linux/delay.h> | |
28 | #include <linux/ide.h> | |
29 | #include <linux/initrd.h> | |
30 | #include <linux/irq.h> | |
31 | #include <linux/seq_file.h> | |
32 | #include <linux/root_dev.h> | |
33 | #include <linux/tty.h> | |
34 | #include <linux/serial.h> | |
35 | #include <linux/serial_core.h> | |
36 | #include <linux/ethtool.h> | |
37 | ||
38 | #include <asm/system.h> | |
39 | #include <asm/pgtable.h> | |
40 | #include <asm/page.h> | |
41 | #include <asm/dma.h> | |
42 | #include <asm/io.h> | |
43 | #include <asm/machdep.h> | |
44 | #include <asm/ocp.h> | |
45 | #include <asm/pci-bridge.h> | |
46 | #include <asm/time.h> | |
47 | #include <asm/todc.h> | |
48 | #include <asm/bootinfo.h> | |
49 | #include <asm/ppc4xx_pic.h> | |
50 | #include <asm/ppcboot.h> | |
51 | ||
52 | #include <syslib/gen550.h> | |
53 | #include <syslib/ibm440gx_common.h> | |
54 | ||
55 | /* | |
56 | * This is a horrible kludge, we eventually need to abstract this | |
57 | * generic PHY stuff, so the standard phy mode defines can be | |
58 | * easily used from arch code. | |
59 | */ | |
60 | #include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h" | |
61 | ||
62 | bd_t __res; | |
63 | ||
64 | static struct ibm44x_clocks clocks __initdata; | |
65 | ||
66 | /* | |
67 | * Bamboo external IRQ triggering/polarity settings | |
68 | */ | |
69 | unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = { | |
70 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ0: Ethernet transceiver */ | |
71 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ1: Expansion connector */ | |
72 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ2: PCI slot 0 */ | |
73 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ3: PCI slot 1 */ | |
74 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ4: PCI slot 2 */ | |
75 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ5: PCI slot 3 */ | |
76 | (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE), /* IRQ6: SMI pushbutton */ | |
77 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ7: EXT */ | |
78 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ8: EXT */ | |
79 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ9: EXT */ | |
80 | }; | |
81 | ||
82 | static void __init | |
83 | bamboo_calibrate_decr(void) | |
84 | { | |
85 | unsigned int freq; | |
86 | ||
87 | if (mfspr(SPRN_CCR1) & CCR1_TCS) | |
88 | freq = BAMBOO_TMRCLK; | |
89 | else | |
90 | freq = clocks.cpu; | |
91 | ||
92 | ibm44x_calibrate_decr(freq); | |
93 | ||
94 | } | |
95 | ||
96 | static int | |
97 | bamboo_show_cpuinfo(struct seq_file *m) | |
98 | { | |
99 | seq_printf(m, "vendor\t\t: IBM\n"); | |
100 | seq_printf(m, "machine\t\t: PPC440EP EVB (Bamboo)\n"); | |
101 | ||
102 | return 0; | |
103 | } | |
104 | ||
105 | static inline int | |
106 | bamboo_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | |
107 | { | |
108 | static char pci_irq_table[][4] = | |
109 | /* | |
110 | * PCI IDSEL/INTPIN->INTLINE | |
111 | * A B C D | |
112 | */ | |
113 | { | |
114 | { 28, 28, 28, 28 }, /* IDSEL 1 - PCI Slot 0 */ | |
115 | { 27, 27, 27, 27 }, /* IDSEL 2 - PCI Slot 1 */ | |
116 | { 26, 26, 26, 26 }, /* IDSEL 3 - PCI Slot 2 */ | |
117 | { 25, 25, 25, 25 }, /* IDSEL 4 - PCI Slot 3 */ | |
118 | }; | |
119 | ||
120 | const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4; | |
121 | return PCI_IRQ_TABLE_LOOKUP; | |
122 | } | |
123 | ||
124 | static void __init bamboo_set_emacdata(void) | |
125 | { | |
126 | unsigned char * selection1_base; | |
127 | struct ocp_def *def; | |
128 | struct ocp_func_emac_data *emacdata; | |
129 | u8 selection1_val; | |
130 | int mode; | |
131 | ||
132 | selection1_base = ioremap64(BAMBOO_FPGA_SELECTION1_REG_ADDR, 16); | |
133 | selection1_val = readb(selection1_base); | |
134 | iounmap((void *) selection1_base); | |
135 | if (BAMBOO_SEL_MII(selection1_val)) | |
136 | mode = PHY_MODE_MII; | |
137 | else if (BAMBOO_SEL_RMII(selection1_val)) | |
138 | mode = PHY_MODE_RMII; | |
139 | else | |
140 | mode = PHY_MODE_SMII; | |
141 | ||
142 | /* Set mac_addr and phy mode for each EMAC */ | |
143 | ||
144 | def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 0); | |
145 | emacdata = def->additions; | |
146 | memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6); | |
147 | emacdata->phy_mode = mode; | |
148 | ||
149 | def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 1); | |
150 | emacdata = def->additions; | |
151 | memcpy(emacdata->mac_addr, __res.bi_enet1addr, 6); | |
152 | emacdata->phy_mode = mode; | |
153 | } | |
154 | ||
155 | static int | |
156 | bamboo_exclude_device(unsigned char bus, unsigned char devfn) | |
157 | { | |
158 | return (bus == 0 && devfn == 0); | |
159 | } | |
160 | ||
161 | #define PCI_READW(offset) \ | |
162 | (readw((void *)((u32)pci_reg_base+offset))) | |
163 | ||
164 | #define PCI_WRITEW(value, offset) \ | |
165 | (writew(value, (void *)((u32)pci_reg_base+offset))) | |
166 | ||
167 | #define PCI_WRITEL(value, offset) \ | |
168 | (writel(value, (void *)((u32)pci_reg_base+offset))) | |
169 | ||
170 | static void __init | |
171 | bamboo_setup_pci(void) | |
172 | { | |
173 | void *pci_reg_base; | |
174 | unsigned long memory_size; | |
175 | memory_size = ppc_md.find_end_of_memory(); | |
176 | ||
177 | pci_reg_base = ioremap64(BAMBOO_PCIL0_BASE, BAMBOO_PCIL0_SIZE); | |
178 | ||
179 | /* Enable PCI I/O, Mem, and Busmaster cycles */ | |
180 | PCI_WRITEW(PCI_READW(PCI_COMMAND) | | |
181 | PCI_COMMAND_MEMORY | | |
182 | PCI_COMMAND_MASTER, PCI_COMMAND); | |
183 | ||
184 | /* Disable region first */ | |
185 | PCI_WRITEL(0, BAMBOO_PCIL0_PMM0MA); | |
186 | ||
187 | /* PLB starting addr: 0x00000000A0000000 */ | |
188 | PCI_WRITEL(BAMBOO_PCI_PHY_MEM_BASE, BAMBOO_PCIL0_PMM0LA); | |
189 | ||
190 | /* PCI start addr, 0xA0000000 (PCI Address) */ | |
191 | PCI_WRITEL(BAMBOO_PCI_MEM_BASE, BAMBOO_PCIL0_PMM0PCILA); | |
192 | PCI_WRITEL(0, BAMBOO_PCIL0_PMM0PCIHA); | |
193 | ||
194 | /* Enable no pre-fetch, enable region */ | |
195 | PCI_WRITEL(((0xffffffff - | |
196 | (BAMBOO_PCI_UPPER_MEM - BAMBOO_PCI_MEM_BASE)) | 0x01), | |
197 | BAMBOO_PCIL0_PMM0MA); | |
198 | ||
199 | /* Disable region one */ | |
200 | PCI_WRITEL(0, BAMBOO_PCIL0_PMM1MA); | |
201 | PCI_WRITEL(0, BAMBOO_PCIL0_PMM1LA); | |
202 | PCI_WRITEL(0, BAMBOO_PCIL0_PMM1PCILA); | |
203 | PCI_WRITEL(0, BAMBOO_PCIL0_PMM1PCIHA); | |
204 | PCI_WRITEL(0, BAMBOO_PCIL0_PMM1MA); | |
205 | ||
206 | /* Disable region two */ | |
207 | PCI_WRITEL(0, BAMBOO_PCIL0_PMM2MA); | |
208 | PCI_WRITEL(0, BAMBOO_PCIL0_PMM2LA); | |
209 | PCI_WRITEL(0, BAMBOO_PCIL0_PMM2PCILA); | |
210 | PCI_WRITEL(0, BAMBOO_PCIL0_PMM2PCIHA); | |
211 | PCI_WRITEL(0, BAMBOO_PCIL0_PMM2MA); | |
212 | ||
213 | /* Now configure the PCI->PLB windows, we only use PTM1 | |
214 | * | |
215 | * For Inbound flow, set the window size to all available memory | |
216 | * This is required because if size is smaller, | |
217 | * then Eth/PCI DD would fail as PCI card not able to access | |
218 | * the memory allocated by DD. | |
219 | */ | |
220 | ||
221 | PCI_WRITEL(0, BAMBOO_PCIL0_PTM1MS); /* disabled region 1 */ | |
222 | PCI_WRITEL(0, BAMBOO_PCIL0_PTM1LA); /* begin of address map */ | |
223 | ||
224 | memory_size = 1 << fls(memory_size - 1); | |
225 | ||
226 | /* Size low + Enabled */ | |
227 | PCI_WRITEL((0xffffffff - (memory_size - 1)) | 0x1, BAMBOO_PCIL0_PTM1MS); | |
228 | ||
229 | eieio(); | |
230 | iounmap(pci_reg_base); | |
231 | } | |
232 | ||
233 | static void __init | |
234 | bamboo_setup_hose(void) | |
235 | { | |
236 | unsigned int bar_response, bar; | |
237 | struct pci_controller *hose; | |
238 | ||
239 | bamboo_setup_pci(); | |
240 | ||
241 | hose = pcibios_alloc_controller(); | |
242 | ||
243 | if (!hose) | |
244 | return; | |
245 | ||
246 | hose->first_busno = 0; | |
247 | hose->last_busno = 0xff; | |
248 | ||
249 | hose->pci_mem_offset = BAMBOO_PCI_MEM_OFFSET; | |
250 | ||
251 | pci_init_resource(&hose->io_resource, | |
252 | BAMBOO_PCI_LOWER_IO, | |
253 | BAMBOO_PCI_UPPER_IO, | |
254 | IORESOURCE_IO, | |
255 | "PCI host bridge"); | |
256 | ||
257 | pci_init_resource(&hose->mem_resources[0], | |
258 | BAMBOO_PCI_LOWER_MEM, | |
259 | BAMBOO_PCI_UPPER_MEM, | |
260 | IORESOURCE_MEM, | |
261 | "PCI host bridge"); | |
262 | ||
263 | ppc_md.pci_exclude_device = bamboo_exclude_device; | |
264 | ||
265 | hose->io_space.start = BAMBOO_PCI_LOWER_IO; | |
266 | hose->io_space.end = BAMBOO_PCI_UPPER_IO; | |
267 | hose->mem_space.start = BAMBOO_PCI_LOWER_MEM; | |
268 | hose->mem_space.end = BAMBOO_PCI_UPPER_MEM; | |
269 | isa_io_base = | |
270 | (unsigned long)ioremap64(BAMBOO_PCI_IO_BASE, BAMBOO_PCI_IO_SIZE); | |
271 | hose->io_base_virt = (void *)isa_io_base; | |
272 | ||
273 | setup_indirect_pci(hose, | |
274 | BAMBOO_PCI_CFGA_PLB32, | |
275 | BAMBOO_PCI_CFGD_PLB32); | |
276 | hose->set_cfg_type = 1; | |
277 | ||
278 | /* Zero config bars */ | |
279 | for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) { | |
280 | early_write_config_dword(hose, hose->first_busno, | |
281 | PCI_FUNC(hose->first_busno), bar, | |
282 | 0x00000000); | |
283 | early_read_config_dword(hose, hose->first_busno, | |
284 | PCI_FUNC(hose->first_busno), bar, | |
285 | &bar_response); | |
286 | } | |
287 | ||
288 | hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); | |
289 | ||
290 | ppc_md.pci_swizzle = common_swizzle; | |
291 | ppc_md.pci_map_irq = bamboo_map_irq; | |
292 | } | |
293 | ||
294 | TODC_ALLOC(); | |
295 | ||
296 | static void __init | |
297 | bamboo_early_serial_map(void) | |
298 | { | |
299 | struct uart_port port; | |
300 | ||
301 | /* Setup ioremapped serial port access */ | |
302 | memset(&port, 0, sizeof(port)); | |
303 | port.membase = ioremap64(PPC440EP_UART0_ADDR, 8); | |
304 | port.irq = 0; | |
305 | port.uartclk = clocks.uart0; | |
306 | port.regshift = 0; | |
307 | port.iotype = SERIAL_IO_MEM; | |
308 | port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; | |
309 | port.line = 0; | |
310 | ||
311 | if (early_serial_setup(&port) != 0) { | |
312 | printk("Early serial init of port 0 failed\n"); | |
313 | } | |
314 | ||
315 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) | |
316 | /* Configure debug serial access */ | |
317 | gen550_init(0, &port); | |
318 | #endif | |
319 | ||
320 | port.membase = ioremap64(PPC440EP_UART1_ADDR, 8); | |
321 | port.irq = 1; | |
322 | port.uartclk = clocks.uart1; | |
323 | port.line = 1; | |
324 | ||
325 | if (early_serial_setup(&port) != 0) { | |
326 | printk("Early serial init of port 1 failed\n"); | |
327 | } | |
328 | ||
329 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) | |
330 | /* Configure debug serial access */ | |
331 | gen550_init(1, &port); | |
332 | #endif | |
333 | ||
334 | port.membase = ioremap64(PPC440EP_UART2_ADDR, 8); | |
335 | port.irq = 3; | |
336 | port.uartclk = clocks.uart2; | |
337 | port.line = 2; | |
338 | ||
339 | if (early_serial_setup(&port) != 0) { | |
340 | printk("Early serial init of port 2 failed\n"); | |
341 | } | |
342 | ||
343 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) | |
344 | /* Configure debug serial access */ | |
345 | gen550_init(2, &port); | |
346 | #endif | |
347 | ||
348 | port.membase = ioremap64(PPC440EP_UART3_ADDR, 8); | |
349 | port.irq = 4; | |
350 | port.uartclk = clocks.uart3; | |
351 | port.line = 3; | |
352 | ||
353 | if (early_serial_setup(&port) != 0) { | |
354 | printk("Early serial init of port 3 failed\n"); | |
355 | } | |
356 | } | |
357 | ||
358 | static void __init | |
359 | bamboo_setup_arch(void) | |
360 | { | |
361 | ||
362 | bamboo_set_emacdata(); | |
363 | ||
364 | ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200); | |
365 | ocp_sys_info.opb_bus_freq = clocks.opb; | |
366 | ||
367 | /* Setup TODC access */ | |
368 | TODC_INIT(TODC_TYPE_DS1743, | |
369 | 0, | |
370 | 0, | |
371 | ioremap64(BAMBOO_RTC_ADDR, BAMBOO_RTC_SIZE), | |
372 | 8); | |
373 | ||
374 | /* init to some ~sane value until calibrate_delay() runs */ | |
375 | loops_per_jiffy = 50000000/HZ; | |
376 | ||
377 | /* Setup PCI host bridge */ | |
378 | bamboo_setup_hose(); | |
379 | ||
380 | #ifdef CONFIG_BLK_DEV_INITRD | |
381 | if (initrd_start) | |
382 | ROOT_DEV = Root_RAM0; | |
383 | else | |
384 | #endif | |
385 | #ifdef CONFIG_ROOT_NFS | |
386 | ROOT_DEV = Root_NFS; | |
387 | #else | |
388 | ROOT_DEV = Root_HDA1; | |
389 | #endif | |
390 | ||
391 | bamboo_early_serial_map(); | |
392 | ||
393 | /* Identify the system */ | |
394 | printk("IBM Bamboo port (MontaVista Software, Inc. (source@mvista.com))\n"); | |
395 | } | |
396 | ||
397 | void __init platform_init(unsigned long r3, unsigned long r4, | |
398 | unsigned long r5, unsigned long r6, unsigned long r7) | |
399 | { | |
400 | parse_bootinfo(find_bootinfo()); | |
401 | ||
402 | /* | |
403 | * If we were passed in a board information, copy it into the | |
404 | * residual data area. | |
405 | */ | |
406 | if (r3) | |
407 | __res = *(bd_t *)(r3 + KERNELBASE); | |
408 | ||
409 | ||
410 | ibm44x_platform_init(); | |
411 | ||
412 | ppc_md.setup_arch = bamboo_setup_arch; | |
413 | ppc_md.show_cpuinfo = bamboo_show_cpuinfo; | |
414 | ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */ | |
415 | ||
416 | ppc_md.calibrate_decr = bamboo_calibrate_decr; | |
417 | ppc_md.time_init = todc_time_init; | |
418 | ppc_md.set_rtc_time = todc_set_rtc_time; | |
419 | ppc_md.get_rtc_time = todc_get_rtc_time; | |
420 | ||
421 | ppc_md.nvram_read_val = todc_direct_read_val; | |
422 | ppc_md.nvram_write_val = todc_direct_write_val; | |
423 | #ifdef CONFIG_KGDB | |
424 | ppc_md.early_serial_map = bamboo_early_serial_map; | |
425 | #endif | |
426 | } | |
427 |