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