diff options
Diffstat (limited to 'arch/powerpc/platforms')
22 files changed, 388 insertions, 380 deletions
diff --git a/arch/powerpc/platforms/82xx/mpc82xx_ads.c b/arch/powerpc/platforms/82xx/mpc82xx_ads.c index da20832b27f1..2d1b05b9f8ef 100644 --- a/arch/powerpc/platforms/82xx/mpc82xx_ads.c +++ b/arch/powerpc/platforms/82xx/mpc82xx_ads.c | |||
@@ -553,7 +553,8 @@ static void __init mpc82xx_add_bridge(struct device_node *np) | |||
553 | 553 | ||
554 | setup_indirect_pci(hose, | 554 | setup_indirect_pci(hose, |
555 | r.start + offsetof(pci_cpm2_t, pci_cfg_addr), | 555 | r.start + offsetof(pci_cpm2_t, pci_cfg_addr), |
556 | r.start + offsetof(pci_cpm2_t, pci_cfg_data)); | 556 | r.start + offsetof(pci_cpm2_t, pci_cfg_data), |
557 | 0); | ||
557 | 558 | ||
558 | pci_process_bridge_OF_ranges(hose, np, 1); | 559 | pci_process_bridge_OF_ranges(hose, np, 1); |
559 | } | 560 | } |
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c index c0e2b89154e5..92069469de20 100644 --- a/arch/powerpc/platforms/83xx/pci.c +++ b/arch/powerpc/platforms/83xx/pci.c | |||
@@ -74,11 +74,11 @@ int __init mpc83xx_add_bridge(struct device_node *dev) | |||
74 | */ | 74 | */ |
75 | /* PCI 1 */ | 75 | /* PCI 1 */ |
76 | if ((rsrc.start & 0xfffff) == 0x8500) { | 76 | if ((rsrc.start & 0xfffff) == 0x8500) { |
77 | setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304); | 77 | setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304, 0); |
78 | } | 78 | } |
79 | /* PCI 2 */ | 79 | /* PCI 2 */ |
80 | if ((rsrc.start & 0xfffff) == 0x8600) { | 80 | if ((rsrc.start & 0xfffff) == 0x8600) { |
81 | setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384); | 81 | setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384, 0); |
82 | primary = 0; | 82 | primary = 0; |
83 | } | 83 | } |
84 | 84 | ||
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index 629926e01e90..f58184086c8c 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig | |||
@@ -18,6 +18,7 @@ config MPC8560_ADS | |||
18 | config MPC85xx_CDS | 18 | config MPC85xx_CDS |
19 | bool "Freescale MPC85xx CDS" | 19 | bool "Freescale MPC85xx CDS" |
20 | select DEFAULT_UIMAGE | 20 | select DEFAULT_UIMAGE |
21 | select PPC_I8259 | ||
21 | help | 22 | help |
22 | This option enables support for the MPC85xx CDS board | 23 | This option enables support for the MPC85xx CDS board |
23 | 24 | ||
@@ -30,6 +31,7 @@ config MPC85xx_MDS | |||
30 | 31 | ||
31 | config MPC8544_DS | 32 | config MPC8544_DS |
32 | bool "Freescale MPC8544 DS" | 33 | bool "Freescale MPC8544 DS" |
34 | select PPC_I8259 | ||
33 | select DEFAULT_UIMAGE | 35 | select DEFAULT_UIMAGE |
34 | help | 36 | help |
35 | This option enables support for the MPC8544 DS board | 37 | This option enables support for the MPC8544 DS board |
@@ -50,9 +52,9 @@ config MPC8560 | |||
50 | config MPC85xx | 52 | config MPC85xx |
51 | bool | 53 | bool |
52 | select PPC_UDBG_16550 | 54 | select PPC_UDBG_16550 |
53 | select PPC_INDIRECT_PCI | 55 | select PPC_INDIRECT_PCI if PCI |
54 | select PPC_INDIRECT_PCI_BE | ||
55 | select MPIC | 56 | select MPIC |
57 | select FSL_PCI if PCI | ||
56 | select SERIAL_8250_SHARE_IRQ if SERIAL_8250 | 58 | select SERIAL_8250_SHARE_IRQ if SERIAL_8250 |
57 | default y if MPC8540_ADS || MPC85xx_CDS || MPC8560_ADS \ | 59 | default y if MPC8540_ADS || MPC85xx_CDS || MPC8560_ADS \ |
58 | || MPC85xx_MDS || MPC8544_DS | 60 | || MPC85xx_MDS || MPC8544_DS |
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 4e02cbb14cf7..d70f2d0f9d36 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the PowerPC 85xx linux kernel. | 2 | # Makefile for the PowerPC 85xx linux kernel. |
3 | # | 3 | # |
4 | obj-$(CONFIG_PPC_85xx) += misc.o pci.o | 4 | obj-$(CONFIG_PPC_85xx) += misc.o |
5 | obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o | 5 | obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o |
6 | obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o | 6 | obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o |
7 | obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o | 7 | obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o |
diff --git a/arch/powerpc/platforms/85xx/mpc8544_ds.c b/arch/powerpc/platforms/85xx/mpc8544_ds.c index 6fb90aab879f..4905f6f8903b 100644 --- a/arch/powerpc/platforms/85xx/mpc8544_ds.c +++ b/arch/powerpc/platforms/85xx/mpc8544_ds.c | |||
@@ -2,6 +2,8 @@ | |||
2 | * MPC8544 DS Board Setup | 2 | * MPC8544 DS Board Setup |
3 | * | 3 | * |
4 | * Author Xianghua Xiao (x.xiao@freescale.com) | 4 | * Author Xianghua Xiao (x.xiao@freescale.com) |
5 | * Roy Zang <tie-fei.zang@freescale.com> | ||
6 | * - Add PCI/PCI Exprees support | ||
5 | * Copyright 2007 Freescale Semiconductor Inc. | 7 | * Copyright 2007 Freescale Semiconductor Inc. |
6 | * | 8 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 9 | * This program is free software; you can redistribute it and/or modify it |
@@ -12,13 +14,16 @@ | |||
12 | 14 | ||
13 | #include <linux/stddef.h> | 15 | #include <linux/stddef.h> |
14 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/pci.h> | ||
15 | #include <linux/kdev_t.h> | 18 | #include <linux/kdev_t.h> |
16 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
17 | #include <linux/seq_file.h> | 20 | #include <linux/seq_file.h> |
21 | #include <linux/interrupt.h> | ||
18 | 22 | ||
19 | #include <asm/system.h> | 23 | #include <asm/system.h> |
20 | #include <asm/time.h> | 24 | #include <asm/time.h> |
21 | #include <asm/machdep.h> | 25 | #include <asm/machdep.h> |
26 | #include <asm/pci-bridge.h> | ||
22 | #include <asm/mpc85xx.h> | 27 | #include <asm/mpc85xx.h> |
23 | #include <mm/mmu_decl.h> | 28 | #include <mm/mmu_decl.h> |
24 | #include <asm/prom.h> | 29 | #include <asm/prom.h> |
@@ -27,6 +32,7 @@ | |||
27 | #include <asm/i8259.h> | 32 | #include <asm/i8259.h> |
28 | 33 | ||
29 | #include <sysdev/fsl_soc.h> | 34 | #include <sysdev/fsl_soc.h> |
35 | #include <sysdev/fsl_pci.h> | ||
30 | #include "mpc85xx.h" | 36 | #include "mpc85xx.h" |
31 | 37 | ||
32 | #undef DEBUG | 38 | #undef DEBUG |
@@ -37,6 +43,17 @@ | |||
37 | #define DBG(fmt, args...) | 43 | #define DBG(fmt, args...) |
38 | #endif | 44 | #endif |
39 | 45 | ||
46 | #ifdef CONFIG_PPC_I8259 | ||
47 | static void mpc8544_8259_cascade(unsigned int irq, struct irq_desc *desc) | ||
48 | { | ||
49 | unsigned int cascade_irq = i8259_irq(); | ||
50 | |||
51 | if (cascade_irq != NO_IRQ) { | ||
52 | generic_handle_irq(cascade_irq); | ||
53 | } | ||
54 | desc->chip->eoi(irq); | ||
55 | } | ||
56 | #endif /* CONFIG_PPC_I8259 */ | ||
40 | 57 | ||
41 | void __init mpc8544_ds_pic_init(void) | 58 | void __init mpc8544_ds_pic_init(void) |
42 | { | 59 | { |
@@ -96,19 +113,240 @@ void __init mpc8544_ds_pic_init(void) | |||
96 | #endif /* CONFIG_PPC_I8259 */ | 113 | #endif /* CONFIG_PPC_I8259 */ |
97 | } | 114 | } |
98 | 115 | ||
116 | #ifdef CONFIG_PCI | ||
117 | enum pirq { PIRQA = 8, PIRQB, PIRQC, PIRQD, PIRQE, PIRQF, PIRQG, PIRQH }; | ||
118 | |||
119 | /* | ||
120 | * Value in table -- IRQ number | ||
121 | */ | ||
122 | const unsigned char uli1575_irq_route_table[16] = { | ||
123 | 0, /* 0: Reserved */ | ||
124 | 0x8, | ||
125 | 0, /* 2: Reserved */ | ||
126 | 0x2, | ||
127 | 0x4, | ||
128 | 0x5, | ||
129 | 0x7, | ||
130 | 0x6, | ||
131 | 0, /* 8: Reserved */ | ||
132 | 0x1, | ||
133 | 0x3, | ||
134 | 0x9, | ||
135 | 0xb, | ||
136 | 0, /* 13: Reserved */ | ||
137 | 0xd, | ||
138 | 0xf, | ||
139 | }; | ||
140 | |||
141 | static int __devinit | ||
142 | get_pci_irq_from_of(struct pci_controller *hose, int slot, int pin) | ||
143 | { | ||
144 | struct of_irq oirq; | ||
145 | u32 laddr[3]; | ||
146 | struct device_node *hosenode = hose ? hose->arch_data : NULL; | ||
147 | |||
148 | if (!hosenode) | ||
149 | return -EINVAL; | ||
150 | |||
151 | laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(slot, 0) << 8); | ||
152 | laddr[1] = laddr[2] = 0; | ||
153 | of_irq_map_raw(hosenode, &pin, 1, laddr, &oirq); | ||
154 | DBG("mpc8544_ds: pci irq addr %x, slot %d, pin %d, irq %d\n", | ||
155 | laddr[0], slot, pin, oirq.specifier[0]); | ||
156 | return oirq.specifier[0]; | ||
157 | } | ||
158 | |||
159 | /*8259*/ | ||
160 | static void __devinit quirk_uli1575(struct pci_dev *dev) | ||
161 | { | ||
162 | unsigned short temp; | ||
163 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
164 | unsigned char irq2pin[16]; | ||
165 | unsigned long pirq_map_word = 0; | ||
166 | u32 irq; | ||
167 | int i; | ||
168 | |||
169 | /* | ||
170 | * ULI1575 interrupts route setup | ||
171 | */ | ||
172 | memset(irq2pin, 0, 16); /* Initialize default value 0 */ | ||
173 | |||
174 | irq2pin[6]=PIRQA+3; /* enabled mapping for IRQ6 to PIRQD, used by SATA */ | ||
175 | |||
176 | /* | ||
177 | * PIRQE -> PIRQF mapping set manually | ||
178 | * | ||
179 | * IRQ pin IRQ# | ||
180 | * PIRQE ---- 9 | ||
181 | * PIRQF ---- 10 | ||
182 | * PIRQG ---- 11 | ||
183 | * PIRQH ---- 12 | ||
184 | */ | ||
185 | for (i = 0; i < 4; i++) | ||
186 | irq2pin[i + 9] = PIRQE + i; | ||
187 | |||
188 | /* Set IRQ-PIRQ Mapping to ULI1575 */ | ||
189 | for (i = 0; i < 16; i++) | ||
190 | if (irq2pin[i]) | ||
191 | pirq_map_word |= (uli1575_irq_route_table[i] & 0xf) | ||
192 | << ((irq2pin[i] - PIRQA) * 4); | ||
193 | |||
194 | pirq_map_word |= 1<<26; /* disable INTx in EP mode*/ | ||
195 | |||
196 | /* ULI1575 IRQ mapping conf register default value is 0xb9317542 */ | ||
197 | DBG("Setup ULI1575 IRQ mapping configuration register value = 0x%x\n", | ||
198 | (int)pirq_map_word); | ||
199 | pci_write_config_dword(dev, 0x48, pirq_map_word); | ||
200 | |||
201 | #define ULI1575_SET_DEV_IRQ(slot, pin, reg) \ | ||
202 | do { \ | ||
203 | int irq; \ | ||
204 | irq = get_pci_irq_from_of(hose, slot, pin); \ | ||
205 | if (irq > 0 && irq < 16) \ | ||
206 | pci_write_config_byte(dev, reg, irq2pin[irq]); \ | ||
207 | else \ | ||
208 | printk(KERN_WARNING "ULI1575 device" \ | ||
209 | "(slot %d, pin %d) irq %d is invalid.\n", \ | ||
210 | slot, pin, irq); \ | ||
211 | } while(0) | ||
212 | |||
213 | /* USB 1.1 OHCI controller 1, slot 28, pin 1 */ | ||
214 | ULI1575_SET_DEV_IRQ(28, 1, 0x86); | ||
215 | |||
216 | /* USB 1.1 OHCI controller 2, slot 28, pin 2 */ | ||
217 | ULI1575_SET_DEV_IRQ(28, 2, 0x87); | ||
218 | |||
219 | /* USB 1.1 OHCI controller 3, slot 28, pin 3 */ | ||
220 | ULI1575_SET_DEV_IRQ(28, 3, 0x88); | ||
221 | |||
222 | /* USB 2.0 controller, slot 28, pin 4 */ | ||
223 | irq = get_pci_irq_from_of(hose, 28, 4); | ||
224 | if (irq >= 0 && irq <= 15) | ||
225 | pci_write_config_dword(dev, 0x74, uli1575_irq_route_table[irq]); | ||
226 | |||
227 | /* Audio controller, slot 29, pin 1 */ | ||
228 | ULI1575_SET_DEV_IRQ(29, 1, 0x8a); | ||
229 | |||
230 | /* Modem controller, slot 29, pin 2 */ | ||
231 | ULI1575_SET_DEV_IRQ(29, 2, 0x8b); | ||
232 | |||
233 | /* HD audio controller, slot 29, pin 3 */ | ||
234 | ULI1575_SET_DEV_IRQ(29, 3, 0x8c); | ||
235 | |||
236 | /* SMB interrupt: slot 30, pin 1 */ | ||
237 | ULI1575_SET_DEV_IRQ(30, 1, 0x8e); | ||
238 | |||
239 | /* PMU ACPI SCI interrupt: slot 30, pin 2 */ | ||
240 | ULI1575_SET_DEV_IRQ(30, 2, 0x8f); | ||
241 | |||
242 | /* Serial ATA interrupt: slot 31, pin 1 */ | ||
243 | ULI1575_SET_DEV_IRQ(31, 1, 0x8d); | ||
244 | |||
245 | /* Primary PATA IDE IRQ: 14 | ||
246 | * Secondary PATA IDE IRQ: 15 | ||
247 | */ | ||
248 | pci_write_config_byte(dev, 0x44, 0x30 | uli1575_irq_route_table[14]); | ||
249 | pci_write_config_byte(dev, 0x75, uli1575_irq_route_table[15]); | ||
250 | |||
251 | /* Set IRQ14 and IRQ15 to legacy IRQs */ | ||
252 | pci_read_config_word(dev, 0x46, &temp); | ||
253 | temp |= 0xc000; | ||
254 | pci_write_config_word(dev, 0x46, temp); | ||
255 | |||
256 | /* Set i8259 interrupt trigger | ||
257 | * IRQ 3: Level | ||
258 | * IRQ 4: Level | ||
259 | * IRQ 5: Level | ||
260 | * IRQ 6: Level | ||
261 | * IRQ 7: Level | ||
262 | * IRQ 9: Level | ||
263 | * IRQ 10: Level | ||
264 | * IRQ 11: Level | ||
265 | * IRQ 12: Level | ||
266 | * IRQ 14: Edge | ||
267 | * IRQ 15: Edge | ||
268 | */ | ||
269 | outb(0xfa, 0x4d0); | ||
270 | outb(0x1e, 0x4d1); | ||
271 | |||
272 | #undef ULI1575_SET_DEV_IRQ | ||
273 | } | ||
274 | |||
275 | /* SATA */ | ||
276 | static void __devinit quirk_uli5288(struct pci_dev *dev) | ||
277 | { | ||
278 | unsigned char c; | ||
279 | |||
280 | pci_read_config_byte(dev, 0x83, &c); | ||
281 | c |= 0x80; /* read/write lock */ | ||
282 | pci_write_config_byte(dev, 0x83, c); | ||
283 | |||
284 | pci_write_config_byte(dev, 0x09, 0x01); /* Base class code: storage */ | ||
285 | pci_write_config_byte(dev, 0x0a, 0x06); /* IDE disk */ | ||
286 | |||
287 | pci_read_config_byte(dev, 0x83, &c); | ||
288 | c &= 0x7f; | ||
289 | pci_write_config_byte(dev, 0x83, c); | ||
290 | |||
291 | pci_read_config_byte(dev, 0x84, &c); | ||
292 | c |= 0x01; /* emulated PATA mode enabled */ | ||
293 | pci_write_config_byte(dev, 0x84, c); | ||
294 | } | ||
295 | |||
296 | /* PATA */ | ||
297 | static void __devinit quirk_uli5229(struct pci_dev *dev) | ||
298 | { | ||
299 | unsigned short temp; | ||
300 | pci_write_config_word(dev, 0x04, 0x0405); /* MEM IO MSI */ | ||
301 | pci_read_config_word(dev, 0x4a, &temp); | ||
302 | temp |= 0x1000; /* Enable Native IRQ 14/15 */ | ||
303 | pci_write_config_word(dev, 0x4a, temp); | ||
304 | } | ||
305 | |||
306 | /*Bridge*/ | ||
307 | static void __devinit early_uli5249(struct pci_dev *dev) | ||
308 | { | ||
309 | unsigned char temp; | ||
310 | pci_write_config_word(dev, 0x04, 0x0007); /* mem access */ | ||
311 | pci_read_config_byte(dev, 0x7c, &temp); | ||
312 | pci_write_config_byte(dev, 0x7c, 0x80); /* R/W lock control */ | ||
313 | pci_write_config_byte(dev, 0x09, 0x01); /* set as pci-pci bridge */ | ||
314 | pci_write_config_byte(dev, 0x7c, temp); /* restore pci bus debug control */ | ||
315 | dev->class |= 0x1; | ||
316 | } | ||
317 | |||
318 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_uli1575); | ||
319 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288); | ||
320 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229); | ||
321 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, 0x5249, early_uli5249); | ||
322 | #endif /* CONFIG_PCI */ | ||
99 | 323 | ||
100 | /* | 324 | /* |
101 | * Setup the architecture | 325 | * Setup the architecture |
102 | */ | 326 | */ |
103 | static void __init mpc8544_ds_setup_arch(void) | 327 | static void __init mpc8544_ds_setup_arch(void) |
104 | { | 328 | { |
329 | #ifdef CONFIG_PCI | ||
330 | struct device_node *np; | ||
331 | #endif | ||
332 | |||
105 | if (ppc_md.progress) | 333 | if (ppc_md.progress) |
106 | ppc_md.progress("mpc8544_ds_setup_arch()", 0); | 334 | ppc_md.progress("mpc8544_ds_setup_arch()", 0); |
107 | 335 | ||
336 | #ifdef CONFIG_PCI | ||
337 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) { | ||
338 | struct resource rsrc; | ||
339 | of_address_to_resource(np, 0, &rsrc); | ||
340 | if ((rsrc.start & 0xfffff) == 0xb000) | ||
341 | fsl_add_bridge(np, 1); | ||
342 | else | ||
343 | fsl_add_bridge(np, 0); | ||
344 | } | ||
345 | #endif | ||
346 | |||
108 | printk("MPC8544 DS board from Freescale Semiconductor\n"); | 347 | printk("MPC8544 DS board from Freescale Semiconductor\n"); |
109 | } | 348 | } |
110 | 349 | ||
111 | |||
112 | /* | 350 | /* |
113 | * Called very early, device-tree isn't unflattened | 351 | * Called very early, device-tree isn't unflattened |
114 | */ | 352 | */ |
@@ -124,6 +362,7 @@ define_machine(mpc8544_ds) { | |||
124 | .probe = mpc8544_ds_probe, | 362 | .probe = mpc8544_ds_probe, |
125 | .setup_arch = mpc8544_ds_setup_arch, | 363 | .setup_arch = mpc8544_ds_setup_arch, |
126 | .init_IRQ = mpc8544_ds_pic_init, | 364 | .init_IRQ = mpc8544_ds_pic_init, |
365 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
127 | .get_irq = mpic_get_irq, | 366 | .get_irq = mpic_get_irq, |
128 | .restart = mpc85xx_restart, | 367 | .restart = mpc85xx_restart, |
129 | .calibrate_decr = generic_calibrate_decr, | 368 | .calibrate_decr = generic_calibrate_decr, |
diff --git a/arch/powerpc/platforms/85xx/mpc85xx.h b/arch/powerpc/platforms/85xx/mpc85xx.h index 7286ffac2c1d..5b34deef12b5 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx.h +++ b/arch/powerpc/platforms/85xx/mpc85xx.h | |||
@@ -15,4 +15,3 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | extern void mpc85xx_restart(char *); | 17 | extern void mpc85xx_restart(char *); |
18 | extern int mpc85xx_add_bridge(struct device_node *dev); | ||
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c index 7235f702394c..40a828675c7b 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <asm/udbg.h> | 29 | #include <asm/udbg.h> |
30 | 30 | ||
31 | #include <sysdev/fsl_soc.h> | 31 | #include <sysdev/fsl_soc.h> |
32 | #include <sysdev/fsl_pci.h> | ||
32 | #include "mpc85xx.h" | 33 | #include "mpc85xx.h" |
33 | 34 | ||
34 | #ifdef CONFIG_CPM2 | 35 | #ifdef CONFIG_CPM2 |
@@ -217,7 +218,7 @@ static void __init mpc85xx_ads_setup_arch(void) | |||
217 | 218 | ||
218 | #ifdef CONFIG_PCI | 219 | #ifdef CONFIG_PCI |
219 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 220 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
220 | mpc85xx_add_bridge(np); | 221 | fsl_add_bridge(np, 1); |
221 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; | 222 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; |
222 | #endif | 223 | #endif |
223 | } | 224 | } |
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c index 50c8d6458362..6a171e9abf7d 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/seq_file.h> | 24 | #include <linux/seq_file.h> |
25 | #include <linux/initrd.h> | 25 | #include <linux/initrd.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/interrupt.h> | ||
27 | #include <linux/fsl_devices.h> | 28 | #include <linux/fsl_devices.h> |
28 | 29 | ||
29 | #include <asm/system.h> | 30 | #include <asm/system.h> |
@@ -45,6 +46,7 @@ | |||
45 | #include <asm/i8259.h> | 46 | #include <asm/i8259.h> |
46 | 47 | ||
47 | #include <sysdev/fsl_soc.h> | 48 | #include <sysdev/fsl_soc.h> |
49 | #include <sysdev/fsl_pci.h> | ||
48 | #include "mpc85xx.h" | 50 | #include "mpc85xx.h" |
49 | 51 | ||
50 | static int cds_pci_slot = 2; | 52 | static int cds_pci_slot = 2; |
@@ -58,8 +60,6 @@ static volatile u8 *cadmus; | |||
58 | static int mpc85xx_exclude_device(struct pci_controller *hose, | 60 | static int mpc85xx_exclude_device(struct pci_controller *hose, |
59 | u_char bus, u_char devfn) | 61 | u_char bus, u_char devfn) |
60 | { | 62 | { |
61 | if ((bus == hose->first_busno) && PCI_SLOT(devfn) == 0) | ||
62 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
63 | /* We explicitly do not go past the Tundra 320 Bridge */ | 63 | /* We explicitly do not go past the Tundra 320 Bridge */ |
64 | if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) | 64 | if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) |
65 | return PCIBIOS_DEVICE_NOT_FOUND; | 65 | return PCIBIOS_DEVICE_NOT_FOUND; |
@@ -69,6 +69,37 @@ static int mpc85xx_exclude_device(struct pci_controller *hose, | |||
69 | return PCIBIOS_SUCCESSFUL; | 69 | return PCIBIOS_SUCCESSFUL; |
70 | } | 70 | } |
71 | 71 | ||
72 | static void mpc85xx_cds_restart(char *cmd) | ||
73 | { | ||
74 | struct pci_dev *dev; | ||
75 | u_char tmp; | ||
76 | |||
77 | if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, | ||
78 | NULL))) { | ||
79 | |||
80 | /* Use the VIA Super Southbridge to force a PCI reset */ | ||
81 | pci_read_config_byte(dev, 0x47, &tmp); | ||
82 | pci_write_config_byte(dev, 0x47, tmp | 1); | ||
83 | |||
84 | /* Flush the outbound PCI write queues */ | ||
85 | pci_read_config_byte(dev, 0x47, &tmp); | ||
86 | |||
87 | /* | ||
88 | * At this point, the harware reset should have triggered. | ||
89 | * However, if it doesn't work for some mysterious reason, | ||
90 | * just fall through to the default reset below. | ||
91 | */ | ||
92 | |||
93 | pci_dev_put(dev); | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * If we can't find the VIA chip (maybe the P2P bridge is disabled) | ||
98 | * or the VIA chip reset didn't work, just use the default reset. | ||
99 | */ | ||
100 | mpc85xx_restart(NULL); | ||
101 | } | ||
102 | |||
72 | static void __init mpc85xx_cds_pci_irq_fixup(struct pci_dev *dev) | 103 | static void __init mpc85xx_cds_pci_irq_fixup(struct pci_dev *dev) |
73 | { | 104 | { |
74 | u_char c; | 105 | u_char c; |
@@ -98,7 +129,7 @@ static void __init mpc85xx_cds_pci_irq_fixup(struct pci_dev *dev) | |||
98 | /* There are two USB controllers. | 129 | /* There are two USB controllers. |
99 | * Identify them by functon number | 130 | * Identify them by functon number |
100 | */ | 131 | */ |
101 | if (PCI_FUNC(dev->devfn)) | 132 | if (PCI_FUNC(dev->devfn) == 3) |
102 | dev->irq = 11; | 133 | dev->irq = 11; |
103 | else | 134 | else |
104 | dev->irq = 10; | 135 | dev->irq = 10; |
@@ -109,17 +140,41 @@ static void __init mpc85xx_cds_pci_irq_fixup(struct pci_dev *dev) | |||
109 | } | 140 | } |
110 | } | 141 | } |
111 | 142 | ||
143 | static void __devinit skip_fake_bridge(struct pci_dev *dev) | ||
144 | { | ||
145 | /* Make it an error to skip the fake bridge | ||
146 | * in pci_setup_device() in probe.c */ | ||
147 | dev->hdr_type = 0x7f; | ||
148 | } | ||
149 | DECLARE_PCI_FIXUP_EARLY(0x1957, 0x3fff, skip_fake_bridge); | ||
150 | DECLARE_PCI_FIXUP_EARLY(0x3fff, 0x1957, skip_fake_bridge); | ||
151 | DECLARE_PCI_FIXUP_EARLY(0xff3f, 0x5719, skip_fake_bridge); | ||
152 | |||
112 | #ifdef CONFIG_PPC_I8259 | 153 | #ifdef CONFIG_PPC_I8259 |
113 | #warning The i8259 PIC support is currently broken | 154 | static void mpc85xx_8259_cascade_handler(unsigned int irq, |
114 | static void mpc85xx_8259_cascade(unsigned int irq, struct irq_desc *desc) | 155 | struct irq_desc *desc) |
115 | { | 156 | { |
116 | unsigned int cascade_irq = i8259_irq(); | 157 | unsigned int cascade_irq = i8259_irq(); |
117 | 158 | ||
118 | if (cascade_irq != NO_IRQ) | 159 | if (cascade_irq != NO_IRQ) |
160 | /* handle an interrupt from the 8259 */ | ||
119 | generic_handle_irq(cascade_irq); | 161 | generic_handle_irq(cascade_irq); |
120 | 162 | ||
121 | desc->chip->eoi(irq); | 163 | /* check for any interrupts from the shared IRQ line */ |
164 | handle_fasteoi_irq(irq, desc); | ||
165 | } | ||
166 | |||
167 | static irqreturn_t mpc85xx_8259_cascade_action(int irq, void *dev_id) | ||
168 | { | ||
169 | return IRQ_HANDLED; | ||
122 | } | 170 | } |
171 | |||
172 | static struct irqaction mpc85xxcds_8259_irqaction = { | ||
173 | .handler = mpc85xx_8259_cascade_action, | ||
174 | .flags = IRQF_SHARED, | ||
175 | .mask = CPU_MASK_NONE, | ||
176 | .name = "8259 cascade", | ||
177 | }; | ||
123 | #endif /* PPC_I8259 */ | 178 | #endif /* PPC_I8259 */ |
124 | #endif /* CONFIG_PCI */ | 179 | #endif /* CONFIG_PCI */ |
125 | 180 | ||
@@ -128,10 +183,6 @@ static void __init mpc85xx_cds_pic_init(void) | |||
128 | struct mpic *mpic; | 183 | struct mpic *mpic; |
129 | struct resource r; | 184 | struct resource r; |
130 | struct device_node *np = NULL; | 185 | struct device_node *np = NULL; |
131 | #ifdef CONFIG_PPC_I8259 | ||
132 | struct device_node *cascade_node = NULL; | ||
133 | int cascade_irq; | ||
134 | #endif | ||
135 | 186 | ||
136 | np = of_find_node_by_type(np, "open-pic"); | 187 | np = of_find_node_by_type(np, "open-pic"); |
137 | 188 | ||
@@ -155,8 +206,19 @@ static void __init mpc85xx_cds_pic_init(void) | |||
155 | of_node_put(np); | 206 | of_node_put(np); |
156 | 207 | ||
157 | mpic_init(mpic); | 208 | mpic_init(mpic); |
209 | } | ||
210 | |||
211 | #if defined(CONFIG_PPC_I8259) && defined(CONFIG_PCI) | ||
212 | static int mpc85xx_cds_8259_attach(void) | ||
213 | { | ||
214 | int ret; | ||
215 | struct device_node *np = NULL; | ||
216 | struct device_node *cascade_node = NULL; | ||
217 | int cascade_irq; | ||
218 | |||
219 | if (!machine_is(mpc85xx_cds)) | ||
220 | return 0; | ||
158 | 221 | ||
159 | #ifdef CONFIG_PPC_I8259 | ||
160 | /* Initialize the i8259 controller */ | 222 | /* Initialize the i8259 controller */ |
161 | for_each_node_by_type(np, "interrupt-controller") | 223 | for_each_node_by_type(np, "interrupt-controller") |
162 | if (of_device_is_compatible(np, "chrp,iic")) { | 224 | if (of_device_is_compatible(np, "chrp,iic")) { |
@@ -166,22 +228,39 @@ static void __init mpc85xx_cds_pic_init(void) | |||
166 | 228 | ||
167 | if (cascade_node == NULL) { | 229 | if (cascade_node == NULL) { |
168 | printk(KERN_DEBUG "Could not find i8259 PIC\n"); | 230 | printk(KERN_DEBUG "Could not find i8259 PIC\n"); |
169 | return; | 231 | return -ENODEV; |
170 | } | 232 | } |
171 | 233 | ||
172 | cascade_irq = irq_of_parse_and_map(cascade_node, 0); | 234 | cascade_irq = irq_of_parse_and_map(cascade_node, 0); |
173 | if (cascade_irq == NO_IRQ) { | 235 | if (cascade_irq == NO_IRQ) { |
174 | printk(KERN_ERR "Failed to map cascade interrupt\n"); | 236 | printk(KERN_ERR "Failed to map cascade interrupt\n"); |
175 | return; | 237 | return -ENXIO; |
176 | } | 238 | } |
177 | 239 | ||
178 | i8259_init(cascade_node, 0); | 240 | i8259_init(cascade_node, 0); |
179 | of_node_put(cascade_node); | 241 | of_node_put(cascade_node); |
180 | 242 | ||
181 | set_irq_chained_handler(cascade_irq, mpc85xx_8259_cascade); | 243 | /* |
182 | #endif /* CONFIG_PPC_I8259 */ | 244 | * Hook the interrupt to make sure desc->action is never NULL. |
245 | * This is required to ensure that the interrupt does not get | ||
246 | * disabled when the last user of the shared IRQ line frees their | ||
247 | * interrupt. | ||
248 | */ | ||
249 | if ((ret = setup_irq(cascade_irq, &mpc85xxcds_8259_irqaction))) { | ||
250 | printk(KERN_ERR "Failed to setup cascade interrupt\n"); | ||
251 | return ret; | ||
252 | } | ||
253 | |||
254 | /* Success. Connect our low-level cascade handler. */ | ||
255 | set_irq_handler(cascade_irq, mpc85xx_8259_cascade_handler); | ||
256 | |||
257 | return 0; | ||
183 | } | 258 | } |
184 | 259 | ||
260 | device_initcall(mpc85xx_cds_8259_attach); | ||
261 | |||
262 | #endif /* CONFIG_PPC_I8259 */ | ||
263 | |||
185 | /* | 264 | /* |
186 | * Setup the architecture | 265 | * Setup the architecture |
187 | */ | 266 | */ |
@@ -218,9 +297,14 @@ static void __init mpc85xx_cds_setup_arch(void) | |||
218 | } | 297 | } |
219 | 298 | ||
220 | #ifdef CONFIG_PCI | 299 | #ifdef CONFIG_PCI |
221 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 300 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) { |
222 | mpc85xx_add_bridge(np); | 301 | struct resource rsrc; |
223 | 302 | of_address_to_resource(np, 0, &rsrc); | |
303 | if ((rsrc.start & 0xfffff) == 0x8000) | ||
304 | fsl_add_bridge(np, 1); | ||
305 | else | ||
306 | fsl_add_bridge(np, 0); | ||
307 | } | ||
224 | ppc_md.pci_irq_fixup = mpc85xx_cds_pci_irq_fixup; | 308 | ppc_md.pci_irq_fixup = mpc85xx_cds_pci_irq_fixup; |
225 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; | 309 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; |
226 | #endif | 310 | #endif |
@@ -265,7 +349,12 @@ define_machine(mpc85xx_cds) { | |||
265 | .init_IRQ = mpc85xx_cds_pic_init, | 349 | .init_IRQ = mpc85xx_cds_pic_init, |
266 | .show_cpuinfo = mpc85xx_cds_show_cpuinfo, | 350 | .show_cpuinfo = mpc85xx_cds_show_cpuinfo, |
267 | .get_irq = mpic_get_irq, | 351 | .get_irq = mpic_get_irq, |
352 | #ifdef CONFIG_PCI | ||
353 | .restart = mpc85xx_cds_restart, | ||
354 | #else | ||
268 | .restart = mpc85xx_restart, | 355 | .restart = mpc85xx_restart, |
356 | #endif | ||
269 | .calibrate_decr = generic_calibrate_decr, | 357 | .calibrate_decr = generic_calibrate_decr, |
270 | .progress = udbg_progress, | 358 | .progress = udbg_progress, |
359 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
271 | }; | 360 | }; |
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index 004b80bd0b84..e8003bf00c9a 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <asm/prom.h> | 46 | #include <asm/prom.h> |
47 | #include <asm/udbg.h> | 47 | #include <asm/udbg.h> |
48 | #include <sysdev/fsl_soc.h> | 48 | #include <sysdev/fsl_soc.h> |
49 | #include <sysdev/fsl_pci.h> | ||
49 | #include <asm/qe.h> | 50 | #include <asm/qe.h> |
50 | #include <asm/qe_ic.h> | 51 | #include <asm/qe_ic.h> |
51 | #include <asm/mpic.h> | 52 | #include <asm/mpic.h> |
@@ -94,9 +95,8 @@ static void __init mpc85xx_mds_setup_arch(void) | |||
94 | } | 95 | } |
95 | 96 | ||
96 | #ifdef CONFIG_PCI | 97 | #ifdef CONFIG_PCI |
97 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) { | 98 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
98 | mpc85xx_add_bridge(np); | 99 | fsl_add_bridge(np, 1); |
99 | } | ||
100 | of_node_put(np); | 100 | of_node_put(np); |
101 | #endif | 101 | #endif |
102 | 102 | ||
@@ -208,4 +208,5 @@ define_machine(mpc85xx_mds) { | |||
208 | .restart = mpc85xx_restart, | 208 | .restart = mpc85xx_restart, |
209 | .calibrate_decr = generic_calibrate_decr, | 209 | .calibrate_decr = generic_calibrate_decr, |
210 | .progress = udbg_progress, | 210 | .progress = udbg_progress, |
211 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
211 | }; | 212 | }; |
diff --git a/arch/powerpc/platforms/85xx/pci.c b/arch/powerpc/platforms/85xx/pci.c deleted file mode 100644 index 8118417b7364..000000000000 --- a/arch/powerpc/platforms/85xx/pci.c +++ /dev/null | |||
@@ -1,91 +0,0 @@ | |||
1 | /* | ||
2 | * FSL SoC setup code | ||
3 | * | ||
4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/stddef.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/pci.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/irq.h> | ||
19 | #include <linux/module.h> | ||
20 | |||
21 | #include <asm/system.h> | ||
22 | #include <asm/atomic.h> | ||
23 | #include <asm/io.h> | ||
24 | #include <asm/pci-bridge.h> | ||
25 | #include <asm/prom.h> | ||
26 | #include <sysdev/fsl_soc.h> | ||
27 | |||
28 | #undef DEBUG | ||
29 | |||
30 | #ifdef DEBUG | ||
31 | #define DBG(x...) printk(x) | ||
32 | #else | ||
33 | #define DBG(x...) | ||
34 | #endif | ||
35 | |||
36 | #ifdef CONFIG_PCI | ||
37 | int __init mpc85xx_add_bridge(struct device_node *dev) | ||
38 | { | ||
39 | int len; | ||
40 | struct pci_controller *hose; | ||
41 | struct resource rsrc; | ||
42 | const int *bus_range; | ||
43 | int primary = 1, has_address = 0; | ||
44 | phys_addr_t immr = get_immrbase(); | ||
45 | |||
46 | DBG("Adding PCI host bridge %s\n", dev->full_name); | ||
47 | |||
48 | /* Fetch host bridge registers address */ | ||
49 | has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); | ||
50 | |||
51 | /* Get bus range if any */ | ||
52 | bus_range = of_get_property(dev, "bus-range", &len); | ||
53 | if (bus_range == NULL || len < 2 * sizeof(int)) { | ||
54 | printk(KERN_WARNING "Can't get bus-range for %s, assume" | ||
55 | " bus 0\n", dev->full_name); | ||
56 | } | ||
57 | |||
58 | pci_assign_all_buses = 1; | ||
59 | hose = pcibios_alloc_controller(dev); | ||
60 | if (!hose) | ||
61 | return -ENOMEM; | ||
62 | |||
63 | hose->first_busno = bus_range ? bus_range[0] : 0; | ||
64 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | ||
65 | |||
66 | /* PCI 1 */ | ||
67 | if ((rsrc.start & 0xfffff) == 0x8000) { | ||
68 | setup_indirect_pci(hose, immr + 0x8000, immr + 0x8004); | ||
69 | } | ||
70 | /* PCI 2 */ | ||
71 | if ((rsrc.start & 0xfffff) == 0x9000) { | ||
72 | setup_indirect_pci(hose, immr + 0x9000, immr + 0x9004); | ||
73 | primary = 0; | ||
74 | } | ||
75 | |||
76 | printk(KERN_INFO "Found MPC85xx PCI host bridge at 0x%016llx. " | ||
77 | "Firmware bus number: %d->%d\n", | ||
78 | (unsigned long long)rsrc.start, hose->first_busno, | ||
79 | hose->last_busno); | ||
80 | |||
81 | DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", | ||
82 | hose, hose->cfg_addr, hose->cfg_data); | ||
83 | |||
84 | /* Interpret the "ranges" property */ | ||
85 | /* This also maps the I/O region and sets isa_io/mem_base */ | ||
86 | pci_process_bridge_OF_ranges(hose, dev, primary); | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | #endif | ||
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index 0faebfdc1596..343b76d0d793 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig | |||
@@ -14,8 +14,7 @@ endchoice | |||
14 | 14 | ||
15 | config MPC8641 | 15 | config MPC8641 |
16 | bool | 16 | bool |
17 | select PPC_INDIRECT_PCI | 17 | select FSL_PCI if PCI |
18 | select PPC_INDIRECT_PCI_BE | ||
19 | select PPC_UDBG_16550 | 18 | select PPC_UDBG_16550 |
20 | select MPIC | 19 | select MPIC |
21 | default y if MPC8641_HPCN | 20 | default y if MPC8641_HPCN |
diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile index 418fd8f4d268..3376c7767f2d 100644 --- a/arch/powerpc/platforms/86xx/Makefile +++ b/arch/powerpc/platforms/86xx/Makefile | |||
@@ -4,4 +4,3 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_SMP) += mpc86xx_smp.o | 5 | obj-$(CONFIG_SMP) += mpc86xx_smp.o |
6 | obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o | 6 | obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o |
7 | obj-$(CONFIG_PCI) += pci.o | ||
diff --git a/arch/powerpc/platforms/86xx/mpc86xx.h b/arch/powerpc/platforms/86xx/mpc86xx.h index 23f7ed2a7f88..525ffa1904f9 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx.h +++ b/arch/powerpc/platforms/86xx/mpc86xx.h | |||
@@ -15,11 +15,6 @@ | |||
15 | * mpc86xx_* files. Mostly for use by mpc86xx_setup(). | 15 | * mpc86xx_* files. Mostly for use by mpc86xx_setup(). |
16 | */ | 16 | */ |
17 | 17 | ||
18 | extern int mpc86xx_add_bridge(struct device_node *dev); | ||
19 | |||
20 | extern int mpc86xx_exclude_device(struct pci_controller *hose, | ||
21 | u_char bus, u_char devfn); | ||
22 | |||
23 | extern void __init mpc86xx_smp_init(void); | 18 | extern void __init mpc86xx_smp_init(void); |
24 | 19 | ||
25 | #endif /* __MPC86XX_H__ */ | 20 | #endif /* __MPC86XX_H__ */ |
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c index 5b01ec7c13dc..e9eaa0749ae6 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c | |||
@@ -31,6 +31,7 @@ | |||
31 | 31 | ||
32 | #include <asm/mpic.h> | 32 | #include <asm/mpic.h> |
33 | 33 | ||
34 | #include <sysdev/fsl_pci.h> | ||
34 | #include <sysdev/fsl_soc.h> | 35 | #include <sysdev/fsl_soc.h> |
35 | 36 | ||
36 | #include "mpc86xx.h" | 37 | #include "mpc86xx.h" |
@@ -344,8 +345,14 @@ mpc86xx_hpcn_setup_arch(void) | |||
344 | } | 345 | } |
345 | 346 | ||
346 | #ifdef CONFIG_PCI | 347 | #ifdef CONFIG_PCI |
347 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 348 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) { |
348 | mpc86xx_add_bridge(np); | 349 | struct resource rsrc; |
350 | of_address_to_resource(np, 0, &rsrc); | ||
351 | if ((rsrc.start & 0xfffff) == 0x8000) | ||
352 | fsl_add_bridge(np, 1); | ||
353 | else | ||
354 | fsl_add_bridge(np, 0); | ||
355 | } | ||
349 | #endif | 356 | #endif |
350 | 357 | ||
351 | printk("MPC86xx HPCN board from Freescale Semiconductor\n"); | 358 | printk("MPC86xx HPCN board from Freescale Semiconductor\n"); |
@@ -424,7 +431,6 @@ mpc86xx_time_init(void) | |||
424 | return 0; | 431 | return 0; |
425 | } | 432 | } |
426 | 433 | ||
427 | |||
428 | define_machine(mpc86xx_hpcn) { | 434 | define_machine(mpc86xx_hpcn) { |
429 | .name = "MPC86xx HPCN", | 435 | .name = "MPC86xx HPCN", |
430 | .probe = mpc86xx_hpcn_probe, | 436 | .probe = mpc86xx_hpcn_probe, |
@@ -436,4 +442,5 @@ define_machine(mpc86xx_hpcn) { | |||
436 | .time_init = mpc86xx_time_init, | 442 | .time_init = mpc86xx_time_init, |
437 | .calibrate_decr = generic_calibrate_decr, | 443 | .calibrate_decr = generic_calibrate_decr, |
438 | .progress = udbg_progress, | 444 | .progress = udbg_progress, |
445 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
439 | }; | 446 | }; |
diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c deleted file mode 100644 index 73cd5b05a84e..000000000000 --- a/arch/powerpc/platforms/86xx/pci.c +++ /dev/null | |||
@@ -1,238 +0,0 @@ | |||
1 | /* | ||
2 | * MPC86XX pci setup code | ||
3 | * | ||
4 | * Recode: ZHANG WEI <wei.zhang@freescale.com> | ||
5 | * Initial author: Xianghua Xiao <x.xiao@freescale.com> | ||
6 | * | ||
7 | * Copyright 2006 Freescale Semiconductor 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/types.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/pci.h> | ||
19 | #include <linux/serial.h> | ||
20 | |||
21 | #include <asm/system.h> | ||
22 | #include <asm/atomic.h> | ||
23 | #include <asm/io.h> | ||
24 | #include <asm/prom.h> | ||
25 | #include <asm/pci-bridge.h> | ||
26 | #include <sysdev/fsl_soc.h> | ||
27 | #include <sysdev/fsl_pcie.h> | ||
28 | |||
29 | #include "mpc86xx.h" | ||
30 | |||
31 | #undef DEBUG | ||
32 | |||
33 | #ifdef DEBUG | ||
34 | #define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args) | ||
35 | #else | ||
36 | #define DBG(fmt, args...) | ||
37 | #endif | ||
38 | |||
39 | struct pcie_outbound_window_regs { | ||
40 | uint pexotar; /* 0x.0 - PCI Express outbound translation address register */ | ||
41 | uint pexotear; /* 0x.4 - PCI Express outbound translation extended address register */ | ||
42 | uint pexowbar; /* 0x.8 - PCI Express outbound window base address register */ | ||
43 | char res1[4]; | ||
44 | uint pexowar; /* 0x.10 - PCI Express outbound window attributes register */ | ||
45 | char res2[12]; | ||
46 | }; | ||
47 | |||
48 | struct pcie_inbound_window_regs { | ||
49 | uint pexitar; /* 0x.0 - PCI Express inbound translation address register */ | ||
50 | char res1[4]; | ||
51 | uint pexiwbar; /* 0x.8 - PCI Express inbound window base address register */ | ||
52 | uint pexiwbear; /* 0x.c - PCI Express inbound window base extended address register */ | ||
53 | uint pexiwar; /* 0x.10 - PCI Express inbound window attributes register */ | ||
54 | char res2[12]; | ||
55 | }; | ||
56 | |||
57 | static void __init setup_pcie_atmu(struct pci_controller *hose, struct resource *rsrc) | ||
58 | { | ||
59 | volatile struct ccsr_pex *pcie; | ||
60 | volatile struct pcie_outbound_window_regs *pcieow; | ||
61 | volatile struct pcie_inbound_window_regs *pcieiw; | ||
62 | int i = 0; | ||
63 | |||
64 | DBG("PCIE memory map start 0x%x, size 0x%x\n", rsrc->start, | ||
65 | rsrc->end - rsrc->start + 1); | ||
66 | pcie = ioremap(rsrc->start, rsrc->end - rsrc->start + 1); | ||
67 | |||
68 | /* Disable all windows (except pexowar0 since its ignored) */ | ||
69 | pcie->pexowar1 = 0; | ||
70 | pcie->pexowar2 = 0; | ||
71 | pcie->pexowar3 = 0; | ||
72 | pcie->pexowar4 = 0; | ||
73 | pcie->pexiwar1 = 0; | ||
74 | pcie->pexiwar2 = 0; | ||
75 | pcie->pexiwar3 = 0; | ||
76 | |||
77 | pcieow = (struct pcie_outbound_window_regs *)&pcie->pexotar1; | ||
78 | pcieiw = (struct pcie_inbound_window_regs *)&pcie->pexitar1; | ||
79 | |||
80 | /* Setup outbound MEM window */ | ||
81 | for(i = 0; i < 3; i++) | ||
82 | if (hose->mem_resources[i].flags & IORESOURCE_MEM){ | ||
83 | DBG("PCIE MEM resource start 0x%08x, size 0x%08x.\n", | ||
84 | hose->mem_resources[i].start, | ||
85 | hose->mem_resources[i].end | ||
86 | - hose->mem_resources[i].start + 1); | ||
87 | pcieow->pexotar = (hose->mem_resources[i].start) >> 12 | ||
88 | & 0x000fffff; | ||
89 | pcieow->pexotear = 0; | ||
90 | pcieow->pexowbar = (hose->mem_resources[i].start) >> 12 | ||
91 | & 0x000fffff; | ||
92 | /* Enable, Mem R/W */ | ||
93 | pcieow->pexowar = 0x80044000 | | ||
94 | (__ilog2(hose->mem_resources[i].end | ||
95 | - hose->mem_resources[i].start + 1) | ||
96 | - 1); | ||
97 | pcieow++; | ||
98 | } | ||
99 | |||
100 | /* Setup outbound IO window */ | ||
101 | if (hose->io_resource.flags & IORESOURCE_IO){ | ||
102 | DBG("PCIE IO resource start 0x%08x, size 0x%08x, phy base 0x%08x.\n", | ||
103 | hose->io_resource.start, | ||
104 | hose->io_resource.end - hose->io_resource.start + 1, | ||
105 | hose->io_base_phys); | ||
106 | pcieow->pexotar = (hose->io_resource.start) >> 12 & 0x000fffff; | ||
107 | pcieow->pexotear = 0; | ||
108 | pcieow->pexowbar = (hose->io_base_phys) >> 12 & 0x000fffff; | ||
109 | /* Enable, IO R/W */ | ||
110 | pcieow->pexowar = 0x80088000 | (__ilog2(hose->io_resource.end | ||
111 | - hose->io_resource.start + 1) - 1); | ||
112 | } | ||
113 | |||
114 | /* Setup 2G inbound Memory Window @ 0 */ | ||
115 | pcieiw->pexitar = 0x00000000; | ||
116 | pcieiw->pexiwbar = 0x00000000; | ||
117 | /* Enable, Prefetch, Local Mem, Snoop R/W, 2G */ | ||
118 | pcieiw->pexiwar = 0xa0f5501e; | ||
119 | } | ||
120 | |||
121 | static void __init | ||
122 | mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size) | ||
123 | { | ||
124 | u16 cmd; | ||
125 | |||
126 | DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n", | ||
127 | pcie_offset, pcie_size); | ||
128 | |||
129 | early_read_config_word(hose, 0, 0, PCI_COMMAND, &cmd); | ||
130 | cmd |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | ||
131 | | PCI_COMMAND_IO; | ||
132 | early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd); | ||
133 | |||
134 | early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80); | ||
135 | } | ||
136 | |||
137 | static void __devinit quirk_fsl_pcie_transparent(struct pci_dev *dev) | ||
138 | { | ||
139 | struct resource *res; | ||
140 | int i, res_idx = PCI_BRIDGE_RESOURCES; | ||
141 | struct pci_controller *hose; | ||
142 | |||
143 | /* | ||
144 | * Make the bridge be transparent. | ||
145 | */ | ||
146 | dev->transparent = 1; | ||
147 | |||
148 | hose = pci_bus_to_host(dev->bus); | ||
149 | if (!hose) { | ||
150 | printk(KERN_ERR "Can't find hose for bus %d\n", | ||
151 | dev->bus->number); | ||
152 | return; | ||
153 | } | ||
154 | |||
155 | if (hose->io_resource.flags) { | ||
156 | res = &dev->resource[res_idx++]; | ||
157 | res->start = hose->io_resource.start; | ||
158 | res->end = hose->io_resource.end; | ||
159 | res->flags = hose->io_resource.flags; | ||
160 | } | ||
161 | |||
162 | for (i = 0; i < 3; i++) { | ||
163 | res = &dev->resource[res_idx + i]; | ||
164 | res->start = hose->mem_resources[i].start; | ||
165 | res->end = hose->mem_resources[i].end; | ||
166 | res->flags = hose->mem_resources[i].flags; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | |||
171 | DECLARE_PCI_FIXUP_EARLY(0x1957, 0x7010, quirk_fsl_pcie_transparent); | ||
172 | DECLARE_PCI_FIXUP_EARLY(0x1957, 0x7011, quirk_fsl_pcie_transparent); | ||
173 | |||
174 | #define PCIE_LTSSM 0x404 /* PCIe Link Training and Status */ | ||
175 | #define PCIE_LTSSM_L0 0x16 /* L0 state */ | ||
176 | |||
177 | int __init mpc86xx_add_bridge(struct device_node *dev) | ||
178 | { | ||
179 | int len; | ||
180 | struct pci_controller *hose; | ||
181 | struct resource rsrc; | ||
182 | const int *bus_range; | ||
183 | int has_address = 0; | ||
184 | int primary = 0; | ||
185 | u16 val; | ||
186 | |||
187 | DBG("Adding PCIE host bridge %s\n", dev->full_name); | ||
188 | |||
189 | /* Fetch host bridge registers address */ | ||
190 | has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); | ||
191 | |||
192 | /* Get bus range if any */ | ||
193 | bus_range = of_get_property(dev, "bus-range", &len); | ||
194 | if (bus_range == NULL || len < 2 * sizeof(int)) | ||
195 | printk(KERN_WARNING "Can't get bus-range for %s, assume" | ||
196 | " bus 0\n", dev->full_name); | ||
197 | |||
198 | pci_assign_all_buses = 1; | ||
199 | hose = pcibios_alloc_controller(dev); | ||
200 | if (!hose) | ||
201 | return -ENOMEM; | ||
202 | |||
203 | hose->indirect_type = PPC_INDIRECT_TYPE_EXT_REG | | ||
204 | PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS; | ||
205 | |||
206 | hose->first_busno = bus_range ? bus_range[0] : 0x0; | ||
207 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | ||
208 | |||
209 | setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4); | ||
210 | |||
211 | /* Probe the hose link training status */ | ||
212 | early_read_config_word(hose, 0, 0, PCIE_LTSSM, &val); | ||
213 | if (val < PCIE_LTSSM_L0) | ||
214 | return -ENXIO; | ||
215 | |||
216 | /* Setup the PCIE host controller. */ | ||
217 | mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1); | ||
218 | |||
219 | if ((rsrc.start & 0xfffff) == 0x8000) | ||
220 | primary = 1; | ||
221 | |||
222 | printk(KERN_INFO "Found MPC86xx PCIE host bridge at 0x%08lx. " | ||
223 | "Firmware bus number: %d->%d\n", | ||
224 | (unsigned long) rsrc.start, | ||
225 | hose->first_busno, hose->last_busno); | ||
226 | |||
227 | DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", | ||
228 | hose, hose->cfg_addr, hose->cfg_data); | ||
229 | |||
230 | /* Interpret the "ranges" property */ | ||
231 | /* This also maps the I/O region and sets isa_io/mem_base */ | ||
232 | pci_process_bridge_OF_ranges(hose, dev, primary); | ||
233 | |||
234 | /* Setup PEX window registers */ | ||
235 | setup_pcie_atmu(hose, &rsrc); | ||
236 | |||
237 | return 0; | ||
238 | } | ||
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index 6694f86d7000..9cb081c26e71 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c | |||
@@ -59,7 +59,8 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang) | |||
59 | INIT_LIST_HEAD(&ctx->aff_list); | 59 | INIT_LIST_HEAD(&ctx->aff_list); |
60 | if (gang) | 60 | if (gang) |
61 | spu_gang_add_ctx(gang, ctx); | 61 | spu_gang_add_ctx(gang, ctx); |
62 | ctx->cpus_allowed = current->cpus_allowed; | 62 | |
63 | __spu_update_sched_info(ctx); | ||
63 | spu_set_timeslice(ctx); | 64 | spu_set_timeslice(ctx); |
64 | ctx->stats.util_state = SPU_UTIL_IDLE_LOADED; | 65 | ctx->stats.util_state = SPU_UTIL_IDLE_LOADED; |
65 | 66 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index 0b50fa5cb39d..6abdd8fe2098 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c | |||
@@ -312,6 +312,7 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event) | |||
312 | spu_acquire(ctx); | 312 | spu_acquire(ctx); |
313 | if (ctx->state == SPU_STATE_SAVED) { | 313 | if (ctx->state == SPU_STATE_SAVED) { |
314 | __spu_update_sched_info(ctx); | 314 | __spu_update_sched_info(ctx); |
315 | spu_set_timeslice(ctx); | ||
315 | 316 | ||
316 | ret = spu_activate(ctx, 0); | 317 | ret = spu_activate(ctx, 0); |
317 | if (ret) { | 318 | if (ret) { |
@@ -322,6 +323,9 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event) | |||
322 | /* | 323 | /* |
323 | * We have to update the scheduling priority under active_mutex | 324 | * We have to update the scheduling priority under active_mutex |
324 | * to protect against find_victim(). | 325 | * to protect against find_victim(). |
326 | * | ||
327 | * No need to update the timeslice ASAP, it will get updated | ||
328 | * once the current one has expired. | ||
325 | */ | 329 | */ |
326 | spu_update_sched_info(ctx); | 330 | spu_update_sched_info(ctx); |
327 | } | 331 | } |
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 227968b4779d..758a80ac080a 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c | |||
@@ -927,10 +927,6 @@ int __init spu_sched_init(void) | |||
927 | INIT_LIST_HEAD(&spu_prio->runq[i]); | 927 | INIT_LIST_HEAD(&spu_prio->runq[i]); |
928 | __clear_bit(i, spu_prio->bitmap); | 928 | __clear_bit(i, spu_prio->bitmap); |
929 | } | 929 | } |
930 | for (i = 0; i < MAX_NUMNODES; i++) { | ||
931 | mutex_init(&cbe_spu_info[i].list_mutex); | ||
932 | INIT_LIST_HEAD(&cbe_spu_info[i].spus); | ||
933 | } | ||
934 | spin_lock_init(&spu_prio->runq_lock); | 930 | spin_lock_init(&spu_prio->runq_lock); |
935 | 931 | ||
936 | setup_timer(&spusched_timer, spusched_wake, 0); | 932 | setup_timer(&spusched_timer, spusched_wake, 0); |
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index 3690624e49d4..28d1647b204e 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c | |||
@@ -181,7 +181,7 @@ setup_python(struct pci_controller *hose, struct device_node *dev) | |||
181 | } | 181 | } |
182 | iounmap(reg); | 182 | iounmap(reg); |
183 | 183 | ||
184 | setup_indirect_pci(hose, r.start + 0xf8000, r.start + 0xf8010); | 184 | setup_indirect_pci(hose, r.start + 0xf8000, r.start + 0xf8010, 0); |
185 | } | 185 | } |
186 | 186 | ||
187 | /* Marvell Discovery II based Pegasos 2 */ | 187 | /* Marvell Discovery II based Pegasos 2 */ |
@@ -277,13 +277,14 @@ chrp_find_bridges(void) | |||
277 | hose->cfg_data = p; | 277 | hose->cfg_data = p; |
278 | gg2_pci_config_base = p; | 278 | gg2_pci_config_base = p; |
279 | } else if (is_pegasos == 1) { | 279 | } else if (is_pegasos == 1) { |
280 | setup_indirect_pci(hose, 0xfec00cf8, 0xfee00cfc); | 280 | setup_indirect_pci(hose, 0xfec00cf8, 0xfee00cfc, 0); |
281 | } else if (is_pegasos == 2) { | 281 | } else if (is_pegasos == 2) { |
282 | setup_peg2(hose, dev); | 282 | setup_peg2(hose, dev); |
283 | } else if (!strncmp(model, "IBM,CPC710", 10)) { | 283 | } else if (!strncmp(model, "IBM,CPC710", 10)) { |
284 | setup_indirect_pci(hose, | 284 | setup_indirect_pci(hose, |
285 | r.start + 0x000f8000, | 285 | r.start + 0x000f8000, |
286 | r.start + 0x000f8010); | 286 | r.start + 0x000f8010, |
287 | 0); | ||
287 | if (index == 0) { | 288 | if (index == 0) { |
288 | dma = of_get_property(dev, "system-dma-base", | 289 | dma = of_get_property(dev, "system-dma-base", |
289 | &len); | 290 | &len); |
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c index f4d0a7a603f5..bd5ca58345a1 100644 --- a/arch/powerpc/platforms/embedded6xx/linkstation.c +++ b/arch/powerpc/platforms/embedded6xx/linkstation.c | |||
@@ -73,7 +73,7 @@ static int __init linkstation_add_bridge(struct device_node *dev) | |||
73 | return -ENOMEM; | 73 | return -ENOMEM; |
74 | hose->first_busno = bus_range ? bus_range[0] : 0; | 74 | hose->first_busno = bus_range ? bus_range[0] : 0; |
75 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 75 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
76 | setup_indirect_pci(hose, 0xfec00000, 0xfee00000); | 76 | setup_indirect_pci(hose, 0xfec00000, 0xfee00000, 0); |
77 | 77 | ||
78 | /* Interpret the "ranges" property */ | 78 | /* Interpret the "ranges" property */ |
79 | /* This also maps the I/O region and sets isa_io/mem_base */ | 79 | /* This also maps the I/O region and sets isa_io/mem_base */ |
diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c index 91df52a1899a..34bdbbe3ce59 100644 --- a/arch/powerpc/platforms/iseries/lpevents.c +++ b/arch/powerpc/platforms/iseries/lpevents.c | |||
@@ -182,7 +182,7 @@ static int set_spread_lpevents(char *str) | |||
182 | } | 182 | } |
183 | __setup("spread_lpevents=", set_spread_lpevents); | 183 | __setup("spread_lpevents=", set_spread_lpevents); |
184 | 184 | ||
185 | void setup_hvlpevent_queue(void) | 185 | void __init setup_hvlpevent_queue(void) |
186 | { | 186 | { |
187 | void *eventStack; | 187 | void *eventStack; |
188 | 188 | ||
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index fceaae40fe70..2542403288f9 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c | |||
@@ -490,6 +490,9 @@ static int __init maple_add_bridge(struct device_node *dev) | |||
490 | /* Fixup "bus-range" OF property */ | 490 | /* Fixup "bus-range" OF property */ |
491 | fixup_bus_range(dev); | 491 | fixup_bus_range(dev); |
492 | 492 | ||
493 | /* Check for legacy IOs */ | ||
494 | isa_bridge_find_early(hose); | ||
495 | |||
493 | return 0; | 496 | return 0; |
494 | } | 497 | } |
495 | 498 | ||