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