diff options
Diffstat (limited to 'arch/ppc/syslib/mpc10x_common.c')
-rw-r--r-- | arch/ppc/syslib/mpc10x_common.c | 654 |
1 files changed, 0 insertions, 654 deletions
diff --git a/arch/ppc/syslib/mpc10x_common.c b/arch/ppc/syslib/mpc10x_common.c deleted file mode 100644 index 437a294527a9..000000000000 --- a/arch/ppc/syslib/mpc10x_common.c +++ /dev/null | |||
@@ -1,654 +0,0 @@ | |||
1 | /* | ||
2 | * Common routines for the Motorola SPS MPC106, MPC107 and MPC8240 Host bridge, | ||
3 | * Mem ctlr, EPIC, etc. | ||
4 | * | ||
5 | * Author: Mark A. Greer | ||
6 | * mgreer@mvista.com | ||
7 | * | ||
8 | * 2001 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * *** WARNING - A BAT MUST be set to access the PCI config addr/data regs *** | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/pci.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/serial_8250.h> | ||
23 | #include <linux/fsl_devices.h> | ||
24 | #include <linux/device.h> | ||
25 | |||
26 | #include <asm/byteorder.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <asm/irq.h> | ||
29 | #include <asm/uaccess.h> | ||
30 | #include <asm/machdep.h> | ||
31 | #include <asm/pci-bridge.h> | ||
32 | #include <asm/open_pic.h> | ||
33 | #include <asm/mpc10x.h> | ||
34 | #include <asm/ppc_sys.h> | ||
35 | |||
36 | #ifdef CONFIG_MPC10X_OPENPIC | ||
37 | #ifdef CONFIG_EPIC_SERIAL_MODE | ||
38 | #define EPIC_IRQ_BASE (epic_serial_mode ? 16 : 5) | ||
39 | #else | ||
40 | #define EPIC_IRQ_BASE 5 | ||
41 | #endif | ||
42 | #define MPC10X_I2C_IRQ (EPIC_IRQ_BASE + NUM_8259_INTERRUPTS) | ||
43 | #define MPC10X_DMA0_IRQ (EPIC_IRQ_BASE + 1 + NUM_8259_INTERRUPTS) | ||
44 | #define MPC10X_DMA1_IRQ (EPIC_IRQ_BASE + 2 + NUM_8259_INTERRUPTS) | ||
45 | #define MPC10X_UART0_IRQ (EPIC_IRQ_BASE + 4 + NUM_8259_INTERRUPTS) | ||
46 | #define MPC10X_UART1_IRQ (EPIC_IRQ_BASE + 5 + NUM_8259_INTERRUPTS) | ||
47 | #else | ||
48 | #define MPC10X_I2C_IRQ -1 | ||
49 | #define MPC10X_DMA0_IRQ -1 | ||
50 | #define MPC10X_DMA1_IRQ -1 | ||
51 | #define MPC10X_UART0_IRQ -1 | ||
52 | #define MPC10X_UART1_IRQ -1 | ||
53 | #endif | ||
54 | |||
55 | static struct fsl_i2c_platform_data mpc10x_i2c_pdata = { | ||
56 | .device_flags = 0, | ||
57 | }; | ||
58 | |||
59 | static struct plat_serial8250_port serial_plat_uart0[] = { | ||
60 | [0] = { | ||
61 | .mapbase = 0x4500, | ||
62 | .iotype = UPIO_MEM, | ||
63 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, | ||
64 | }, | ||
65 | { }, | ||
66 | }; | ||
67 | static struct plat_serial8250_port serial_plat_uart1[] = { | ||
68 | [0] = { | ||
69 | .mapbase = 0x4600, | ||
70 | .iotype = UPIO_MEM, | ||
71 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, | ||
72 | }, | ||
73 | { }, | ||
74 | }; | ||
75 | |||
76 | struct platform_device ppc_sys_platform_devices[] = { | ||
77 | [MPC10X_IIC1] = { | ||
78 | .name = "fsl-i2c", | ||
79 | .id = 1, | ||
80 | .dev.platform_data = &mpc10x_i2c_pdata, | ||
81 | .num_resources = 2, | ||
82 | .resource = (struct resource[]) { | ||
83 | { | ||
84 | .start = MPC10X_EUMB_I2C_OFFSET, | ||
85 | .end = MPC10X_EUMB_I2C_OFFSET + | ||
86 | MPC10X_EUMB_I2C_SIZE - 1, | ||
87 | .flags = IORESOURCE_MEM, | ||
88 | }, | ||
89 | { | ||
90 | .flags = IORESOURCE_IRQ | ||
91 | }, | ||
92 | }, | ||
93 | }, | ||
94 | [MPC10X_DMA0] = { | ||
95 | .name = "fsl-dma", | ||
96 | .id = 0, | ||
97 | .num_resources = 2, | ||
98 | .resource = (struct resource[]) { | ||
99 | { | ||
100 | .start = MPC10X_EUMB_DMA_OFFSET + 0x10, | ||
101 | .end = MPC10X_EUMB_DMA_OFFSET + 0x1f, | ||
102 | .flags = IORESOURCE_MEM, | ||
103 | }, | ||
104 | { | ||
105 | .flags = IORESOURCE_IRQ, | ||
106 | }, | ||
107 | }, | ||
108 | }, | ||
109 | [MPC10X_DMA1] = { | ||
110 | .name = "fsl-dma", | ||
111 | .id = 1, | ||
112 | .num_resources = 2, | ||
113 | .resource = (struct resource[]) { | ||
114 | { | ||
115 | .start = MPC10X_EUMB_DMA_OFFSET + 0x20, | ||
116 | .end = MPC10X_EUMB_DMA_OFFSET + 0x2f, | ||
117 | .flags = IORESOURCE_MEM, | ||
118 | }, | ||
119 | { | ||
120 | .flags = IORESOURCE_IRQ, | ||
121 | }, | ||
122 | }, | ||
123 | }, | ||
124 | [MPC10X_DMA1] = { | ||
125 | .name = "fsl-dma", | ||
126 | .id = 1, | ||
127 | .num_resources = 2, | ||
128 | .resource = (struct resource[]) { | ||
129 | { | ||
130 | .start = MPC10X_EUMB_DMA_OFFSET + 0x20, | ||
131 | .end = MPC10X_EUMB_DMA_OFFSET + 0x2f, | ||
132 | .flags = IORESOURCE_MEM, | ||
133 | }, | ||
134 | { | ||
135 | .flags = IORESOURCE_IRQ, | ||
136 | }, | ||
137 | }, | ||
138 | }, | ||
139 | [MPC10X_UART0] = { | ||
140 | .name = "serial8250", | ||
141 | .id = PLAT8250_DEV_PLATFORM, | ||
142 | .dev.platform_data = serial_plat_uart0, | ||
143 | }, | ||
144 | [MPC10X_UART1] = { | ||
145 | .name = "serial8250", | ||
146 | .id = PLAT8250_DEV_PLATFORM1, | ||
147 | .dev.platform_data = serial_plat_uart1, | ||
148 | }, | ||
149 | |||
150 | }; | ||
151 | |||
152 | /* We use the PCI ID to match on */ | ||
153 | struct ppc_sys_spec *cur_ppc_sys_spec; | ||
154 | struct ppc_sys_spec ppc_sys_specs[] = { | ||
155 | { | ||
156 | .ppc_sys_name = "8245", | ||
157 | .mask = 0xFFFFFFFF, | ||
158 | .value = MPC10X_BRIDGE_8245, | ||
159 | .num_devices = 5, | ||
160 | .device_list = (enum ppc_sys_devices[]) | ||
161 | { | ||
162 | MPC10X_IIC1, MPC10X_DMA0, MPC10X_DMA1, MPC10X_UART0, MPC10X_UART1, | ||
163 | }, | ||
164 | }, | ||
165 | { | ||
166 | .ppc_sys_name = "8240", | ||
167 | .mask = 0xFFFFFFFF, | ||
168 | .value = MPC10X_BRIDGE_8240, | ||
169 | .num_devices = 3, | ||
170 | .device_list = (enum ppc_sys_devices[]) | ||
171 | { | ||
172 | MPC10X_IIC1, MPC10X_DMA0, MPC10X_DMA1, | ||
173 | }, | ||
174 | }, | ||
175 | { | ||
176 | .ppc_sys_name = "107", | ||
177 | .mask = 0xFFFFFFFF, | ||
178 | .value = MPC10X_BRIDGE_107, | ||
179 | .num_devices = 3, | ||
180 | .device_list = (enum ppc_sys_devices[]) | ||
181 | { | ||
182 | MPC10X_IIC1, MPC10X_DMA0, MPC10X_DMA1, | ||
183 | }, | ||
184 | }, | ||
185 | { /* default match */ | ||
186 | .ppc_sys_name = "", | ||
187 | .mask = 0x00000000, | ||
188 | .value = 0x00000000, | ||
189 | }, | ||
190 | }; | ||
191 | |||
192 | /* | ||
193 | * mach_mpc10x_fixup: This function enables DUART mode if it detects | ||
194 | * if it detects two UARTS in the platform device entries. | ||
195 | */ | ||
196 | static int __init mach_mpc10x_fixup(struct platform_device *pdev) | ||
197 | { | ||
198 | if (strncmp (pdev->name, "serial8250", 10) == 0 && pdev->id == 1) | ||
199 | writeb(readb(serial_plat_uart1[0].membase + 0x11) | 0x1, | ||
200 | serial_plat_uart1[0].membase + 0x11); | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static int __init mach_mpc10x_init(void) | ||
205 | { | ||
206 | ppc_sys_device_fixup = mach_mpc10x_fixup; | ||
207 | return 0; | ||
208 | } | ||
209 | postcore_initcall(mach_mpc10x_init); | ||
210 | |||
211 | /* Set resources to match bridge memory map */ | ||
212 | void __init | ||
213 | mpc10x_bridge_set_resources(int map, struct pci_controller *hose) | ||
214 | { | ||
215 | |||
216 | switch (map) { | ||
217 | case MPC10X_MEM_MAP_A: | ||
218 | pci_init_resource(&hose->io_resource, | ||
219 | 0x00000000, | ||
220 | 0x3f7fffff, | ||
221 | IORESOURCE_IO, | ||
222 | "PCI host bridge"); | ||
223 | |||
224 | pci_init_resource (&hose->mem_resources[0], | ||
225 | 0xc0000000, | ||
226 | 0xfeffffff, | ||
227 | IORESOURCE_MEM, | ||
228 | "PCI host bridge"); | ||
229 | break; | ||
230 | case MPC10X_MEM_MAP_B: | ||
231 | pci_init_resource(&hose->io_resource, | ||
232 | 0x00000000, | ||
233 | 0x00bfffff, | ||
234 | IORESOURCE_IO, | ||
235 | "PCI host bridge"); | ||
236 | |||
237 | pci_init_resource (&hose->mem_resources[0], | ||
238 | 0x80000000, | ||
239 | 0xfcffffff, | ||
240 | IORESOURCE_MEM, | ||
241 | "PCI host bridge"); | ||
242 | break; | ||
243 | default: | ||
244 | printk("mpc10x_bridge_set_resources: " | ||
245 | "Invalid map specified\n"); | ||
246 | if (ppc_md.progress) | ||
247 | ppc_md.progress("mpc10x:exit1", 0x100); | ||
248 | } | ||
249 | } | ||
250 | |||
251 | /* | ||
252 | * Do some initialization and put the EUMB registers at the specified address | ||
253 | * (also map the EPIC registers into virtual space--OpenPIC_Addr will be set). | ||
254 | * | ||
255 | * The EPIC is not on the 106, only the 8240 and 107. | ||
256 | */ | ||
257 | int __init | ||
258 | mpc10x_bridge_init(struct pci_controller *hose, | ||
259 | uint current_map, | ||
260 | uint new_map, | ||
261 | uint phys_eumb_base) | ||
262 | { | ||
263 | int host_bridge, picr1, picr1_bit, i; | ||
264 | ulong pci_config_addr, pci_config_data; | ||
265 | u_char pir, byte; | ||
266 | |||
267 | if (ppc_md.progress) ppc_md.progress("mpc10x:enter", 0x100); | ||
268 | |||
269 | /* Set up for current map so we can get at config regs */ | ||
270 | switch (current_map) { | ||
271 | case MPC10X_MEM_MAP_A: | ||
272 | setup_indirect_pci(hose, | ||
273 | MPC10X_MAPA_CNFG_ADDR, | ||
274 | MPC10X_MAPA_CNFG_DATA); | ||
275 | break; | ||
276 | case MPC10X_MEM_MAP_B: | ||
277 | setup_indirect_pci(hose, | ||
278 | MPC10X_MAPB_CNFG_ADDR, | ||
279 | MPC10X_MAPB_CNFG_DATA); | ||
280 | break; | ||
281 | default: | ||
282 | printk("mpc10x_bridge_init: %s\n", | ||
283 | "Invalid current map specified"); | ||
284 | if (ppc_md.progress) | ||
285 | ppc_md.progress("mpc10x:exit1", 0x100); | ||
286 | return -1; | ||
287 | } | ||
288 | |||
289 | /* Make sure it's a supported bridge */ | ||
290 | early_read_config_dword(hose, | ||
291 | 0, | ||
292 | PCI_DEVFN(0,0), | ||
293 | PCI_VENDOR_ID, | ||
294 | &host_bridge); | ||
295 | |||
296 | switch (host_bridge) { | ||
297 | case MPC10X_BRIDGE_106: | ||
298 | case MPC10X_BRIDGE_8240: | ||
299 | case MPC10X_BRIDGE_107: | ||
300 | case MPC10X_BRIDGE_8245: | ||
301 | break; | ||
302 | default: | ||
303 | if (ppc_md.progress) | ||
304 | ppc_md.progress("mpc10x:exit2", 0x100); | ||
305 | return -1; | ||
306 | } | ||
307 | |||
308 | switch (new_map) { | ||
309 | case MPC10X_MEM_MAP_A: | ||
310 | MPC10X_SETUP_HOSE(hose, A); | ||
311 | pci_config_addr = MPC10X_MAPA_CNFG_ADDR; | ||
312 | pci_config_data = MPC10X_MAPA_CNFG_DATA; | ||
313 | picr1_bit = MPC10X_CFG_PICR1_ADDR_MAP_A; | ||
314 | break; | ||
315 | case MPC10X_MEM_MAP_B: | ||
316 | MPC10X_SETUP_HOSE(hose, B); | ||
317 | pci_config_addr = MPC10X_MAPB_CNFG_ADDR; | ||
318 | pci_config_data = MPC10X_MAPB_CNFG_DATA; | ||
319 | picr1_bit = MPC10X_CFG_PICR1_ADDR_MAP_B; | ||
320 | break; | ||
321 | default: | ||
322 | printk("mpc10x_bridge_init: %s\n", | ||
323 | "Invalid new map specified"); | ||
324 | if (ppc_md.progress) | ||
325 | ppc_md.progress("mpc10x:exit3", 0x100); | ||
326 | return -1; | ||
327 | } | ||
328 | |||
329 | /* Make bridge use the 'new_map', if not already usng it */ | ||
330 | if (current_map != new_map) { | ||
331 | early_read_config_dword(hose, | ||
332 | 0, | ||
333 | PCI_DEVFN(0,0), | ||
334 | MPC10X_CFG_PICR1_REG, | ||
335 | &picr1); | ||
336 | |||
337 | picr1 = (picr1 & ~MPC10X_CFG_PICR1_ADDR_MAP_MASK) | | ||
338 | picr1_bit; | ||
339 | |||
340 | early_write_config_dword(hose, | ||
341 | 0, | ||
342 | PCI_DEVFN(0,0), | ||
343 | MPC10X_CFG_PICR1_REG, | ||
344 | picr1); | ||
345 | |||
346 | asm volatile("sync"); | ||
347 | |||
348 | /* Undo old mappings & map in new cfg data/addr regs */ | ||
349 | iounmap((void *)hose->cfg_addr); | ||
350 | iounmap((void *)hose->cfg_data); | ||
351 | |||
352 | setup_indirect_pci(hose, | ||
353 | pci_config_addr, | ||
354 | pci_config_data); | ||
355 | } | ||
356 | |||
357 | /* Setup resources to match map */ | ||
358 | mpc10x_bridge_set_resources(new_map, hose); | ||
359 | |||
360 | /* | ||
361 | * Want processor accesses of 0xFDxxxxxx to be mapped | ||
362 | * to PCI memory space at 0x00000000. Do not want | ||
363 | * host bridge to respond to PCI memory accesses of | ||
364 | * 0xFDxxxxxx. Do not want host bridge to respond | ||
365 | * to PCI memory addresses 0xFD000000-0xFDFFFFFF; | ||
366 | * want processor accesses from 0x000A0000-0x000BFFFF | ||
367 | * to be forwarded to system memory. | ||
368 | * | ||
369 | * Only valid if not in agent mode and using MAP B. | ||
370 | */ | ||
371 | if (new_map == MPC10X_MEM_MAP_B) { | ||
372 | early_read_config_byte(hose, | ||
373 | 0, | ||
374 | PCI_DEVFN(0,0), | ||
375 | MPC10X_CFG_MAPB_OPTIONS_REG, | ||
376 | &byte); | ||
377 | |||
378 | byte &= ~(MPC10X_CFG_MAPB_OPTIONS_PFAE | | ||
379 | MPC10X_CFG_MAPB_OPTIONS_PCICH | | ||
380 | MPC10X_CFG_MAPB_OPTIONS_PROCCH); | ||
381 | |||
382 | if (host_bridge != MPC10X_BRIDGE_106) { | ||
383 | byte |= MPC10X_CFG_MAPB_OPTIONS_CFAE; | ||
384 | } | ||
385 | |||
386 | early_write_config_byte(hose, | ||
387 | 0, | ||
388 | PCI_DEVFN(0,0), | ||
389 | MPC10X_CFG_MAPB_OPTIONS_REG, | ||
390 | byte); | ||
391 | } | ||
392 | |||
393 | if (host_bridge != MPC10X_BRIDGE_106) { | ||
394 | early_read_config_byte(hose, | ||
395 | 0, | ||
396 | PCI_DEVFN(0,0), | ||
397 | MPC10X_CFG_PIR_REG, | ||
398 | &pir); | ||
399 | |||
400 | if (pir != MPC10X_CFG_PIR_HOST_BRIDGE) { | ||
401 | printk("Host bridge in Agent mode\n"); | ||
402 | /* Read or Set LMBAR & PCSRBAR? */ | ||
403 | } | ||
404 | |||
405 | /* Set base addr of the 8240/107 EUMB. */ | ||
406 | early_write_config_dword(hose, | ||
407 | 0, | ||
408 | PCI_DEVFN(0,0), | ||
409 | MPC10X_CFG_EUMBBAR, | ||
410 | phys_eumb_base); | ||
411 | #ifdef CONFIG_MPC10X_OPENPIC | ||
412 | /* Map EPIC register part of EUMB into vitual memory - PCORE | ||
413 | uses an i8259 instead of EPIC. */ | ||
414 | OpenPIC_Addr = | ||
415 | ioremap(phys_eumb_base + MPC10X_EUMB_EPIC_OFFSET, | ||
416 | MPC10X_EUMB_EPIC_SIZE); | ||
417 | #endif | ||
418 | } | ||
419 | |||
420 | #ifdef CONFIG_MPC10X_STORE_GATHERING | ||
421 | mpc10x_enable_store_gathering(hose); | ||
422 | #else | ||
423 | mpc10x_disable_store_gathering(hose); | ||
424 | #endif | ||
425 | |||
426 | /* setup platform devices for MPC10x bridges */ | ||
427 | identify_ppc_sys_by_id (host_bridge); | ||
428 | |||
429 | for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) { | ||
430 | unsigned int dev_id = cur_ppc_sys_spec->device_list[i]; | ||
431 | ppc_sys_fixup_mem_resource(&ppc_sys_platform_devices[dev_id], | ||
432 | phys_eumb_base); | ||
433 | } | ||
434 | |||
435 | /* IRQs are determined at runtime */ | ||
436 | ppc_sys_platform_devices[MPC10X_IIC1].resource[1].start = MPC10X_I2C_IRQ; | ||
437 | ppc_sys_platform_devices[MPC10X_IIC1].resource[1].end = MPC10X_I2C_IRQ; | ||
438 | ppc_sys_platform_devices[MPC10X_DMA0].resource[1].start = MPC10X_DMA0_IRQ; | ||
439 | ppc_sys_platform_devices[MPC10X_DMA0].resource[1].end = MPC10X_DMA0_IRQ; | ||
440 | ppc_sys_platform_devices[MPC10X_DMA1].resource[1].start = MPC10X_DMA1_IRQ; | ||
441 | ppc_sys_platform_devices[MPC10X_DMA1].resource[1].end = MPC10X_DMA1_IRQ; | ||
442 | |||
443 | serial_plat_uart0[0].mapbase += phys_eumb_base; | ||
444 | serial_plat_uart0[0].irq = MPC10X_UART0_IRQ; | ||
445 | serial_plat_uart0[0].membase = ioremap(serial_plat_uart0[0].mapbase, 0x100); | ||
446 | |||
447 | serial_plat_uart1[0].mapbase += phys_eumb_base; | ||
448 | serial_plat_uart1[0].irq = MPC10X_UART1_IRQ; | ||
449 | serial_plat_uart1[0].membase = ioremap(serial_plat_uart1[0].mapbase, 0x100); | ||
450 | |||
451 | /* | ||
452 | * 8240 erratum 26, 8241/8245 erratum 29, 107 erratum 23: speculative | ||
453 | * PCI reads may return stale data so turn off. | ||
454 | */ | ||
455 | if ((host_bridge == MPC10X_BRIDGE_8240) | ||
456 | || (host_bridge == MPC10X_BRIDGE_8245) | ||
457 | || (host_bridge == MPC10X_BRIDGE_107)) { | ||
458 | |||
459 | early_read_config_dword(hose, 0, PCI_DEVFN(0,0), | ||
460 | MPC10X_CFG_PICR1_REG, &picr1); | ||
461 | |||
462 | picr1 &= ~MPC10X_CFG_PICR1_SPEC_PCI_RD; | ||
463 | |||
464 | early_write_config_dword(hose, 0, PCI_DEVFN(0,0), | ||
465 | MPC10X_CFG_PICR1_REG, picr1); | ||
466 | } | ||
467 | |||
468 | /* | ||
469 | * 8241/8245 erratum 28: PCI reads from local memory may return | ||
470 | * stale data. Workaround by setting PICR2[0] to disable copyback | ||
471 | * optimization. Oddly, the latest available user manual for the | ||
472 | * 8245 (Rev 2., dated 10/2003) says PICR2[0] is reserverd. | ||
473 | */ | ||
474 | if (host_bridge == MPC10X_BRIDGE_8245) { | ||
475 | u32 picr2; | ||
476 | |||
477 | early_read_config_dword(hose, 0, PCI_DEVFN(0,0), | ||
478 | MPC10X_CFG_PICR2_REG, &picr2); | ||
479 | |||
480 | picr2 |= MPC10X_CFG_PICR2_COPYBACK_OPT; | ||
481 | |||
482 | early_write_config_dword(hose, 0, PCI_DEVFN(0,0), | ||
483 | MPC10X_CFG_PICR2_REG, picr2); | ||
484 | } | ||
485 | |||
486 | if (ppc_md.progress) ppc_md.progress("mpc10x:exit", 0x100); | ||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | /* | ||
491 | * Need to make our own PCI config space access macros because | ||
492 | * mpc10x_get_mem_size() is called before the data structures are set up for | ||
493 | * the 'early_xxx' and 'indirect_xxx' routines to work. | ||
494 | * Assumes bus 0. | ||
495 | */ | ||
496 | #define MPC10X_CFG_read(val, addr, type, op) *val = op((type)(addr)) | ||
497 | #define MPC10X_CFG_write(val, addr, type, op) op((type *)(addr), (val)) | ||
498 | |||
499 | #define MPC10X_PCI_OP(rw, size, type, op, mask) \ | ||
500 | static void \ | ||
501 | mpc10x_##rw##_config_##size(uint *cfg_addr, uint *cfg_data, int devfn, int offset, type val) \ | ||
502 | { \ | ||
503 | out_be32(cfg_addr, \ | ||
504 | ((offset & 0xfc) << 24) | (devfn << 16) \ | ||
505 | | (0 << 8) | 0x80); \ | ||
506 | MPC10X_CFG_##rw(val, cfg_data + (offset & mask), type, op); \ | ||
507 | return; \ | ||
508 | } | ||
509 | |||
510 | MPC10X_PCI_OP(read, byte, u8 *, in_8, 3) | ||
511 | MPC10X_PCI_OP(read, dword, u32 *, in_le32, 0) | ||
512 | #if 0 /* Not used */ | ||
513 | MPC10X_PCI_OP(write, byte, u8, out_8, 3) | ||
514 | MPC10X_PCI_OP(read, word, u16 *, in_le16, 2) | ||
515 | MPC10X_PCI_OP(write, word, u16, out_le16, 2) | ||
516 | MPC10X_PCI_OP(write, dword, u32, out_le32, 0) | ||
517 | #endif | ||
518 | |||
519 | /* | ||
520 | * Read the memory controller registers to determine the amount of memory in | ||
521 | * the system. This assumes that the firmware has correctly set up the memory | ||
522 | * controller registers. | ||
523 | */ | ||
524 | unsigned long __init | ||
525 | mpc10x_get_mem_size(uint mem_map) | ||
526 | { | ||
527 | uint *config_addr, *config_data, val; | ||
528 | ulong start, end, total, offset; | ||
529 | int i; | ||
530 | u_char bank_enables; | ||
531 | |||
532 | switch (mem_map) { | ||
533 | case MPC10X_MEM_MAP_A: | ||
534 | config_addr = (uint *)MPC10X_MAPA_CNFG_ADDR; | ||
535 | config_data = (uint *)MPC10X_MAPA_CNFG_DATA; | ||
536 | break; | ||
537 | case MPC10X_MEM_MAP_B: | ||
538 | config_addr = (uint *)MPC10X_MAPB_CNFG_ADDR; | ||
539 | config_data = (uint *)MPC10X_MAPB_CNFG_DATA; | ||
540 | break; | ||
541 | default: | ||
542 | return 0; | ||
543 | } | ||
544 | |||
545 | mpc10x_read_config_byte(config_addr, | ||
546 | config_data, | ||
547 | PCI_DEVFN(0,0), | ||
548 | MPC10X_MCTLR_MEM_BANK_ENABLES, | ||
549 | &bank_enables); | ||
550 | |||
551 | total = 0; | ||
552 | |||
553 | for (i=0; i<8; i++) { | ||
554 | if (bank_enables & (1 << i)) { | ||
555 | offset = MPC10X_MCTLR_MEM_START_1 + ((i > 3) ? 4 : 0); | ||
556 | mpc10x_read_config_dword(config_addr, | ||
557 | config_data, | ||
558 | PCI_DEVFN(0,0), | ||
559 | offset, | ||
560 | &val); | ||
561 | start = (val >> ((i & 3) << 3)) & 0xff; | ||
562 | |||
563 | offset = MPC10X_MCTLR_EXT_MEM_START_1 + ((i>3) ? 4 : 0); | ||
564 | mpc10x_read_config_dword(config_addr, | ||
565 | config_data, | ||
566 | PCI_DEVFN(0,0), | ||
567 | offset, | ||
568 | &val); | ||
569 | val = (val >> ((i & 3) << 3)) & 0x03; | ||
570 | start = (val << 28) | (start << 20); | ||
571 | |||
572 | offset = MPC10X_MCTLR_MEM_END_1 + ((i > 3) ? 4 : 0); | ||
573 | mpc10x_read_config_dword(config_addr, | ||
574 | config_data, | ||
575 | PCI_DEVFN(0,0), | ||
576 | offset, | ||
577 | &val); | ||
578 | end = (val >> ((i & 3) << 3)) & 0xff; | ||
579 | |||
580 | offset = MPC10X_MCTLR_EXT_MEM_END_1 + ((i > 3) ? 4 : 0); | ||
581 | mpc10x_read_config_dword(config_addr, | ||
582 | config_data, | ||
583 | PCI_DEVFN(0,0), | ||
584 | offset, | ||
585 | &val); | ||
586 | val = (val >> ((i & 3) << 3)) & 0x03; | ||
587 | end = (val << 28) | (end << 20) | 0xfffff; | ||
588 | |||
589 | total += (end - start + 1); | ||
590 | } | ||
591 | } | ||
592 | |||
593 | return total; | ||
594 | } | ||
595 | |||
596 | int __init | ||
597 | mpc10x_enable_store_gathering(struct pci_controller *hose) | ||
598 | { | ||
599 | uint picr1; | ||
600 | |||
601 | early_read_config_dword(hose, | ||
602 | 0, | ||
603 | PCI_DEVFN(0,0), | ||
604 | MPC10X_CFG_PICR1_REG, | ||
605 | &picr1); | ||
606 | |||
607 | picr1 |= MPC10X_CFG_PICR1_ST_GATH_EN; | ||
608 | |||
609 | early_write_config_dword(hose, | ||
610 | 0, | ||
611 | PCI_DEVFN(0,0), | ||
612 | MPC10X_CFG_PICR1_REG, | ||
613 | picr1); | ||
614 | |||
615 | return 0; | ||
616 | } | ||
617 | |||
618 | int __init | ||
619 | mpc10x_disable_store_gathering(struct pci_controller *hose) | ||
620 | { | ||
621 | uint picr1; | ||
622 | |||
623 | early_read_config_dword(hose, | ||
624 | 0, | ||
625 | PCI_DEVFN(0,0), | ||
626 | MPC10X_CFG_PICR1_REG, | ||
627 | &picr1); | ||
628 | |||
629 | picr1 &= ~MPC10X_CFG_PICR1_ST_GATH_EN; | ||
630 | |||
631 | early_write_config_dword(hose, | ||
632 | 0, | ||
633 | PCI_DEVFN(0,0), | ||
634 | MPC10X_CFG_PICR1_REG, | ||
635 | picr1); | ||
636 | |||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | #ifdef CONFIG_MPC10X_OPENPIC | ||
641 | void __init mpc10x_set_openpic(void) | ||
642 | { | ||
643 | /* Map external IRQs */ | ||
644 | openpic_set_sources(0, EPIC_IRQ_BASE, OpenPIC_Addr + 0x10200); | ||
645 | /* Skip reserved space and map i2c and DMA Ch[01] */ | ||
646 | openpic_set_sources(EPIC_IRQ_BASE, 3, OpenPIC_Addr + 0x11020); | ||
647 | /* Skip reserved space and map Message Unit Interrupt (I2O) */ | ||
648 | openpic_set_sources(EPIC_IRQ_BASE + 3, 1, OpenPIC_Addr + 0x110C0); | ||
649 | /* Skip reserved space and map Serial Interrupts */ | ||
650 | openpic_set_sources(EPIC_IRQ_BASE + 4, 2, OpenPIC_Addr + 0x11120); | ||
651 | |||
652 | openpic_init(NUM_8259_INTERRUPTS); | ||
653 | } | ||
654 | #endif | ||