diff options
author | Ishizaki Kou <kou.ishizaki@toshiba.co.jp> | 2008-04-24 05:24:13 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-04-24 07:08:13 -0400 |
commit | 6ec859e1b21ab42bfc36bb3b51db275480165c8a (patch) | |
tree | 299d0729340598d795559084a11c2fdfc61ce199 | |
parent | 7cfb62a2e820b6032c08835dbd996d8518af14a3 (diff) |
[POWERPC] celleb: Consolidate io-workarounds code
Now, we can use generic io-workarounds mechanism and the workaround
code for spider-pci. This changes Celleb PCI code to use spider-pci
code.
Signed-off-by: Kou Ishizaki <kou.ishizaki@toshiba.co.jp>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r-- | arch/powerpc/platforms/cell/Makefile | 6 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/Makefile | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/io-workarounds.c | 280 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/pci.c | 41 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/pci.h | 18 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/scc_epci.c | 59 | ||||
-rw-r--r-- | arch/powerpc/platforms/celleb/setup.c | 2 |
7 files changed, 52 insertions, 357 deletions
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index 20966b709604..81c26f32453e 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile | |||
@@ -27,3 +27,9 @@ obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \ | |||
27 | spufs/ | 27 | spufs/ |
28 | 28 | ||
29 | obj-$(CONFIG_PCI_MSI) += axon_msi.o | 29 | obj-$(CONFIG_PCI_MSI) += axon_msi.o |
30 | |||
31 | |||
32 | # celleb stuff | ||
33 | ifeq ($(CONFIG_PPC_CELLEB),y) | ||
34 | obj-y += io-workarounds.o spider-pci.o | ||
35 | endif | ||
diff --git a/arch/powerpc/platforms/celleb/Makefile b/arch/powerpc/platforms/celleb/Makefile index 889d43f715ea..6d51a3c00713 100644 --- a/arch/powerpc/platforms/celleb/Makefile +++ b/arch/powerpc/platforms/celleb/Makefile | |||
@@ -1,7 +1,6 @@ | |||
1 | obj-y += interrupt.o iommu.o setup.o \ | 1 | obj-y += interrupt.o iommu.o setup.o \ |
2 | htab.o beat.o hvCall.o pci.o \ | 2 | htab.o beat.o hvCall.o pci.o \ |
3 | scc_epci.o scc_uhc.o \ | 3 | scc_epci.o scc_uhc.o |
4 | io-workarounds.o | ||
5 | 4 | ||
6 | obj-$(CONFIG_SMP) += smp.o | 5 | obj-$(CONFIG_SMP) += smp.o |
7 | obj-$(CONFIG_PPC_UDBG_BEAT) += udbg_beat.o | 6 | obj-$(CONFIG_PPC_UDBG_BEAT) += udbg_beat.o |
diff --git a/arch/powerpc/platforms/celleb/io-workarounds.c b/arch/powerpc/platforms/celleb/io-workarounds.c deleted file mode 100644 index 423339be1bac..000000000000 --- a/arch/powerpc/platforms/celleb/io-workarounds.c +++ /dev/null | |||
@@ -1,280 +0,0 @@ | |||
1 | /* | ||
2 | * Support for Celleb io workarounds | ||
3 | * | ||
4 | * (C) Copyright 2006-2007 TOSHIBA CORPORATION | ||
5 | * | ||
6 | * This file is based to arch/powerpc/platform/cell/io-workarounds.c | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | */ | ||
22 | |||
23 | #undef DEBUG | ||
24 | |||
25 | #include <linux/of.h> | ||
26 | #include <linux/of_device.h> | ||
27 | #include <linux/irq.h> | ||
28 | |||
29 | #include <asm/io.h> | ||
30 | #include <asm/prom.h> | ||
31 | #include <asm/machdep.h> | ||
32 | #include <asm/pci-bridge.h> | ||
33 | #include <asm/ppc-pci.h> | ||
34 | |||
35 | #include "pci.h" | ||
36 | |||
37 | #define MAX_CELLEB_PCI_BUS 4 | ||
38 | |||
39 | void *celleb_dummy_page_va; | ||
40 | |||
41 | static struct celleb_pci_bus { | ||
42 | struct pci_controller *phb; | ||
43 | void (*dummy_read)(struct pci_controller *); | ||
44 | } celleb_pci_busses[MAX_CELLEB_PCI_BUS]; | ||
45 | |||
46 | static int celleb_pci_count = 0; | ||
47 | |||
48 | static struct celleb_pci_bus *celleb_pci_find(unsigned long vaddr, | ||
49 | unsigned long paddr) | ||
50 | { | ||
51 | int i, j; | ||
52 | struct resource *res; | ||
53 | |||
54 | for (i = 0; i < celleb_pci_count; i++) { | ||
55 | struct celleb_pci_bus *bus = &celleb_pci_busses[i]; | ||
56 | struct pci_controller *phb = bus->phb; | ||
57 | if (paddr) | ||
58 | for (j = 0; j < 3; j++) { | ||
59 | res = &phb->mem_resources[j]; | ||
60 | if (paddr >= res->start && paddr <= res->end) | ||
61 | return bus; | ||
62 | } | ||
63 | res = &phb->io_resource; | ||
64 | if (vaddr && vaddr >= res->start && vaddr <= res->end) | ||
65 | return bus; | ||
66 | } | ||
67 | return NULL; | ||
68 | } | ||
69 | |||
70 | static void celleb_io_flush(const PCI_IO_ADDR addr) | ||
71 | { | ||
72 | struct celleb_pci_bus *bus; | ||
73 | int token; | ||
74 | |||
75 | token = PCI_GET_ADDR_TOKEN(addr); | ||
76 | |||
77 | if (token && token <= celleb_pci_count) | ||
78 | bus = &celleb_pci_busses[token - 1]; | ||
79 | else { | ||
80 | unsigned long vaddr, paddr; | ||
81 | pte_t *ptep; | ||
82 | |||
83 | vaddr = (unsigned long)PCI_FIX_ADDR(addr); | ||
84 | if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END) | ||
85 | return; | ||
86 | |||
87 | ptep = find_linux_pte(init_mm.pgd, vaddr); | ||
88 | if (ptep == NULL) | ||
89 | paddr = 0; | ||
90 | else | ||
91 | paddr = pte_pfn(*ptep) << PAGE_SHIFT; | ||
92 | bus = celleb_pci_find(vaddr, paddr); | ||
93 | |||
94 | if (bus == NULL) | ||
95 | return; | ||
96 | } | ||
97 | |||
98 | if (bus->dummy_read) | ||
99 | bus->dummy_read(bus->phb); | ||
100 | } | ||
101 | |||
102 | static u8 celleb_readb(const PCI_IO_ADDR addr) | ||
103 | { | ||
104 | u8 val; | ||
105 | val = __do_readb(addr); | ||
106 | celleb_io_flush(addr); | ||
107 | return val; | ||
108 | } | ||
109 | |||
110 | static u16 celleb_readw(const PCI_IO_ADDR addr) | ||
111 | { | ||
112 | u16 val; | ||
113 | val = __do_readw(addr); | ||
114 | celleb_io_flush(addr); | ||
115 | return val; | ||
116 | } | ||
117 | |||
118 | static u32 celleb_readl(const PCI_IO_ADDR addr) | ||
119 | { | ||
120 | u32 val; | ||
121 | val = __do_readl(addr); | ||
122 | celleb_io_flush(addr); | ||
123 | return val; | ||
124 | } | ||
125 | |||
126 | static u64 celleb_readq(const PCI_IO_ADDR addr) | ||
127 | { | ||
128 | u64 val; | ||
129 | val = __do_readq(addr); | ||
130 | celleb_io_flush(addr); | ||
131 | return val; | ||
132 | } | ||
133 | |||
134 | static u16 celleb_readw_be(const PCI_IO_ADDR addr) | ||
135 | { | ||
136 | u16 val; | ||
137 | val = __do_readw_be(addr); | ||
138 | celleb_io_flush(addr); | ||
139 | return val; | ||
140 | } | ||
141 | |||
142 | static u32 celleb_readl_be(const PCI_IO_ADDR addr) | ||
143 | { | ||
144 | u32 val; | ||
145 | val = __do_readl_be(addr); | ||
146 | celleb_io_flush(addr); | ||
147 | return val; | ||
148 | } | ||
149 | |||
150 | static u64 celleb_readq_be(const PCI_IO_ADDR addr) | ||
151 | { | ||
152 | u64 val; | ||
153 | val = __do_readq_be(addr); | ||
154 | celleb_io_flush(addr); | ||
155 | return val; | ||
156 | } | ||
157 | |||
158 | static void celleb_readsb(const PCI_IO_ADDR addr, | ||
159 | void *buf, unsigned long count) | ||
160 | { | ||
161 | __do_readsb(addr, buf, count); | ||
162 | celleb_io_flush(addr); | ||
163 | } | ||
164 | |||
165 | static void celleb_readsw(const PCI_IO_ADDR addr, | ||
166 | void *buf, unsigned long count) | ||
167 | { | ||
168 | __do_readsw(addr, buf, count); | ||
169 | celleb_io_flush(addr); | ||
170 | } | ||
171 | |||
172 | static void celleb_readsl(const PCI_IO_ADDR addr, | ||
173 | void *buf, unsigned long count) | ||
174 | { | ||
175 | __do_readsl(addr, buf, count); | ||
176 | celleb_io_flush(addr); | ||
177 | } | ||
178 | |||
179 | static void celleb_memcpy_fromio(void *dest, | ||
180 | const PCI_IO_ADDR src, | ||
181 | unsigned long n) | ||
182 | { | ||
183 | __do_memcpy_fromio(dest, src, n); | ||
184 | celleb_io_flush(src); | ||
185 | } | ||
186 | |||
187 | static void __iomem *celleb_ioremap(unsigned long addr, | ||
188 | unsigned long size, | ||
189 | unsigned long flags) | ||
190 | { | ||
191 | struct celleb_pci_bus *bus; | ||
192 | void __iomem *res = __ioremap(addr, size, flags); | ||
193 | int busno; | ||
194 | |||
195 | bus = celleb_pci_find(0, addr); | ||
196 | if (bus != NULL) { | ||
197 | busno = bus - celleb_pci_busses; | ||
198 | PCI_SET_ADDR_TOKEN(res, busno + 1); | ||
199 | } | ||
200 | return res; | ||
201 | } | ||
202 | |||
203 | static void celleb_iounmap(volatile void __iomem *addr) | ||
204 | { | ||
205 | return __iounmap(PCI_FIX_ADDR(addr)); | ||
206 | } | ||
207 | |||
208 | static struct ppc_pci_io celleb_pci_io __initdata = { | ||
209 | .readb = celleb_readb, | ||
210 | .readw = celleb_readw, | ||
211 | .readl = celleb_readl, | ||
212 | .readq = celleb_readq, | ||
213 | .readw_be = celleb_readw_be, | ||
214 | .readl_be = celleb_readl_be, | ||
215 | .readq_be = celleb_readq_be, | ||
216 | .readsb = celleb_readsb, | ||
217 | .readsw = celleb_readsw, | ||
218 | .readsl = celleb_readsl, | ||
219 | .memcpy_fromio = celleb_memcpy_fromio, | ||
220 | }; | ||
221 | |||
222 | void __init celleb_pci_add_one(struct pci_controller *phb, | ||
223 | void (*dummy_read)(struct pci_controller *)) | ||
224 | { | ||
225 | struct celleb_pci_bus *bus = &celleb_pci_busses[celleb_pci_count]; | ||
226 | struct device_node *np = phb->dn; | ||
227 | |||
228 | if (celleb_pci_count >= MAX_CELLEB_PCI_BUS) { | ||
229 | printk(KERN_ERR "Too many pci bridges, workarounds" | ||
230 | " disabled for %s\n", np->full_name); | ||
231 | return; | ||
232 | } | ||
233 | |||
234 | celleb_pci_count++; | ||
235 | |||
236 | bus->phb = phb; | ||
237 | bus->dummy_read = dummy_read; | ||
238 | } | ||
239 | |||
240 | static struct of_device_id celleb_pci_workaround_match[] __initdata = { | ||
241 | { | ||
242 | .name = "pci-pseudo", | ||
243 | .data = fake_pci_workaround_init, | ||
244 | }, { | ||
245 | .name = "epci", | ||
246 | .data = epci_workaround_init, | ||
247 | }, { | ||
248 | }, | ||
249 | }; | ||
250 | |||
251 | int __init celleb_pci_workaround_init(void) | ||
252 | { | ||
253 | struct pci_controller *phb; | ||
254 | struct device_node *node; | ||
255 | const struct of_device_id *match; | ||
256 | void (*init_func)(struct pci_controller *); | ||
257 | |||
258 | celleb_dummy_page_va = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
259 | if (!celleb_dummy_page_va) { | ||
260 | printk(KERN_ERR "Celleb: dummy read disabled. " | ||
261 | "Alloc celleb_dummy_page_va failed\n"); | ||
262 | return 1; | ||
263 | } | ||
264 | |||
265 | list_for_each_entry(phb, &hose_list, list_node) { | ||
266 | node = phb->dn; | ||
267 | match = of_match_node(celleb_pci_workaround_match, node); | ||
268 | |||
269 | if (match) { | ||
270 | init_func = match->data; | ||
271 | (*init_func)(phb); | ||
272 | } | ||
273 | } | ||
274 | |||
275 | ppc_pci_io = celleb_pci_io; | ||
276 | ppc_md.ioremap = celleb_ioremap; | ||
277 | ppc_md.iounmap = celleb_iounmap; | ||
278 | |||
279 | return 0; | ||
280 | } | ||
diff --git a/arch/powerpc/platforms/celleb/pci.c b/arch/powerpc/platforms/celleb/pci.c index 51b390d34e4d..539d2cc59542 100644 --- a/arch/powerpc/platforms/celleb/pci.c +++ b/arch/powerpc/platforms/celleb/pci.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <asm/pci-bridge.h> | 41 | #include <asm/pci-bridge.h> |
42 | #include <asm/ppc-pci.h> | 42 | #include <asm/ppc-pci.h> |
43 | 43 | ||
44 | #include "../cell/io-workarounds.h" | ||
44 | #include "pci.h" | 45 | #include "pci.h" |
45 | #include "interrupt.h" | 46 | #include "interrupt.h" |
46 | 47 | ||
@@ -457,33 +458,39 @@ static int __init celleb_setup_fake_pci(struct device_node *dev, | |||
457 | return 0; | 458 | return 0; |
458 | } | 459 | } |
459 | 460 | ||
460 | void __init fake_pci_workaround_init(struct pci_controller *phb) | 461 | static struct celleb_phb_spec celleb_fake_pci_spec __initdata = { |
461 | { | 462 | .setup = celleb_setup_fake_pci, |
462 | /** | 463 | }; |
463 | * We will add fake pci bus to scc_pci_bus for the purpose to improve | ||
464 | * I/O Macro performance. But device-tree and device drivers | ||
465 | * are not ready to use address with a token. | ||
466 | */ | ||
467 | |||
468 | /* celleb_pci_add_one(phb, NULL); */ | ||
469 | } | ||
470 | 464 | ||
471 | static struct of_device_id celleb_phb_match[] __initdata = { | 465 | static struct of_device_id celleb_phb_match[] __initdata = { |
472 | { | 466 | { |
473 | .name = "pci-pseudo", | 467 | .name = "pci-pseudo", |
474 | .data = celleb_setup_fake_pci, | 468 | .data = &celleb_fake_pci_spec, |
475 | }, { | 469 | }, { |
476 | .name = "epci", | 470 | .name = "epci", |
477 | .data = celleb_setup_epci, | 471 | .data = &celleb_epci_spec, |
478 | }, { | 472 | }, { |
479 | }, | 473 | }, |
480 | }; | 474 | }; |
481 | 475 | ||
476 | static int __init celleb_io_workaround_init(struct pci_controller *phb, | ||
477 | struct celleb_phb_spec *phb_spec) | ||
478 | { | ||
479 | if (phb_spec->ops) { | ||
480 | iowa_register_bus(phb, phb_spec->ops, phb_spec->iowa_init, | ||
481 | phb_spec->iowa_data); | ||
482 | io_workaround_init(); | ||
483 | } | ||
484 | |||
485 | return 0; | ||
486 | } | ||
487 | |||
482 | int __init celleb_setup_phb(struct pci_controller *phb) | 488 | int __init celleb_setup_phb(struct pci_controller *phb) |
483 | { | 489 | { |
484 | struct device_node *dev = phb->dn; | 490 | struct device_node *dev = phb->dn; |
485 | const struct of_device_id *match; | 491 | const struct of_device_id *match; |
486 | int (*setup_func)(struct device_node *, struct pci_controller *); | 492 | struct celleb_phb_spec *phb_spec; |
493 | int rc; | ||
487 | 494 | ||
488 | match = of_match_node(celleb_phb_match, dev); | 495 | match = of_match_node(celleb_phb_match, dev); |
489 | if (!match) | 496 | if (!match) |
@@ -492,8 +499,12 @@ int __init celleb_setup_phb(struct pci_controller *phb) | |||
492 | phb_set_bus_ranges(dev, phb); | 499 | phb_set_bus_ranges(dev, phb); |
493 | phb->buid = 1; | 500 | phb->buid = 1; |
494 | 501 | ||
495 | setup_func = match->data; | 502 | phb_spec = match->data; |
496 | return (*setup_func)(dev, phb); | 503 | rc = (*phb_spec->setup)(dev, phb); |
504 | if (rc) | ||
505 | return 1; | ||
506 | |||
507 | return celleb_io_workaround_init(phb, phb_spec); | ||
497 | } | 508 | } |
498 | 509 | ||
499 | int celleb_pci_probe_mode(struct pci_bus *bus) | 510 | int celleb_pci_probe_mode(struct pci_bus *bus) |
diff --git a/arch/powerpc/platforms/celleb/pci.h b/arch/powerpc/platforms/celleb/pci.h index 5d5544ffeddb..cabb3a108c31 100644 --- a/arch/powerpc/platforms/celleb/pci.h +++ b/arch/powerpc/platforms/celleb/pci.h | |||
@@ -27,16 +27,18 @@ | |||
27 | #include <asm/prom.h> | 27 | #include <asm/prom.h> |
28 | #include <asm/ppc-pci.h> | 28 | #include <asm/ppc-pci.h> |
29 | 29 | ||
30 | #include "../cell/io-workarounds.h" | ||
31 | |||
32 | struct celleb_phb_spec { | ||
33 | int (*setup)(struct device_node *, struct pci_controller *); | ||
34 | struct ppc_pci_io *ops; | ||
35 | int (*iowa_init)(struct iowa_bus *, void *); | ||
36 | void *iowa_data; | ||
37 | }; | ||
38 | |||
30 | extern int celleb_setup_phb(struct pci_controller *); | 39 | extern int celleb_setup_phb(struct pci_controller *); |
31 | extern int celleb_pci_probe_mode(struct pci_bus *); | 40 | extern int celleb_pci_probe_mode(struct pci_bus *); |
32 | 41 | ||
33 | extern int celleb_setup_epci(struct device_node *, struct pci_controller *); | 42 | extern struct celleb_phb_spec celleb_epci_spec; |
34 | |||
35 | extern void *celleb_dummy_page_va; | ||
36 | extern int __init celleb_pci_workaround_init(void); | ||
37 | extern void __init celleb_pci_add_one(struct pci_controller *, | ||
38 | void (*)(struct pci_controller *)); | ||
39 | extern void fake_pci_workaround_init(struct pci_controller *); | ||
40 | extern void epci_workaround_init(struct pci_controller *); | ||
41 | 43 | ||
42 | #endif /* _CELLEB_PCI_H */ | 44 | #endif /* _CELLEB_PCI_H */ |
diff --git a/arch/powerpc/platforms/celleb/scc_epci.c b/arch/powerpc/platforms/celleb/scc_epci.c index a999b393f6f6..b126739834ac 100644 --- a/arch/powerpc/platforms/celleb/scc_epci.c +++ b/arch/powerpc/platforms/celleb/scc_epci.c | |||
@@ -43,10 +43,6 @@ | |||
43 | 43 | ||
44 | #define iob() __asm__ __volatile__("eieio; sync":::"memory") | 44 | #define iob() __asm__ __volatile__("eieio; sync":::"memory") |
45 | 45 | ||
46 | struct epci_private { | ||
47 | dma_addr_t dummy_page_da; | ||
48 | }; | ||
49 | |||
50 | static inline PCI_IO_ADDR celleb_epci_get_epci_base( | 46 | static inline PCI_IO_ADDR celleb_epci_get_epci_base( |
51 | struct pci_controller *hose) | 47 | struct pci_controller *hose) |
52 | { | 48 | { |
@@ -71,42 +67,6 @@ static inline PCI_IO_ADDR celleb_epci_get_epci_cfg( | |||
71 | return hose->cfg_data; | 67 | return hose->cfg_data; |
72 | } | 68 | } |
73 | 69 | ||
74 | static void scc_epci_dummy_read(struct pci_controller *hose) | ||
75 | { | ||
76 | PCI_IO_ADDR epci_base; | ||
77 | u32 val; | ||
78 | |||
79 | epci_base = celleb_epci_get_epci_base(hose); | ||
80 | |||
81 | val = in_be32(epci_base + SCC_EPCI_WATRP); | ||
82 | iosync(); | ||
83 | |||
84 | return; | ||
85 | } | ||
86 | |||
87 | void __init epci_workaround_init(struct pci_controller *hose) | ||
88 | { | ||
89 | PCI_IO_ADDR epci_base; | ||
90 | PCI_IO_ADDR reg; | ||
91 | struct epci_private *private = hose->private_data; | ||
92 | |||
93 | BUG_ON(!private); | ||
94 | |||
95 | private->dummy_page_da = dma_map_single(hose->parent, | ||
96 | celleb_dummy_page_va, PAGE_SIZE, DMA_FROM_DEVICE); | ||
97 | if (private->dummy_page_da == DMA_ERROR_CODE) { | ||
98 | printk(KERN_ERR "EPCI: dummy read disabled. " | ||
99 | "Map dummy page failed.\n"); | ||
100 | return; | ||
101 | } | ||
102 | |||
103 | celleb_pci_add_one(hose, scc_epci_dummy_read); | ||
104 | epci_base = celleb_epci_get_epci_base(hose); | ||
105 | |||
106 | reg = epci_base + SCC_EPCI_DUMYRADR; | ||
107 | out_be32(reg, private->dummy_page_da); | ||
108 | } | ||
109 | |||
110 | static inline void clear_and_disable_master_abort_interrupt( | 70 | static inline void clear_and_disable_master_abort_interrupt( |
111 | struct pci_controller *hose) | 71 | struct pci_controller *hose) |
112 | { | 72 | { |
@@ -425,8 +385,8 @@ static int __init celleb_epci_init(struct pci_controller *hose) | |||
425 | return 0; | 385 | return 0; |
426 | } | 386 | } |
427 | 387 | ||
428 | int __init celleb_setup_epci(struct device_node *node, | 388 | static int __init celleb_setup_epci(struct device_node *node, |
429 | struct pci_controller *hose) | 389 | struct pci_controller *hose) |
430 | { | 390 | { |
431 | struct resource r; | 391 | struct resource r; |
432 | 392 | ||
@@ -462,20 +422,12 @@ int __init celleb_setup_epci(struct device_node *node, | |||
462 | r.start, (unsigned long)hose->cfg_data, | 422 | r.start, (unsigned long)hose->cfg_data, |
463 | (r.end - r.start + 1)); | 423 | (r.end - r.start + 1)); |
464 | 424 | ||
465 | hose->private_data = kzalloc(sizeof(struct epci_private), GFP_KERNEL); | ||
466 | if (hose->private_data == NULL) { | ||
467 | printk(KERN_ERR "EPCI: no memory for private data.\n"); | ||
468 | goto error; | ||
469 | } | ||
470 | |||
471 | hose->ops = &celleb_epci_ops; | 425 | hose->ops = &celleb_epci_ops; |
472 | celleb_epci_init(hose); | 426 | celleb_epci_init(hose); |
473 | 427 | ||
474 | return 0; | 428 | return 0; |
475 | 429 | ||
476 | error: | 430 | error: |
477 | kfree(hose->private_data); | ||
478 | |||
479 | if (hose->cfg_addr) | 431 | if (hose->cfg_addr) |
480 | iounmap(hose->cfg_addr); | 432 | iounmap(hose->cfg_addr); |
481 | 433 | ||
@@ -483,3 +435,10 @@ error: | |||
483 | iounmap(hose->cfg_data); | 435 | iounmap(hose->cfg_data); |
484 | return 1; | 436 | return 1; |
485 | } | 437 | } |
438 | |||
439 | struct celleb_phb_spec celleb_epci_spec __initdata = { | ||
440 | .setup = celleb_setup_epci, | ||
441 | .ops = &spiderpci_ops, | ||
442 | .iowa_init = &spiderpci_iowa_init, | ||
443 | .iowa_data = (void *)0, | ||
444 | }; | ||
diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c index f27ae1e3fb58..ff8209e61e84 100644 --- a/arch/powerpc/platforms/celleb/setup.c +++ b/arch/powerpc/platforms/celleb/setup.c | |||
@@ -114,8 +114,6 @@ static int __init celleb_publish_devices(void) | |||
114 | /* Publish OF platform devices for southbridge IOs */ | 114 | /* Publish OF platform devices for southbridge IOs */ |
115 | of_platform_bus_probe(NULL, celleb_bus_ids, NULL); | 115 | of_platform_bus_probe(NULL, celleb_bus_ids, NULL); |
116 | 116 | ||
117 | celleb_pci_workaround_init(); | ||
118 | |||
119 | return 0; | 117 | return 0; |
120 | } | 118 | } |
121 | machine_device_initcall(celleb_beat, celleb_publish_devices); | 119 | machine_device_initcall(celleb_beat, celleb_publish_devices); |