aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/85xx/Kconfig9
-rw-r--r--arch/powerpc/platforms/85xx/Makefile1
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_cds.c359
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_cds.h43
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c12
-rw-r--r--arch/powerpc/platforms/iseries/Makefile6
-rw-r--r--arch/powerpc/platforms/iseries/call_pci.h19
-rw-r--r--arch/powerpc/platforms/iseries/dt.c615
-rw-r--r--arch/powerpc/platforms/iseries/iommu.c44
-rw-r--r--arch/powerpc/platforms/iseries/iommu.h35
-rw-r--r--arch/powerpc/platforms/iseries/irq.c7
-rw-r--r--arch/powerpc/platforms/iseries/irq.h2
-rw-r--r--arch/powerpc/platforms/iseries/mf.c9
-rw-r--r--arch/powerpc/platforms/iseries/pci.c347
-rw-r--r--arch/powerpc/platforms/iseries/setup.c271
-rw-r--r--arch/powerpc/platforms/iseries/setup.h2
-rw-r--r--arch/powerpc/platforms/iseries/vio.c131
-rw-r--r--arch/powerpc/platforms/maple/pci.c3
-rw-r--r--arch/powerpc/platforms/maple/setup.c2
-rw-r--r--arch/powerpc/platforms/powermac/feature.c2
-rw-r--r--arch/powerpc/platforms/powermac/pci.c3
-rw-r--r--arch/powerpc/platforms/pseries/Makefile1
-rw-r--r--arch/powerpc/platforms/pseries/eeh_driver.c20
-rw-r--r--arch/powerpc/platforms/pseries/eeh_event.c50
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c151
-rw-r--r--arch/powerpc/platforms/pseries/rtasd.c6
-rw-r--r--arch/powerpc/platforms/pseries/setup.c6
-rw-r--r--arch/powerpc/platforms/pseries/vio.c274
-rw-r--r--arch/powerpc/platforms/pseries/xics.c25
29 files changed, 1284 insertions, 1171 deletions
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 06e371282f57..454fc53289ab 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -11,13 +11,20 @@ config MPC8540_ADS
11 help 11 help
12 This option enables support for the MPC 8540 ADS board 12 This option enables support for the MPC 8540 ADS board
13 13
14config MPC85xx_CDS
15 bool "Freescale MPC85xx CDS"
16 select DEFAULT_UIMAGE
17 select PPC_I8259 if PCI
18 help
19 This option enables support for the MPC85xx CDS board
20
14endchoice 21endchoice
15 22
16config MPC8540 23config MPC8540
17 bool 24 bool
18 select PPC_UDBG_16550 25 select PPC_UDBG_16550
19 select PPC_INDIRECT_PCI 26 select PPC_INDIRECT_PCI
20 default y if MPC8540_ADS 27 default y if MPC8540_ADS || MPC85xx_CDS
21 28
22config PPC_INDIRECT_PCI_BE 29config PPC_INDIRECT_PCI_BE
23 bool 30 bool
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index ffc4139cb214..7615aa59c78b 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -3,3 +3,4 @@
3# 3#
4obj-$(CONFIG_PPC_85xx) += misc.o pci.o 4obj-$(CONFIG_PPC_85xx) += misc.o pci.o
5obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o 5obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
6obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
new file mode 100644
index 000000000000..18e6e11f7020
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -0,0 +1,359 @@
1/*
2 * MPC85xx setup and early boot code plus other random bits.
3 *
4 * Maintained by Kumar Gala (see MAINTAINERS for contact information)
5 *
6 * Copyright 2005 Freescale Semiconductor Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/config.h>
15#include <linux/stddef.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/errno.h>
19#include <linux/reboot.h>
20#include <linux/pci.h>
21#include <linux/kdev_t.h>
22#include <linux/major.h>
23#include <linux/console.h>
24#include <linux/delay.h>
25#include <linux/seq_file.h>
26#include <linux/root_dev.h>
27#include <linux/initrd.h>
28#include <linux/module.h>
29#include <linux/fsl_devices.h>
30
31#include <asm/system.h>
32#include <asm/pgtable.h>
33#include <asm/page.h>
34#include <asm/atomic.h>
35#include <asm/time.h>
36#include <asm/io.h>
37#include <asm/machdep.h>
38#include <asm/ipic.h>
39#include <asm/bootinfo.h>
40#include <asm/pci-bridge.h>
41#include <asm/mpc85xx.h>
42#include <asm/irq.h>
43#include <mm/mmu_decl.h>
44#include <asm/prom.h>
45#include <asm/udbg.h>
46#include <asm/mpic.h>
47#include <asm/i8259.h>
48
49#include <sysdev/fsl_soc.h>
50#include "mpc85xx.h"
51
52#ifndef CONFIG_PCI
53unsigned long isa_io_base = 0;
54unsigned long isa_mem_base = 0;
55#endif
56
57static int cds_pci_slot = 2;
58static volatile u8 *cadmus;
59
60/*
61 * Internal interrupts are all Level Sensitive, and Positive Polarity
62 *
63 * Note: Likely, this table and the following function should be
64 * obtained and derived from the OF Device Tree.
65 */
66static u_char mpc85xx_cds_openpic_initsenses[] __initdata = {
67 MPC85XX_INTERNAL_IRQ_SENSES,
68#if defined(CONFIG_PCI)
69 (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Ext 0: PCI slot 0 */
70 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 1: PCI slot 1 */
71 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 2: PCI slot 2 */
72 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 3: PCI slot 3 */
73#else
74 0x0, /* External 0: */
75 0x0, /* External 1: */
76 0x0, /* External 2: */
77 0x0, /* External 3: */
78#endif
79 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 5: PHY */
80 0x0, /* External 6: */
81 0x0, /* External 7: */
82 0x0, /* External 8: */
83 0x0, /* External 9: */
84 0x0, /* External 10: */
85#ifdef CONFIG_PCI
86 (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 11: PCI2 slot 0 */
87#else
88 0x0, /* External 11: */
89#endif
90};
91
92
93#ifdef CONFIG_PCI
94/*
95 * interrupt routing
96 */
97int
98mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
99{
100 struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
101
102 if (!hose->index)
103 {
104 /* Handle PCI1 interrupts */
105 char pci_irq_table[][4] =
106 /*
107 * PCI IDSEL/INTPIN->INTLINE
108 * A B C D
109 */
110
111 /* Note IRQ assignment for slots is based on which slot the elysium is
112 * in -- in this setup elysium is in slot #2 (this PIRQA as first
113 * interrupt on slot */
114 {
115 { 0, 1, 2, 3 }, /* 16 - PMC */
116 { 0, 1, 2, 3 }, /* 17 P2P (Tsi320) */
117 { 0, 1, 2, 3 }, /* 18 - Slot 1 */
118 { 1, 2, 3, 0 }, /* 19 - Slot 2 */
119 { 2, 3, 0, 1 }, /* 20 - Slot 3 */
120 { 3, 0, 1, 2 }, /* 21 - Slot 4 */
121 };
122
123 const long min_idsel = 16, max_idsel = 21, irqs_per_slot = 4;
124 int i, j;
125
126 for (i = 0; i < 6; i++)
127 for (j = 0; j < 4; j++)
128 pci_irq_table[i][j] =
129 ((pci_irq_table[i][j] + 5 -
130 cds_pci_slot) & 0x3) + PIRQ0A;
131
132 return PCI_IRQ_TABLE_LOOKUP;
133 } else {
134 /* Handle PCI2 interrupts (if we have one) */
135 char pci_irq_table[][4] =
136 {
137 /*
138 * We only have one slot and one interrupt
139 * going to PIRQA - PIRQD */
140 { PIRQ1A, PIRQ1A, PIRQ1A, PIRQ1A }, /* 21 - slot 0 */
141 };
142
143 const long min_idsel = 21, max_idsel = 21, irqs_per_slot = 4;
144
145 return PCI_IRQ_TABLE_LOOKUP;
146 }
147}
148
149#define ARCADIA_HOST_BRIDGE_IDSEL 17
150#define ARCADIA_2ND_BRIDGE_IDSEL 3
151
152extern int mpc85xx_pci2_busno;
153
154int
155mpc85xx_exclude_device(u_char bus, u_char devfn)
156{
157 if (bus == 0 && PCI_SLOT(devfn) == 0)
158 return PCIBIOS_DEVICE_NOT_FOUND;
159 if (mpc85xx_pci2_busno)
160 if (bus == (mpc85xx_pci2_busno) && PCI_SLOT(devfn) == 0)
161 return PCIBIOS_DEVICE_NOT_FOUND;
162 /* We explicitly do not go past the Tundra 320 Bridge */
163 if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
164 return PCIBIOS_DEVICE_NOT_FOUND;
165 if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
166 return PCIBIOS_DEVICE_NOT_FOUND;
167 else
168 return PCIBIOS_SUCCESSFUL;
169}
170
171void __init
172mpc85xx_cds_pcibios_fixup(void)
173{
174 struct pci_dev *dev;
175 u_char c;
176
177 if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
178 PCI_DEVICE_ID_VIA_82C586_1, NULL))) {
179 /*
180 * U-Boot does not set the enable bits
181 * for the IDE device. Force them on here.
182 */
183 pci_read_config_byte(dev, 0x40, &c);
184 c |= 0x03; /* IDE: Chip Enable Bits */
185 pci_write_config_byte(dev, 0x40, c);
186
187 /*
188 * Since only primary interface works, force the
189 * IDE function to standard primary IDE interrupt
190 * w/ 8259 offset
191 */
192 dev->irq = 14;
193 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
194 pci_dev_put(dev);
195 }
196
197 /*
198 * Force legacy USB interrupt routing
199 */
200 if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
201 PCI_DEVICE_ID_VIA_82C586_2, NULL))) {
202 dev->irq = 10;
203 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10);
204 pci_dev_put(dev);
205 }
206
207 if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
208 PCI_DEVICE_ID_VIA_82C586_2, dev))) {
209 dev->irq = 11;
210 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
211 pci_dev_put(dev);
212 }
213}
214#endif /* CONFIG_PCI */
215
216void __init mpc85xx_cds_pic_init(void)
217{
218 struct mpic *mpic1;
219 phys_addr_t OpenPIC_PAddr;
220
221 /* Determine the Physical Address of the OpenPIC regs */
222 OpenPIC_PAddr = get_immrbase() + MPC85xx_OPENPIC_OFFSET;
223
224 mpic1 = mpic_alloc(OpenPIC_PAddr,
225 MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
226 4, MPC85xx_OPENPIC_IRQ_OFFSET, 0, 250,
227 mpc85xx_cds_openpic_initsenses,
228 sizeof(mpc85xx_cds_openpic_initsenses), " OpenPIC ");
229 BUG_ON(mpic1 == NULL);
230 mpic_assign_isu(mpic1, 0, OpenPIC_PAddr + 0x10200);
231 mpic_assign_isu(mpic1, 1, OpenPIC_PAddr + 0x10280);
232 mpic_assign_isu(mpic1, 2, OpenPIC_PAddr + 0x10300);
233 mpic_assign_isu(mpic1, 3, OpenPIC_PAddr + 0x10380);
234 mpic_assign_isu(mpic1, 4, OpenPIC_PAddr + 0x10400);
235 mpic_assign_isu(mpic1, 5, OpenPIC_PAddr + 0x10480);
236 mpic_assign_isu(mpic1, 6, OpenPIC_PAddr + 0x10500);
237 mpic_assign_isu(mpic1, 7, OpenPIC_PAddr + 0x10580);
238
239 /* dummy mappings to get to 48 */
240 mpic_assign_isu(mpic1, 8, OpenPIC_PAddr + 0x10600);
241 mpic_assign_isu(mpic1, 9, OpenPIC_PAddr + 0x10680);
242 mpic_assign_isu(mpic1, 10, OpenPIC_PAddr + 0x10700);
243 mpic_assign_isu(mpic1, 11, OpenPIC_PAddr + 0x10780);
244
245 /* External ints */
246 mpic_assign_isu(mpic1, 12, OpenPIC_PAddr + 0x10000);
247 mpic_assign_isu(mpic1, 13, OpenPIC_PAddr + 0x10080);
248 mpic_assign_isu(mpic1, 14, OpenPIC_PAddr + 0x10100);
249
250 mpic_init(mpic1);
251
252#ifdef CONFIG_PCI
253 mpic_setup_cascade(PIRQ0A, i8259_irq_cascade, NULL);
254
255 i8259_init(0,0);
256#endif
257}
258
259
260/*
261 * Setup the architecture
262 */
263static void __init
264mpc85xx_cds_setup_arch(void)
265{
266 struct device_node *cpu;
267#ifdef CONFIG_PCI
268 struct device_node *np;
269#endif
270
271 if (ppc_md.progress)
272 ppc_md.progress("mpc85xx_cds_setup_arch()", 0);
273
274 cpu = of_find_node_by_type(NULL, "cpu");
275 if (cpu != 0) {
276 unsigned int *fp;
277
278 fp = (int *)get_property(cpu, "clock-frequency", NULL);
279 if (fp != 0)
280 loops_per_jiffy = *fp / HZ;
281 else
282 loops_per_jiffy = 500000000 / HZ;
283 of_node_put(cpu);
284 }
285
286 cadmus = ioremap(CADMUS_BASE, CADMUS_SIZE);
287 cds_pci_slot = ((cadmus[CM_CSR] >> 6) & 0x3) + 1;
288
289 if (ppc_md.progress) {
290 char buf[40];
291 snprintf(buf, 40, "CDS Version = 0x%x in slot %d\n",
292 cadmus[CM_VER], cds_pci_slot);
293 ppc_md.progress(buf, 0);
294 }
295
296#ifdef CONFIG_PCI
297 for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
298 add_bridge(np);
299
300 ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup;
301 ppc_md.pci_swizzle = common_swizzle;
302 ppc_md.pci_map_irq = mpc85xx_map_irq;
303 ppc_md.pci_exclude_device = mpc85xx_exclude_device;
304#endif
305
306#ifdef CONFIG_ROOT_NFS
307 ROOT_DEV = Root_NFS;
308#else
309 ROOT_DEV = Root_HDA1;
310#endif
311}
312
313
314void
315mpc85xx_cds_show_cpuinfo(struct seq_file *m)
316{
317 uint pvid, svid, phid1;
318 uint memsize = total_memory;
319
320 pvid = mfspr(SPRN_PVR);
321 svid = mfspr(SPRN_SVR);
322
323 seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
324 seq_printf(m, "Machine\t\t: MPC85xx CDS (0x%x)\n", cadmus[CM_VER]);
325 seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
326 seq_printf(m, "SVR\t\t: 0x%x\n", svid);
327
328 /* Display cpu Pll setting */
329 phid1 = mfspr(SPRN_HID1);
330 seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
331
332 /* Display the amount of memory */
333 seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
334}
335
336
337/*
338 * Called very early, device-tree isn't unflattened
339 */
340static int __init mpc85xx_cds_probe(void)
341{
342 /* We always match for now, eventually we should look at
343 * the flat dev tree to ensure this is the board we are
344 * supposed to run on
345 */
346 return 1;
347}
348
349define_machine(mpc85xx_cds) {
350 .name = "MPC85xx CDS",
351 .probe = mpc85xx_cds_probe,
352 .setup_arch = mpc85xx_cds_setup_arch,
353 .init_IRQ = mpc85xx_cds_pic_init,
354 .show_cpuinfo = mpc85xx_cds_show_cpuinfo,
355 .get_irq = mpic_get_irq,
356 .restart = mpc85xx_restart,
357 .calibrate_decr = generic_calibrate_decr,
358 .progress = udbg_progress,
359};
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.h b/arch/powerpc/platforms/85xx/mpc85xx_cds.h
new file mode 100644
index 000000000000..671f54ff185a
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.h
@@ -0,0 +1,43 @@
1/*
2 * arch/ppc/platforms/85xx/mpc85xx_cds_common.h
3 *
4 * MPC85xx CDS board definitions
5 *
6 * Maintainer: Kumar Gala <galak@kernel.crashing.org>
7 *
8 * Copyright 2004 Freescale Semiconductor, Inc
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 */
16
17#ifndef __MACH_MPC85XX_CDS_H__
18#define __MACH_MPC85XX_CDS_H__
19
20/* CADMUS info */
21#define CADMUS_BASE (0xf8004000)
22#define CADMUS_SIZE (256)
23#define CM_VER (0)
24#define CM_CSR (1)
25#define CM_RST (2)
26
27/* CDS NVRAM/RTC */
28#define CDS_RTC_ADDR (0xf8000000)
29#define CDS_RTC_SIZE (8 * 1024)
30
31/* PCI interrupt controller */
32#define PIRQ0A MPC85xx_IRQ_EXT0
33#define PIRQ0B MPC85xx_IRQ_EXT1
34#define PIRQ0C MPC85xx_IRQ_EXT2
35#define PIRQ0D MPC85xx_IRQ_EXT3
36#define PIRQ1A MPC85xx_IRQ_EXT11
37
38#define NR_8259_INTS 16
39#define CPM_IRQ_OFFSET NR_8259_INTS
40
41#define MPC85xx_OPENPIC_IRQ_OFFSET 80
42
43#endif /* __MACH_MPC85XX_CDS_H__ */
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 8bb33abfad17..36439c5e9f2d 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -30,7 +30,7 @@
30struct spu_context *alloc_spu_context(void) 30struct spu_context *alloc_spu_context(void)
31{ 31{
32 struct spu_context *ctx; 32 struct spu_context *ctx;
33 ctx = kmalloc(sizeof *ctx, GFP_KERNEL); 33 ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
34 if (!ctx) 34 if (!ctx)
35 goto out; 35 goto out;
36 /* Binding to physical processor deferred 36 /* Binding to physical processor deferred
@@ -48,17 +48,7 @@ struct spu_context *alloc_spu_context(void)
48 init_waitqueue_head(&ctx->wbox_wq); 48 init_waitqueue_head(&ctx->wbox_wq);
49 init_waitqueue_head(&ctx->stop_wq); 49 init_waitqueue_head(&ctx->stop_wq);
50 init_waitqueue_head(&ctx->mfc_wq); 50 init_waitqueue_head(&ctx->mfc_wq);
51 ctx->ibox_fasync = NULL;
52 ctx->wbox_fasync = NULL;
53 ctx->mfc_fasync = NULL;
54 ctx->mfc = NULL;
55 ctx->tagwait = 0;
56 ctx->state = SPU_STATE_SAVED; 51 ctx->state = SPU_STATE_SAVED;
57 ctx->local_store = NULL;
58 ctx->cntl = NULL;
59 ctx->signal1 = NULL;
60 ctx->signal2 = NULL;
61 ctx->spu = NULL;
62 ctx->ops = &spu_backing_ops; 52 ctx->ops = &spu_backing_ops;
63 ctx->owner = get_task_mm(current); 53 ctx->owner = get_task_mm(current);
64 goto out; 54 goto out;
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
index ce8c0b943fa0..dee4eb4d8bec 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -1,9 +1,11 @@
1EXTRA_CFLAGS += -mno-minimal-toc 1EXTRA_CFLAGS += -mno-minimal-toc
2 2
3obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \ 3obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \
4 hvcall.o proc.o htab.o iommu.o misc.o irq.o 4 hvcall.o proc.o htab.o iommu.o misc.o irq.o
5obj-$(CONFIG_PCI) += pci.o vpdinfo.o 5obj-$(CONFIG_PCI) += pci.o vpdinfo.o
6obj-$(CONFIG_IBMVIO) += vio.o
7obj-$(CONFIG_SMP) += smp.o 6obj-$(CONFIG_SMP) += smp.o
8obj-$(CONFIG_VIOPATH) += viopath.o 7obj-$(CONFIG_VIOPATH) += viopath.o
9obj-$(CONFIG_MODULES) += ksyms.o 8obj-$(CONFIG_MODULES) += ksyms.o
9
10$(obj)/dt_mod.o: $(obj)/dt.o
11 @$(OBJCOPY) --rename-section .rodata.str1.8=.dt_strings $(obj)/dt.o $(obj)/dt_mod.o
diff --git a/arch/powerpc/platforms/iseries/call_pci.h b/arch/powerpc/platforms/iseries/call_pci.h
index 59d4e0ad5cf3..dbdf69850ed9 100644
--- a/arch/powerpc/platforms/iseries/call_pci.h
+++ b/arch/powerpc/platforms/iseries/call_pci.h
@@ -145,6 +145,25 @@ static inline u64 HvCallPci_configLoad16(u16 busNumber, u8 subBusNumber,
145 return retVal.rc; 145 return retVal.rc;
146} 146}
147 147
148static inline u64 HvCallPci_configLoad32(u16 busNumber, u8 subBusNumber,
149 u8 deviceId, u32 offset, u32 *value)
150{
151 struct HvCallPci_DsaAddr dsa;
152 struct HvCallPci_LoadReturn retVal;
153
154 *((u64*)&dsa) = 0;
155
156 dsa.busNumber = busNumber;
157 dsa.subBusNumber = subBusNumber;
158 dsa.deviceId = deviceId;
159
160 HvCall3Ret16(HvCallPciConfigLoad32, &retVal, *(u64 *)&dsa, offset, 0);
161
162 *value = retVal.value;
163
164 return retVal.rc;
165}
166
148static inline u64 HvCallPci_configStore8(u16 busNumber, u8 subBusNumber, 167static inline u64 HvCallPci_configStore8(u16 busNumber, u8 subBusNumber,
149 u8 deviceId, u32 offset, u8 value) 168 u8 deviceId, u32 offset, u8 value)
150{ 169{
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
new file mode 100644
index 000000000000..d3444aabe76e
--- /dev/null
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -0,0 +1,615 @@
1/*
2 * Copyright (c) 2005-2006 Michael Ellerman, IBM Corporation
3 *
4 * Description:
5 * This file contains all the routines to build a flattened device
6 * tree for a legacy iSeries machine.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13
14#undef DEBUG
15
16#include <linux/types.h>
17#include <linux/init.h>
18#include <linux/pci.h>
19#include <linux/pci_regs.h>
20#include <linux/pci_ids.h>
21#include <linux/threads.h>
22#include <linux/bitops.h>
23#include <linux/string.h>
24#include <linux/kernel.h>
25#include <linux/if_ether.h> /* ETH_ALEN */
26
27#include <asm/machdep.h>
28#include <asm/prom.h>
29#include <asm/lppaca.h>
30#include <asm/cputable.h>
31#include <asm/abs_addr.h>
32#include <asm/system.h>
33#include <asm/iseries/hv_types.h>
34#include <asm/iseries/hv_lp_config.h>
35#include <asm/iseries/hv_call_xm.h>
36#include <asm/iseries/it_exp_vpd_panel.h>
37#include <asm/udbg.h>
38
39#include "processor_vpd.h"
40#include "call_hpt.h"
41#include "call_pci.h"
42#include "pci.h"
43
44#ifdef DEBUG
45#define DBG(fmt...) udbg_printf(fmt)
46#else
47#define DBG(fmt...)
48#endif
49
50/*
51 * These are created by the linker script at the start and end
52 * of the section containing all the strings from this file.
53 */
54extern char __dt_strings_start[];
55extern char __dt_strings_end[];
56
57struct iseries_flat_dt {
58 struct boot_param_header header;
59 u64 reserve_map[2];
60};
61
62static void * __initdata dt_data;
63
64/*
65 * Putting these strings here keeps them out of the section
66 * that we rename to .dt_strings using objcopy and capture
67 * for the strings blob of the flattened device tree.
68 */
69static char __initdata device_type_cpu[] = "cpu";
70static char __initdata device_type_memory[] = "memory";
71static char __initdata device_type_serial[] = "serial";
72static char __initdata device_type_network[] = "network";
73static char __initdata device_type_block[] = "block";
74static char __initdata device_type_byte[] = "byte";
75static char __initdata device_type_pci[] = "pci";
76static char __initdata device_type_vdevice[] = "vdevice";
77static char __initdata device_type_vscsi[] = "vscsi";
78
79static struct iseries_flat_dt * __init dt_init(void)
80{
81 struct iseries_flat_dt *dt;
82 unsigned long str_len;
83
84 str_len = __dt_strings_end - __dt_strings_start;
85 dt = (struct iseries_flat_dt *)ALIGN(klimit, 8);
86 dt->header.off_mem_rsvmap =
87 offsetof(struct iseries_flat_dt, reserve_map);
88 dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8);
89 dt->header.off_dt_struct = dt->header.off_dt_strings
90 + ALIGN(str_len, 8);
91 dt_data = (void *)((unsigned long)dt + dt->header.off_dt_struct);
92 dt->header.dt_strings_size = str_len;
93
94 /* There is no notion of hardware cpu id on iSeries */
95 dt->header.boot_cpuid_phys = smp_processor_id();
96
97 memcpy((char *)dt + dt->header.off_dt_strings, __dt_strings_start,
98 str_len);
99
100 dt->header.magic = OF_DT_HEADER;
101 dt->header.version = 0x10;
102 dt->header.last_comp_version = 0x10;
103
104 dt->reserve_map[0] = 0;
105 dt->reserve_map[1] = 0;
106
107 return dt;
108}
109
110static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value)
111{
112 *((u32 *)dt_data) = value;
113 dt_data += sizeof(u32);
114}
115
116#ifdef notyet
117static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value)
118{
119 *((u64 *)dt_data) = value;
120 dt_data += sizeof(u64);
121}
122#endif
123
124static void __init dt_push_bytes(struct iseries_flat_dt *dt, const char *data,
125 int len)
126{
127 memcpy(dt_data, data, len);
128 dt_data += ALIGN(len, 4);
129}
130
131static void __init dt_start_node(struct iseries_flat_dt *dt, const char *name)
132{
133 dt_push_u32(dt, OF_DT_BEGIN_NODE);
134 dt_push_bytes(dt, name, strlen(name) + 1);
135}
136
137#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
138
139static void __init dt_prop(struct iseries_flat_dt *dt, const char *name,
140 const void *data, int len)
141{
142 unsigned long offset;
143
144 dt_push_u32(dt, OF_DT_PROP);
145
146 /* Length of the data */
147 dt_push_u32(dt, len);
148
149 offset = name - __dt_strings_start;
150
151 /* The offset of the properties name in the string blob. */
152 dt_push_u32(dt, (u32)offset);
153
154 /* The actual data. */
155 dt_push_bytes(dt, data, len);
156}
157
158static void __init dt_prop_str(struct iseries_flat_dt *dt, const char *name,
159 const char *data)
160{
161 dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
162}
163
164static void __init dt_prop_u32(struct iseries_flat_dt *dt, const char *name,
165 u32 data)
166{
167 dt_prop(dt, name, &data, sizeof(u32));
168}
169
170#ifdef notyet
171static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name,
172 u64 data)
173{
174 dt_prop(dt, name, &data, sizeof(u64));
175}
176#endif
177
178static void __init dt_prop_u64_list(struct iseries_flat_dt *dt,
179 const char *name, u64 *data, int n)
180{
181 dt_prop(dt, name, data, sizeof(u64) * n);
182}
183
184static void __init dt_prop_u32_list(struct iseries_flat_dt *dt,
185 const char *name, u32 *data, int n)
186{
187 dt_prop(dt, name, data, sizeof(u32) * n);
188}
189
190#ifdef notyet
191static void __init dt_prop_empty(struct iseries_flat_dt *dt, const char *name)
192{
193 dt_prop(dt, name, NULL, 0);
194}
195#endif
196
197static void __init dt_cpus(struct iseries_flat_dt *dt)
198{
199 unsigned char buf[32];
200 unsigned char *p;
201 unsigned int i, index;
202 struct IoHriProcessorVpd *d;
203 u32 pft_size[2];
204
205 /* yuck */
206 snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name);
207 p = strchr(buf, ' ');
208 if (!p) p = buf + strlen(buf);
209
210 dt_start_node(dt, "cpus");
211 dt_prop_u32(dt, "#address-cells", 1);
212 dt_prop_u32(dt, "#size-cells", 0);
213
214 pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA */
215 pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);
216
217 for (i = 0; i < NR_CPUS; i++) {
218 if (lppaca[i].dyn_proc_status >= 2)
219 continue;
220
221 snprintf(p, 32 - (p - buf), "@%d", i);
222 dt_start_node(dt, buf);
223
224 dt_prop_str(dt, "device_type", device_type_cpu);
225
226 index = lppaca[i].dyn_hv_phys_proc_index;
227 d = &xIoHriProcessorVpd[index];
228
229 dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
230 dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize);
231
232 dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024);
233 dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize);
234
235 /* magic conversions to Hz copied from old code */
236 dt_prop_u32(dt, "clock-frequency",
237 ((1UL << 34) * 1000000) / d->xProcFreq);
238 dt_prop_u32(dt, "timebase-frequency",
239 ((1UL << 32) * 1000000) / d->xTimeBaseFreq);
240
241 dt_prop_u32(dt, "reg", i);
242
243 dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2);
244
245 dt_end_node(dt);
246 }
247
248 dt_end_node(dt);
249}
250
251static void __init dt_model(struct iseries_flat_dt *dt)
252{
253 char buf[16] = "IBM,";
254
255 /* "IBM," + mfgId[2:3] + systemSerial[1:5] */
256 strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2);
257 strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5);
258 buf[11] = '\0';
259 dt_prop_str(dt, "system-id", buf);
260
261 /* "IBM," + machineType[0:4] */
262 strne2a(buf + 4, xItExtVpdPanel.machineType, 4);
263 buf[8] = '\0';
264 dt_prop_str(dt, "model", buf);
265
266 dt_prop_str(dt, "compatible", "IBM,iSeries");
267}
268
269static void __init dt_do_vdevice(struct iseries_flat_dt *dt,
270 const char *name, u32 reg, int unit,
271 const char *type, const char *compat, int end)
272{
273 char buf[32];
274
275 snprintf(buf, 32, "%s@%08x", name, reg + ((unit >= 0) ? unit : 0));
276 dt_start_node(dt, buf);
277 dt_prop_str(dt, "device_type", type);
278 if (compat)
279 dt_prop_str(dt, "compatible", compat);
280 dt_prop_u32(dt, "reg", reg + ((unit >= 0) ? unit : 0));
281 if (unit >= 0)
282 dt_prop_u32(dt, "linux,unit_address", unit);
283 if (end)
284 dt_end_node(dt);
285}
286
287static void __init dt_vdevices(struct iseries_flat_dt *dt)
288{
289 u32 reg = 0;
290 HvLpIndexMap vlan_map;
291 int i;
292
293 dt_start_node(dt, "vdevice");
294 dt_prop_str(dt, "device_type", device_type_vdevice);
295 dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice");
296 dt_prop_u32(dt, "#address-cells", 1);
297 dt_prop_u32(dt, "#size-cells", 0);
298
299 dt_do_vdevice(dt, "vty", reg, -1, device_type_serial, NULL, 1);
300 reg++;
301
302 dt_do_vdevice(dt, "v-scsi", reg, -1, device_type_vscsi,
303 "IBM,v-scsi", 1);
304 reg++;
305
306 vlan_map = HvLpConfig_getVirtualLanIndexMap();
307 for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
308 unsigned char mac_addr[ETH_ALEN];
309
310 if ((vlan_map & (0x8000 >> i)) == 0)
311 continue;
312 dt_do_vdevice(dt, "l-lan", reg, i, device_type_network,
313 "IBM,iSeries-l-lan", 0);
314 mac_addr[0] = 0x02;
315 mac_addr[1] = 0x01;
316 mac_addr[2] = 0xff;
317 mac_addr[3] = i;
318 mac_addr[4] = 0xff;
319 mac_addr[5] = HvLpConfig_getLpIndex_outline();
320 dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN);
321 dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN);
322 dt_prop_u32(dt, "max-frame-size", 9000);
323 dt_prop_u32(dt, "address-bits", 48);
324
325 dt_end_node(dt);
326 }
327 reg += HVMAXARCHITECTEDVIRTUALLANS;
328
329 for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
330 dt_do_vdevice(dt, "viodasd", reg, i, device_type_block,
331 "IBM,iSeries-viodasd", 1);
332 reg += HVMAXARCHITECTEDVIRTUALDISKS;
333
334 for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
335 dt_do_vdevice(dt, "viocd", reg, i, device_type_block,
336 "IBM,iSeries-viocd", 1);
337 reg += HVMAXARCHITECTEDVIRTUALCDROMS;
338
339 for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
340 dt_do_vdevice(dt, "viotape", reg, i, device_type_byte,
341 "IBM,iSeries-viotape", 1);
342
343 dt_end_node(dt);
344}
345
346struct pci_class_name {
347 u16 code;
348 const char *name;
349 const char *type;
350};
351
352static struct pci_class_name __initdata pci_class_name[] = {
353 { PCI_CLASS_NETWORK_ETHERNET, "ethernet", device_type_network },
354};
355
356static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code)
357{
358 struct pci_class_name *cp;
359
360 for (cp = pci_class_name;
361 cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++)
362 if (cp->code == class_code)
363 return cp;
364 return NULL;
365}
366
367/*
368 * This assumes that the node slot is always on the primary bus!
369 */
370static void __init scan_bridge_slot(struct iseries_flat_dt *dt,
371 HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info)
372{
373 HvSubBusNumber sub_bus = bridge_info->subBusNumber;
374 u16 vendor_id;
375 u16 device_id;
376 u32 class_id;
377 int err;
378 char buf[32];
379 u32 reg[5];
380 int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus);
381 int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus);
382 HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function);
383 u8 devfn;
384 struct pci_class_name *cp;
385
386 /*
387 * Connect all functions of any device found.
388 */
389 for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) {
390 for (function = 0; function < 8; function++) {
391 HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel,
392 function);
393 err = HvCallXm_connectBusUnit(bus, sub_bus,
394 agent_id, 0);
395 if (err) {
396 if (err != 0x302)
397 DBG("connectBusUnit(%x, %x, %x) %x\n",
398 bus, sub_bus, agent_id, err);
399 continue;
400 }
401
402 err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
403 PCI_VENDOR_ID, &vendor_id);
404 if (err) {
405 DBG("ReadVendor(%x, %x, %x) %x\n",
406 bus, sub_bus, agent_id, err);
407 continue;
408 }
409 err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
410 PCI_DEVICE_ID, &device_id);
411 if (err) {
412 DBG("ReadDevice(%x, %x, %x) %x\n",
413 bus, sub_bus, agent_id, err);
414 continue;
415 }
416 err = HvCallPci_configLoad32(bus, sub_bus, agent_id,
417 PCI_CLASS_REVISION , &class_id);
418 if (err) {
419 DBG("ReadClass(%x, %x, %x) %x\n",
420 bus, sub_bus, agent_id, err);
421 continue;
422 }
423
424 devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel),
425 function);
426 cp = dt_find_pci_class_name(class_id >> 16);
427 if (cp && cp->name)
428 strncpy(buf, cp->name, sizeof(buf) - 1);
429 else
430 snprintf(buf, sizeof(buf), "pci%x,%x",
431 vendor_id, device_id);
432 buf[sizeof(buf) - 1] = '\0';
433 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
434 "@%x", PCI_SLOT(devfn));
435 buf[sizeof(buf) - 1] = '\0';
436 if (function != 0)
437 snprintf(buf + strlen(buf),
438 sizeof(buf) - strlen(buf),
439 ",%x", function);
440 dt_start_node(dt, buf);
441 reg[0] = (bus << 16) | (devfn << 8);
442 reg[1] = 0;
443 reg[2] = 0;
444 reg[3] = 0;
445 reg[4] = 0;
446 dt_prop_u32_list(dt, "reg", reg, 5);
447 if (cp && (cp->type || cp->name))
448 dt_prop_str(dt, "device_type",
449 cp->type ? cp->type : cp->name);
450 dt_prop_u32(dt, "vendor-id", vendor_id);
451 dt_prop_u32(dt, "device-id", device_id);
452 dt_prop_u32(dt, "class-code", class_id >> 8);
453 dt_prop_u32(dt, "revision-id", class_id & 0xff);
454 dt_prop_u32(dt, "linux,subbus", sub_bus);
455 dt_prop_u32(dt, "linux,agent-id", agent_id);
456 dt_prop_u32(dt, "linux,logical-slot-number",
457 bridge_info->logicalSlotNumber);
458 dt_end_node(dt);
459
460 }
461 }
462}
463
464static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus,
465 HvSubBusNumber sub_bus, int id_sel)
466{
467 struct HvCallPci_BridgeInfo bridge_info;
468 HvAgentId agent_id;
469 int function;
470 int ret;
471
472 /* Note: hvSubBus and irq is always be 0 at this level! */
473 for (function = 0; function < 8; ++function) {
474 agent_id = ISERIES_PCI_AGENTID(id_sel, function);
475 ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0);
476 if (ret != 0) {
477 if (ret != 0xb)
478 DBG("connectBusUnit(%x, %x, %x) %x\n",
479 bus, sub_bus, agent_id, ret);
480 continue;
481 }
482 DBG("found device at bus %d idsel %d func %d (AgentId %x)\n",
483 bus, id_sel, function, agent_id);
484 ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id,
485 iseries_hv_addr(&bridge_info),
486 sizeof(struct HvCallPci_BridgeInfo));
487 if (ret != 0)
488 continue;
489 DBG("bridge info: type %x subbus %x "
490 "maxAgents %x maxsubbus %x logslot %x\n",
491 bridge_info.busUnitInfo.deviceType,
492 bridge_info.subBusNumber,
493 bridge_info.maxAgents,
494 bridge_info.maxSubBusNumber,
495 bridge_info.logicalSlotNumber);
496 if (bridge_info.busUnitInfo.deviceType ==
497 HvCallPci_BridgeDevice)
498 scan_bridge_slot(dt, bus, &bridge_info);
499 else
500 DBG("PCI: Invalid Bridge Configuration(0x%02X)",
501 bridge_info.busUnitInfo.deviceType);
502 }
503}
504
505static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus)
506{
507 struct HvCallPci_DeviceInfo dev_info;
508 const HvSubBusNumber sub_bus = 0; /* EADs is always 0. */
509 int err;
510 int id_sel;
511 const int max_agents = 8;
512
513 /*
514 * Probe for EADs Bridges
515 */
516 for (id_sel = 1; id_sel < max_agents; ++id_sel) {
517 err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel,
518 iseries_hv_addr(&dev_info),
519 sizeof(struct HvCallPci_DeviceInfo));
520 if (err) {
521 if (err != 0x302)
522 DBG("getDeviceInfo(%x, %x, %x) %x\n",
523 bus, sub_bus, id_sel, err);
524 continue;
525 }
526 if (dev_info.deviceType != HvCallPci_NodeDevice) {
527 DBG("PCI: Invalid System Configuration"
528 "(0x%02X) for bus 0x%02x id 0x%02x.\n",
529 dev_info.deviceType, bus, id_sel);
530 continue;
531 }
532 scan_bridge(dt, bus, sub_bus, id_sel);
533 }
534}
535
536static void __init dt_pci_devices(struct iseries_flat_dt *dt)
537{
538 HvBusNumber bus;
539 char buf[32];
540 u32 buses[2];
541 int phb_num = 0;
542
543 /* Check all possible buses. */
544 for (bus = 0; bus < 256; bus++) {
545 int err = HvCallXm_testBus(bus);
546
547 if (err) {
548 /*
549 * Check for Unexpected Return code, a clue that
550 * something has gone wrong.
551 */
552 if (err != 0x0301)
553 DBG("Unexpected Return on Probe(0x%02X) "
554 "0x%04X\n", bus, err);
555 continue;
556 }
557 DBG("bus %d appears to exist\n", bus);
558 snprintf(buf, 32, "pci@%d", phb_num);
559 dt_start_node(dt, buf);
560 dt_prop_str(dt, "device_type", device_type_pci);
561 dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB");
562 dt_prop_u32(dt, "#address-cells", 3);
563 dt_prop_u32(dt, "#size-cells", 2);
564 buses[0] = buses[1] = bus;
565 dt_prop_u32_list(dt, "bus-range", buses, 2);
566 scan_phb(dt, bus);
567 dt_end_node(dt);
568 phb_num++;
569 }
570}
571
572static void dt_finish(struct iseries_flat_dt *dt)
573{
574 dt_push_u32(dt, OF_DT_END);
575 dt->header.totalsize = (unsigned long)dt_data - (unsigned long)dt;
576 klimit = ALIGN((unsigned long)dt_data, 8);
577}
578
579void * __init build_flat_dt(unsigned long phys_mem_size)
580{
581 struct iseries_flat_dt *iseries_dt;
582 u64 tmp[2];
583
584 iseries_dt = dt_init();
585
586 dt_start_node(iseries_dt, "");
587
588 dt_prop_u32(iseries_dt, "#address-cells", 2);
589 dt_prop_u32(iseries_dt, "#size-cells", 2);
590 dt_model(iseries_dt);
591
592 /* /memory */
593 dt_start_node(iseries_dt, "memory@0");
594 dt_prop_str(iseries_dt, "device_type", device_type_memory);
595 tmp[0] = 0;
596 tmp[1] = phys_mem_size;
597 dt_prop_u64_list(iseries_dt, "reg", tmp, 2);
598 dt_end_node(iseries_dt);
599
600 /* /chosen */
601 dt_start_node(iseries_dt, "chosen");
602 dt_prop_str(iseries_dt, "bootargs", cmd_line);
603 dt_end_node(iseries_dt);
604
605 dt_cpus(iseries_dt);
606
607 dt_vdevices(iseries_dt);
608 dt_pci_devices(iseries_dt);
609
610 dt_end_node(iseries_dt);
611
612 dt_finish(iseries_dt);
613
614 return iseries_dt;
615}
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index bea0b703f409..a992f6af249f 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -4,6 +4,7 @@
4 * Rewrite, cleanup: 4 * Rewrite, cleanup:
5 * 5 *
6 * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation 6 * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
7 * Copyright (C) 2006 Olof Johansson <olof@lixom.net>
7 * 8 *
8 * Dynamic DMA mapping support, iSeries-specific parts. 9 * Dynamic DMA mapping support, iSeries-specific parts.
9 * 10 *
@@ -31,42 +32,37 @@
31#include <asm/tce.h> 32#include <asm/tce.h>
32#include <asm/machdep.h> 33#include <asm/machdep.h>
33#include <asm/abs_addr.h> 34#include <asm/abs_addr.h>
35#include <asm/prom.h>
34#include <asm/pci-bridge.h> 36#include <asm/pci-bridge.h>
35#include <asm/iseries/hv_call_xm.h> 37#include <asm/iseries/hv_call_xm.h>
36 38#include <asm/iseries/iommu.h>
37#include "iommu.h"
38
39extern struct list_head iSeries_Global_Device_List;
40
41 39
42static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, 40static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
43 unsigned long uaddr, enum dma_data_direction direction) 41 unsigned long uaddr, enum dma_data_direction direction)
44{ 42{
45 u64 rc; 43 u64 rc;
46 union tce_entry tce; 44 u64 tce, rpn;
47 45
48 index <<= TCE_PAGE_FACTOR; 46 index <<= TCE_PAGE_FACTOR;
49 npages <<= TCE_PAGE_FACTOR; 47 npages <<= TCE_PAGE_FACTOR;
50 48
51 while (npages--) { 49 while (npages--) {
52 tce.te_word = 0; 50 rpn = virt_to_abs(uaddr) >> TCE_SHIFT;
53 tce.te_bits.tb_rpn = virt_to_abs(uaddr) >> TCE_SHIFT; 51 tce = (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
54 52
55 if (tbl->it_type == TCE_VB) { 53 if (tbl->it_type == TCE_VB) {
56 /* Virtual Bus */ 54 /* Virtual Bus */
57 tce.te_bits.tb_valid = 1; 55 tce |= TCE_VALID|TCE_ALLIO;
58 tce.te_bits.tb_allio = 1;
59 if (direction != DMA_TO_DEVICE) 56 if (direction != DMA_TO_DEVICE)
60 tce.te_bits.tb_rdwr = 1; 57 tce |= TCE_VB_WRITE;
61 } else { 58 } else {
62 /* PCI Bus */ 59 /* PCI Bus */
63 tce.te_bits.tb_rdwr = 1; /* Read allowed */ 60 tce |= TCE_PCI_READ; /* Read allowed */
64 if (direction != DMA_TO_DEVICE) 61 if (direction != DMA_TO_DEVICE)
65 tce.te_bits.tb_pciwr = 1; 62 tce |= TCE_PCI_WRITE;
66 } 63 }
67 64
68 rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, 65 rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, tce);
69 tce.te_word);
70 if (rc) 66 if (rc)
71 panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", 67 panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n",
72 rc); 68 rc);
@@ -124,7 +120,7 @@ void iommu_table_getparms_iSeries(unsigned long busno,
124 120
125 /* itc_size is in pages worth of table, it_size is in # of entries */ 121 /* itc_size is in pages worth of table, it_size is in # of entries */
126 tbl->it_size = ((parms->itc_size * TCE_PAGE_SIZE) / 122 tbl->it_size = ((parms->itc_size * TCE_PAGE_SIZE) /
127 sizeof(union tce_entry)) >> TCE_PAGE_FACTOR; 123 TCE_ENTRY_SIZE) >> TCE_PAGE_FACTOR;
128 tbl->it_busno = parms->itc_busno; 124 tbl->it_busno = parms->itc_busno;
129 tbl->it_offset = parms->itc_offset >> TCE_PAGE_FACTOR; 125 tbl->it_offset = parms->itc_offset >> TCE_PAGE_FACTOR;
130 tbl->it_index = parms->itc_index; 126 tbl->it_index = parms->itc_index;
@@ -142,10 +138,15 @@ void iommu_table_getparms_iSeries(unsigned long busno,
142 */ 138 */
143static struct iommu_table *iommu_table_find(struct iommu_table * tbl) 139static struct iommu_table *iommu_table_find(struct iommu_table * tbl)
144{ 140{
145 struct pci_dn *pdn; 141 struct device_node *node;
146 142
147 list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) { 143 for (node = NULL; (node = of_find_all_nodes(node)); ) {
148 struct iommu_table *it = pdn->iommu_table; 144 struct pci_dn *pdn = PCI_DN(node);
145 struct iommu_table *it;
146
147 if (pdn == NULL)
148 continue;
149 it = pdn->iommu_table;
149 if ((it != NULL) && 150 if ((it != NULL) &&
150 (it->it_type == TCE_PCI) && 151 (it->it_type == TCE_PCI) &&
151 (it->it_offset == tbl->it_offset) && 152 (it->it_offset == tbl->it_offset) &&
@@ -161,10 +162,13 @@ void iommu_devnode_init_iSeries(struct device_node *dn)
161{ 162{
162 struct iommu_table *tbl; 163 struct iommu_table *tbl;
163 struct pci_dn *pdn = PCI_DN(dn); 164 struct pci_dn *pdn = PCI_DN(dn);
165 u32 *lsn = (u32 *)get_property(dn, "linux,logical-slot-number", NULL);
166
167 BUG_ON(lsn == NULL);
164 168
165 tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); 169 tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
166 170
167 iommu_table_getparms_iSeries(pdn->busno, pdn->LogicalSlot, 0, tbl); 171 iommu_table_getparms_iSeries(pdn->busno, *lsn, 0, tbl);
168 172
169 /* Look for existing tce table */ 173 /* Look for existing tce table */
170 pdn->iommu_table = iommu_table_find(tbl); 174 pdn->iommu_table = iommu_table_find(tbl);
diff --git a/arch/powerpc/platforms/iseries/iommu.h b/arch/powerpc/platforms/iseries/iommu.h
deleted file mode 100644
index cb5658fbe657..000000000000
--- a/arch/powerpc/platforms/iseries/iommu.h
+++ /dev/null
@@ -1,35 +0,0 @@
1#ifndef _PLATFORMS_ISERIES_IOMMU_H
2#define _PLATFORMS_ISERIES_IOMMU_H
3
4/*
5 * Copyright (C) 2005 Stephen Rothwell, IBM Corporation
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the:
19 * Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330,
21 * Boston, MA 02111-1307 USA
22 */
23
24struct device_node;
25struct iommu_table;
26
27/* Creates table for an individual device node */
28extern void iommu_devnode_init_iSeries(struct device_node *dn);
29
30/* Get table parameters from HV */
31extern void iommu_table_getparms_iSeries(unsigned long busno,
32 unsigned char slotno, unsigned char virtbus,
33 struct iommu_table *tbl);
34
35#endif /* _PLATFORMS_ISERIES_IOMMU_H */
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index be3fbfc24e6c..62bbbcf5ded3 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -42,6 +42,7 @@
42#include <asm/iseries/it_lp_queue.h> 42#include <asm/iseries/it_lp_queue.h>
43 43
44#include "irq.h" 44#include "irq.h"
45#include "pci.h"
45#include "call_pci.h" 46#include "call_pci.h"
46 47
47#if defined(CONFIG_SMP) 48#if defined(CONFIG_SMP)
@@ -312,12 +313,12 @@ static hw_irq_controller iSeries_IRQ_handler = {
312 * Note that sub_bus is always 0 (at the moment at least). 313 * Note that sub_bus is always 0 (at the moment at least).
313 */ 314 */
314int __init iSeries_allocate_IRQ(HvBusNumber bus, 315int __init iSeries_allocate_IRQ(HvBusNumber bus,
315 HvSubBusNumber sub_bus, HvAgentId dev_id) 316 HvSubBusNumber sub_bus, u32 bsubbus)
316{ 317{
317 int virtirq; 318 int virtirq;
318 unsigned int realirq; 319 unsigned int realirq;
319 u8 idsel = (dev_id >> 4); 320 u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus);
320 u8 function = dev_id & 7; 321 u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus);
321 322
322 realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3) 323 realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3)
323 + function; 324 + function;
diff --git a/arch/powerpc/platforms/iseries/irq.h b/arch/powerpc/platforms/iseries/irq.h
index b9c801ba5a47..188aa808abd7 100644
--- a/arch/powerpc/platforms/iseries/irq.h
+++ b/arch/powerpc/platforms/iseries/irq.h
@@ -2,7 +2,7 @@
2#define _ISERIES_IRQ_H 2#define _ISERIES_IRQ_H
3 3
4extern void iSeries_init_IRQ(void); 4extern void iSeries_init_IRQ(void);
5extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId); 5extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, u32);
6extern void iSeries_activate_IRQs(void); 6extern void iSeries_activate_IRQs(void);
7extern int iSeries_get_irq(struct pt_regs *); 7extern int iSeries_get_irq(struct pt_regs *);
8 8
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
index d771b8ee857d..1a2c2a50f922 100644
--- a/arch/powerpc/platforms/iseries/mf.c
+++ b/arch/powerpc/platforms/iseries/mf.c
@@ -45,7 +45,6 @@
45 45
46#include "setup.h" 46#include "setup.h"
47 47
48extern int piranha_simulator;
49static int mf_initialized; 48static int mf_initialized;
50 49
51/* 50/*
@@ -658,7 +657,7 @@ static void mf_clear_src(void)
658 657
659void __init mf_display_progress(u16 value) 658void __init mf_display_progress(u16 value)
660{ 659{
661 if (piranha_simulator || !mf_initialized) 660 if (!mf_initialized)
662 return; 661 return;
663 662
664 if (0xFFFF == value) 663 if (0xFFFF == value)
@@ -1295,9 +1294,6 @@ __initcall(mf_proc_init);
1295 */ 1294 */
1296void iSeries_get_rtc_time(struct rtc_time *rtc_tm) 1295void iSeries_get_rtc_time(struct rtc_time *rtc_tm)
1297{ 1296{
1298 if (piranha_simulator)
1299 return;
1300
1301 mf_get_rtc(rtc_tm); 1297 mf_get_rtc(rtc_tm);
1302 rtc_tm->tm_mon--; 1298 rtc_tm->tm_mon--;
1303} 1299}
@@ -1316,9 +1312,6 @@ unsigned long iSeries_get_boot_time(void)
1316{ 1312{
1317 struct rtc_time tm; 1313 struct rtc_time tm;
1318 1314
1319 if (piranha_simulator)
1320 return 0;
1321
1322 mf_get_boot_rtc(&tm); 1315 mf_get_boot_rtc(&tm);
1323 return mktime(tm.tm_year + 1900, tm.tm_mon, tm.tm_mday, 1316 return mktime(tm.tm_year + 1900, tm.tm_mon, tm.tm_mday,
1324 tm.tm_hour, tm.tm_min, tm.tm_sec); 1317 tm.tm_hour, tm.tm_min, tm.tm_sec);
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index a19833b880e4..35bcc98111f5 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -37,36 +37,18 @@
37 37
38#include <asm/iseries/hv_call_xm.h> 38#include <asm/iseries/hv_call_xm.h>
39#include <asm/iseries/mf.h> 39#include <asm/iseries/mf.h>
40#include <asm/iseries/iommu.h>
40 41
41#include <asm/ppc-pci.h> 42#include <asm/ppc-pci.h>
42 43
43#include "irq.h" 44#include "irq.h"
44#include "pci.h" 45#include "pci.h"
45#include "call_pci.h" 46#include "call_pci.h"
46#include "iommu.h"
47
48extern unsigned long io_page_mask;
49 47
50/* 48/*
51 * Forward declares of prototypes. 49 * Forward declares of prototypes.
52 */ 50 */
53static struct device_node *find_Device_Node(int bus, int devfn); 51static struct device_node *find_Device_Node(int bus, int devfn);
54static void scan_PHB_slots(struct pci_controller *Phb);
55static void scan_EADS_bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel);
56static int scan_bridge_slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo *Info);
57
58LIST_HEAD(iSeries_Global_Device_List);
59
60static int DeviceCount;
61
62/* Counters and control flags. */
63static long Pci_Io_Read_Count;
64static long Pci_Io_Write_Count;
65#if 0
66static long Pci_Cfg_Read_Count;
67static long Pci_Cfg_Write_Count;
68#endif
69static long Pci_Error_Count;
70 52
71static int Pci_Retry_Max = 3; /* Only retry 3 times */ 53static int Pci_Retry_Max = 3; /* Only retry 3 times */
72static int Pci_Error_Flag = 1; /* Set Retry Error on. */ 54static int Pci_Error_Flag = 1; /* Set Retry Error on. */
@@ -81,41 +63,19 @@ static struct pci_ops iSeries_pci_ops;
81#define IOMM_TABLE_ENTRY_SIZE 0x0000000000400000UL 63#define IOMM_TABLE_ENTRY_SIZE 0x0000000000400000UL
82#define BASE_IO_MEMORY 0xE000000000000000UL 64#define BASE_IO_MEMORY 0xE000000000000000UL
83 65
84static unsigned long max_io_memory = 0xE000000000000000UL; 66static unsigned long max_io_memory = BASE_IO_MEMORY;
85static long current_iomm_table_entry; 67static long current_iomm_table_entry;
86 68
87/* 69/*
88 * Lookup Tables. 70 * Lookup Tables.
89 */ 71 */
90static struct device_node **iomm_table; 72static struct device_node *iomm_table[IOMM_TABLE_MAX_ENTRIES];
91static u8 *iobar_table; 73static u8 iobar_table[IOMM_TABLE_MAX_ENTRIES];
92 74
93/* 75static const char pci_io_text[] = "iSeries PCI I/O";
94 * Static and Global variables
95 */
96static char *pci_io_text = "iSeries PCI I/O";
97static DEFINE_SPINLOCK(iomm_table_lock); 76static DEFINE_SPINLOCK(iomm_table_lock);
98 77
99/* 78/*
100 * iomm_table_initialize
101 *
102 * Allocates and initalizes the Address Translation Table and Bar
103 * Tables to get them ready for use. Must be called before any
104 * I/O space is handed out to the device BARs.
105 */
106static void iomm_table_initialize(void)
107{
108 spin_lock(&iomm_table_lock);
109 iomm_table = kmalloc(sizeof(*iomm_table) * IOMM_TABLE_MAX_ENTRIES,
110 GFP_KERNEL);
111 iobar_table = kmalloc(sizeof(*iobar_table) * IOMM_TABLE_MAX_ENTRIES,
112 GFP_KERNEL);
113 spin_unlock(&iomm_table_lock);
114 if ((iomm_table == NULL) || (iobar_table == NULL))
115 panic("PCI: I/O tables allocation failed.\n");
116}
117
118/*
119 * iomm_table_allocate_entry 79 * iomm_table_allocate_entry
120 * 80 *
121 * Adds pci_dev entry in address translation table 81 * Adds pci_dev entry in address translation table
@@ -142,9 +102,8 @@ static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
142 */ 102 */
143 spin_lock(&iomm_table_lock); 103 spin_lock(&iomm_table_lock);
144 bar_res->name = pci_io_text; 104 bar_res->name = pci_io_text;
145 bar_res->start = 105 bar_res->start = BASE_IO_MEMORY +
146 IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry; 106 IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
147 bar_res->start += BASE_IO_MEMORY;
148 bar_res->end = bar_res->start + bar_size - 1; 107 bar_res->end = bar_res->start + bar_size - 1;
149 /* 108 /*
150 * Allocate the number of table entries needed for BAR. 109 * Allocate the number of table entries needed for BAR.
@@ -156,7 +115,7 @@ static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
156 ++current_iomm_table_entry; 115 ++current_iomm_table_entry;
157 } 116 }
158 max_io_memory = BASE_IO_MEMORY + 117 max_io_memory = BASE_IO_MEMORY +
159 (IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry); 118 IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
160 spin_unlock(&iomm_table_lock); 119 spin_unlock(&iomm_table_lock);
161} 120}
162 121
@@ -173,13 +132,10 @@ static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
173 */ 132 */
174static void allocate_device_bars(struct pci_dev *dev) 133static void allocate_device_bars(struct pci_dev *dev)
175{ 134{
176 struct resource *bar_res;
177 int bar_num; 135 int bar_num;
178 136
179 for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num) { 137 for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num)
180 bar_res = &dev->resource[bar_num];
181 iomm_table_allocate_entry(dev, bar_num); 138 iomm_table_allocate_entry(dev, bar_num);
182 }
183} 139}
184 140
185/* 141/*
@@ -199,34 +155,7 @@ static void pci_Log_Error(char *Error_Text, int Bus, int SubBus,
199} 155}
200 156
201/* 157/*
202 * build_device_node(u16 Bus, int SubBus, u8 DevFn) 158 * iSeries_pcibios_init
203 */
204static struct device_node *build_device_node(HvBusNumber Bus,
205 HvSubBusNumber SubBus, int AgentId, int Function)
206{
207 struct device_node *node;
208 struct pci_dn *pdn;
209
210 node = kmalloc(sizeof(struct device_node), GFP_KERNEL);
211 if (node == NULL)
212 return NULL;
213 memset(node, 0, sizeof(struct device_node));
214 pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
215 if (pdn == NULL) {
216 kfree(node);
217 return NULL;
218 }
219 node->data = pdn;
220 pdn->node = node;
221 list_add_tail(&pdn->Device_List, &iSeries_Global_Device_List);
222 pdn->busno = Bus;
223 pdn->bussubno = SubBus;
224 pdn->devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function);
225 return node;
226}
227
228/*
229 * unsigned long __init find_and_init_phbs(void)
230 * 159 *
231 * Description: 160 * Description:
232 * This function checks for all possible system PCI host bridges that connect 161 * This function checks for all possible system PCI host bridges that connect
@@ -234,50 +163,42 @@ static struct device_node *build_device_node(HvBusNumber Bus,
234 * ownership status. A pci_controller is built for any bus which is partially 163 * ownership status. A pci_controller is built for any bus which is partially
235 * owned or fully owned by this guest partition. 164 * owned or fully owned by this guest partition.
236 */ 165 */
237unsigned long __init find_and_init_phbs(void) 166void iSeries_pcibios_init(void)
238{ 167{
239 struct pci_controller *phb; 168 struct pci_controller *phb;
240 HvBusNumber bus; 169 struct device_node *root = of_find_node_by_path("/");
241 170 struct device_node *node = NULL;
242 /* Check all possible buses. */
243 for (bus = 0; bus < 256; bus++) {
244 int ret = HvCallXm_testBus(bus);
245 if (ret == 0) {
246 printk("bus %d appears to exist\n", bus);
247 171
248 phb = pcibios_alloc_controller(NULL); 172 if (root == NULL) {
249 if (phb == NULL) 173 printk(KERN_CRIT "iSeries_pcibios_init: can't find root "
250 return -ENOMEM; 174 "of device tree\n");
251 175 return;
252 phb->pci_mem_offset = phb->local_number = bus; 176 }
253 phb->first_busno = bus; 177 while ((node = of_get_next_child(root, node)) != NULL) {
254 phb->last_busno = bus; 178 HvBusNumber bus;
255 phb->ops = &iSeries_pci_ops; 179 u32 *busp;
256 180
257 /* Find and connect the devices. */ 181 if ((node->type == NULL) || (strcmp(node->type, "pci") != 0))
258 scan_PHB_slots(phb); 182 continue;
259 } 183
260 /* 184 busp = (u32 *)get_property(node, "bus-range", NULL);
261 * Check for Unexpected Return code, a clue that something 185 if (busp == NULL)
262 * has gone wrong. 186 continue;
263 */ 187 bus = *busp;
264 else if (ret != 0x0301) 188 printk("bus %d appears to exist\n", bus);
265 printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X", 189 phb = pcibios_alloc_controller(node);
266 bus, ret); 190 if (phb == NULL)
191 continue;
192
193 phb->pci_mem_offset = phb->local_number = bus;
194 phb->first_busno = bus;
195 phb->last_busno = bus;
196 phb->ops = &iSeries_pci_ops;
267 } 197 }
268 return 0;
269}
270 198
271/* 199 of_node_put(root);
272 * iSeries_pcibios_init 200
273 * 201 pci_devs_phb_init();
274 * Chance to initialize and structures or variable before PCI Bus walk.
275 */
276void iSeries_pcibios_init(void)
277{
278 iomm_table_initialize();
279 find_and_init_phbs();
280 io_page_mask = -1;
281} 202}
282 203
283/* 204/*
@@ -299,6 +220,34 @@ void __init iSeries_pci_final_fixup(void)
299 pdev->bus->number, pdev->devfn, node); 220 pdev->bus->number, pdev->devfn, node);
300 221
301 if (node != NULL) { 222 if (node != NULL) {
223 struct pci_dn *pdn = PCI_DN(node);
224 u32 *agent;
225
226 agent = (u32 *)get_property(node, "linux,agent-id",
227 NULL);
228 if ((pdn != NULL) && (agent != NULL)) {
229 u8 irq = iSeries_allocate_IRQ(pdn->busno, 0,
230 pdn->bussubno);
231 int err;
232
233 err = HvCallXm_connectBusUnit(pdn->busno, pdn->bussubno,
234 *agent, irq);
235 if (err)
236 pci_Log_Error("Connect Bus Unit",
237 pdn->busno, pdn->bussubno, *agent, err);
238 else {
239 err = HvCallPci_configStore8(pdn->busno, pdn->bussubno,
240 *agent,
241 PCI_INTERRUPT_LINE,
242 irq);
243 if (err)
244 pci_Log_Error("PciCfgStore Irq Failed!",
245 pdn->busno, pdn->bussubno, *agent, err);
246 }
247 if (!err)
248 pdev->irq = irq;
249 }
250
302 ++DeviceCount; 251 ++DeviceCount;
303 pdev->sysdata = (void *)node; 252 pdev->sysdata = (void *)node;
304 PCI_DN(node)->pcidev = pdev; 253 PCI_DN(node)->pcidev = pdev;
@@ -308,7 +257,6 @@ void __init iSeries_pci_final_fixup(void)
308 } else 257 } else
309 printk("PCI: Device Tree not found for 0x%016lX\n", 258 printk("PCI: Device Tree not found for 0x%016lX\n",
310 (unsigned long)pdev); 259 (unsigned long)pdev);
311 pdev->irq = PCI_DN(node)->Irq;
312 } 260 }
313 iSeries_activate_IRQs(); 261 iSeries_activate_IRQs();
314 mf_display_src(0xC9000200); 262 mf_display_src(0xC9000200);
@@ -323,148 +271,6 @@ void pcibios_fixup_resources(struct pci_dev *pdev)
323} 271}
324 272
325/* 273/*
326 * Loop through each node function to find usable EADs bridges.
327 */
328static void scan_PHB_slots(struct pci_controller *Phb)
329{
330 struct HvCallPci_DeviceInfo *DevInfo;
331 HvBusNumber bus = Phb->local_number; /* System Bus */
332 const HvSubBusNumber SubBus = 0; /* EADs is always 0. */
333 int HvRc = 0;
334 int IdSel;
335 const int MaxAgents = 8;
336
337 DevInfo = (struct HvCallPci_DeviceInfo*)
338 kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL);
339 if (DevInfo == NULL)
340 return;
341
342 /*
343 * Probe for EADs Bridges
344 */
345 for (IdSel = 1; IdSel < MaxAgents; ++IdSel) {
346 HvRc = HvCallPci_getDeviceInfo(bus, SubBus, IdSel,
347 iseries_hv_addr(DevInfo),
348 sizeof(struct HvCallPci_DeviceInfo));
349 if (HvRc == 0) {
350 if (DevInfo->deviceType == HvCallPci_NodeDevice)
351 scan_EADS_bridge(bus, SubBus, IdSel);
352 else
353 printk("PCI: Invalid System Configuration(0x%02X)"
354 " for bus 0x%02x id 0x%02x.\n",
355 DevInfo->deviceType, bus, IdSel);
356 }
357 else
358 pci_Log_Error("getDeviceInfo", bus, SubBus, IdSel, HvRc);
359 }
360 kfree(DevInfo);
361}
362
363static void scan_EADS_bridge(HvBusNumber bus, HvSubBusNumber SubBus,
364 int IdSel)
365{
366 struct HvCallPci_BridgeInfo *BridgeInfo;
367 HvAgentId AgentId;
368 int Function;
369 int HvRc;
370
371 BridgeInfo = (struct HvCallPci_BridgeInfo *)
372 kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL);
373 if (BridgeInfo == NULL)
374 return;
375
376 /* Note: hvSubBus and irq is always be 0 at this level! */
377 for (Function = 0; Function < 8; ++Function) {
378 AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
379 HvRc = HvCallXm_connectBusUnit(bus, SubBus, AgentId, 0);
380 if (HvRc == 0) {
381 printk("found device at bus %d idsel %d func %d (AgentId %x)\n",
382 bus, IdSel, Function, AgentId);
383 /* Connect EADs: 0x18.00.12 = 0x00 */
384 HvRc = HvCallPci_getBusUnitInfo(bus, SubBus, AgentId,
385 iseries_hv_addr(BridgeInfo),
386 sizeof(struct HvCallPci_BridgeInfo));
387 if (HvRc == 0) {
388 printk("bridge info: type %x subbus %x maxAgents %x maxsubbus %x logslot %x\n",
389 BridgeInfo->busUnitInfo.deviceType,
390 BridgeInfo->subBusNumber,
391 BridgeInfo->maxAgents,
392 BridgeInfo->maxSubBusNumber,
393 BridgeInfo->logicalSlotNumber);
394 if (BridgeInfo->busUnitInfo.deviceType ==
395 HvCallPci_BridgeDevice) {
396 /* Scan_Bridge_Slot...: 0x18.00.12 */
397 scan_bridge_slot(bus, BridgeInfo);
398 } else
399 printk("PCI: Invalid Bridge Configuration(0x%02X)",
400 BridgeInfo->busUnitInfo.deviceType);
401 }
402 } else if (HvRc != 0x000B)
403 pci_Log_Error("EADs Connect",
404 bus, SubBus, AgentId, HvRc);
405 }
406 kfree(BridgeInfo);
407}
408
409/*
410 * This assumes that the node slot is always on the primary bus!
411 */
412static int scan_bridge_slot(HvBusNumber Bus,
413 struct HvCallPci_BridgeInfo *BridgeInfo)
414{
415 struct device_node *node;
416 HvSubBusNumber SubBus = BridgeInfo->subBusNumber;
417 u16 VendorId = 0;
418 int HvRc = 0;
419 u8 Irq = 0;
420 int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus);
421 int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus);
422 HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function);
423
424 /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */
425 Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel);
426
427 /*
428 * Connect all functions of any device found.
429 */
430 for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) {
431 for (Function = 0; Function < 8; ++Function) {
432 HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
433 HvRc = HvCallXm_connectBusUnit(Bus, SubBus,
434 AgentId, Irq);
435 if (HvRc != 0) {
436 pci_Log_Error("Connect Bus Unit",
437 Bus, SubBus, AgentId, HvRc);
438 continue;
439 }
440
441 HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId,
442 PCI_VENDOR_ID, &VendorId);
443 if (HvRc != 0) {
444 pci_Log_Error("Read Vendor",
445 Bus, SubBus, AgentId, HvRc);
446 continue;
447 }
448 printk("read vendor ID: %x\n", VendorId);
449
450 /* FoundDevice: 0x18.28.10 = 0x12AE */
451 HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId,
452 PCI_INTERRUPT_LINE, Irq);
453 if (HvRc != 0)
454 pci_Log_Error("PciCfgStore Irq Failed!",
455 Bus, SubBus, AgentId, HvRc);
456
457 ++DeviceCount;
458 node = build_device_node(Bus, SubBus, EADsIdSel, Function);
459 PCI_DN(node)->Irq = Irq;
460 PCI_DN(node)->LogicalSlot = BridgeInfo->logicalSlotNumber;
461
462 } /* for (Function = 0; Function < 8; ++Function) */
463 } /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */
464 return HvRc;
465}
466
467/*
468 * I/0 Memory copy MUST use mmio commands on iSeries 274 * I/0 Memory copy MUST use mmio commands on iSeries
469 * To do; For performance, include the hv call directly 275 * To do; For performance, include the hv call directly
470 */ 276 */
@@ -509,11 +315,13 @@ EXPORT_SYMBOL(iSeries_memcpy_fromio);
509 */ 315 */
510static struct device_node *find_Device_Node(int bus, int devfn) 316static struct device_node *find_Device_Node(int bus, int devfn)
511{ 317{
512 struct pci_dn *pdn; 318 struct device_node *node;
319
320 for (node = NULL; (node = of_find_all_nodes(node)); ) {
321 struct pci_dn *pdn = PCI_DN(node);
513 322
514 list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) { 323 if (pdn && (bus == pdn->busno) && (devfn == pdn->devfn))
515 if ((bus == pdn->busno) && (devfn == pdn->devfn)) 324 return node;
516 return pdn->node;
517 } 325 }
518 return NULL; 326 return NULL;
519} 327}
@@ -625,7 +433,6 @@ static int CheckReturnCode(char *TextHdr, struct device_node *DevNode,
625 if (ret != 0) { 433 if (ret != 0) {
626 struct pci_dn *pdn = PCI_DN(DevNode); 434 struct pci_dn *pdn = PCI_DN(DevNode);
627 435
628 ++Pci_Error_Count;
629 (*retry)++; 436 (*retry)++;
630 printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n", 437 printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n",
631 TextHdr, pdn->busno, pdn->devfn, 438 TextHdr, pdn->busno, pdn->devfn,
@@ -707,7 +514,6 @@ u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
707 return 0xff; 514 return 0xff;
708 } 515 }
709 do { 516 do {
710 ++Pci_Io_Read_Count;
711 HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0); 517 HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0);
712 } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0); 518 } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0);
713 519
@@ -737,7 +543,6 @@ u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
737 return 0xffff; 543 return 0xffff;
738 } 544 }
739 do { 545 do {
740 ++Pci_Io_Read_Count;
741 HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa, 546 HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,
742 BarOffset, 0); 547 BarOffset, 0);
743 } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0); 548 } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0);
@@ -768,7 +573,6 @@ u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
768 return 0xffffffff; 573 return 0xffffffff;
769 } 574 }
770 do { 575 do {
771 ++Pci_Io_Read_Count;
772 HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa, 576 HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa,
773 BarOffset, 0); 577 BarOffset, 0);
774 } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0); 578 } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0);
@@ -806,7 +610,6 @@ void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
806 return; 610 return;
807 } 611 }
808 do { 612 do {
809 ++Pci_Io_Write_Count;
810 rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0); 613 rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0);
811 } while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0); 614 } while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0);
812} 615}
@@ -834,7 +637,6 @@ void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
834 return; 637 return;
835 } 638 }
836 do { 639 do {
837 ++Pci_Io_Write_Count;
838 rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0); 640 rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0);
839 } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0); 641 } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0);
840} 642}
@@ -862,7 +664,6 @@ void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
862 return; 664 return;
863 } 665 }
864 do { 666 do {
865 ++Pci_Io_Write_Count;
866 rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0); 667 rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0);
867 } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0); 668 } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0);
868} 669}
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index a6fd9bedb074..617c724c4590 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -50,7 +50,6 @@
50#include <asm/iseries/hv_call_xm.h> 50#include <asm/iseries/hv_call_xm.h>
51#include <asm/iseries/it_lp_queue.h> 51#include <asm/iseries/it_lp_queue.h>
52#include <asm/iseries/mf.h> 52#include <asm/iseries/mf.h>
53#include <asm/iseries/it_exp_vpd_panel.h>
54#include <asm/iseries/hv_lp_event.h> 53#include <asm/iseries/hv_lp_event.h>
55#include <asm/iseries/lpar_map.h> 54#include <asm/iseries/lpar_map.h>
56#include <asm/udbg.h> 55#include <asm/udbg.h>
@@ -81,9 +80,6 @@ extern void iSeries_pci_final_fixup(void);
81static void iSeries_pci_final_fixup(void) { } 80static void iSeries_pci_final_fixup(void) { }
82#endif 81#endif
83 82
84/* Global Variables */
85int piranha_simulator;
86
87extern int rd_size; /* Defined in drivers/block/rd.c */ 83extern int rd_size; /* Defined in drivers/block/rd.c */
88extern unsigned long embedded_sysmap_start; 84extern unsigned long embedded_sysmap_start;
89extern unsigned long embedded_sysmap_end; 85extern unsigned long embedded_sysmap_end;
@@ -91,8 +87,6 @@ extern unsigned long embedded_sysmap_end;
91extern unsigned long iSeries_recal_tb; 87extern unsigned long iSeries_recal_tb;
92extern unsigned long iSeries_recal_titan; 88extern unsigned long iSeries_recal_titan;
93 89
94static unsigned long cmd_mem_limit;
95
96struct MemoryBlock { 90struct MemoryBlock {
97 unsigned long absStart; 91 unsigned long absStart;
98 unsigned long absEnd; 92 unsigned long absEnd;
@@ -340,8 +334,6 @@ static void __init iSeries_init_early(void)
340#ifdef CONFIG_SMP 334#ifdef CONFIG_SMP
341 smp_init_iSeries(); 335 smp_init_iSeries();
342#endif 336#endif
343 if (itLpNaca.xPirEnvironMode == 0)
344 piranha_simulator = 1;
345 337
346 /* Associate Lp Event Queue 0 with processor 0 */ 338 /* Associate Lp Event Queue 0 with processor 0 */
347 HvCallEvent_setLpEventQueueInterruptProc(0, 0); 339 HvCallEvent_setLpEventQueueInterruptProc(0, 0);
@@ -536,10 +528,10 @@ static void __init iSeries_setup_arch(void)
536{ 528{
537 if (get_lppaca()->shared_proc) { 529 if (get_lppaca()->shared_proc) {
538 ppc_md.idle_loop = iseries_shared_idle; 530 ppc_md.idle_loop = iseries_shared_idle;
539 printk(KERN_INFO "Using shared processor idle loop\n"); 531 printk(KERN_DEBUG "Using shared processor idle loop\n");
540 } else { 532 } else {
541 ppc_md.idle_loop = iseries_dedicated_idle; 533 ppc_md.idle_loop = iseries_dedicated_idle;
542 printk(KERN_INFO "Using dedicated idle loop\n"); 534 printk(KERN_DEBUG "Using dedicated idle loop\n");
543 } 535 }
544 536
545 /* Setup the Lp Event Queue */ 537 /* Setup the Lp Event Queue */
@@ -714,243 +706,6 @@ define_machine(iseries) {
714 /* XXX Implement enable_pmcs for iSeries */ 706 /* XXX Implement enable_pmcs for iSeries */
715}; 707};
716 708
717struct blob {
718 unsigned char data[PAGE_SIZE];
719 unsigned long next;
720};
721
722struct iseries_flat_dt {
723 struct boot_param_header header;
724 u64 reserve_map[2];
725 struct blob dt;
726 struct blob strings;
727};
728
729struct iseries_flat_dt iseries_dt;
730
731void dt_init(struct iseries_flat_dt *dt)
732{
733 dt->header.off_mem_rsvmap =
734 offsetof(struct iseries_flat_dt, reserve_map);
735 dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt);
736 dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings);
737 dt->header.totalsize = sizeof(struct iseries_flat_dt);
738 dt->header.dt_strings_size = sizeof(struct blob);
739
740 /* There is no notion of hardware cpu id on iSeries */
741 dt->header.boot_cpuid_phys = smp_processor_id();
742
743 dt->dt.next = (unsigned long)&dt->dt.data;
744 dt->strings.next = (unsigned long)&dt->strings.data;
745
746 dt->header.magic = OF_DT_HEADER;
747 dt->header.version = 0x10;
748 dt->header.last_comp_version = 0x10;
749
750 dt->reserve_map[0] = 0;
751 dt->reserve_map[1] = 0;
752}
753
754void dt_check_blob(struct blob *b)
755{
756 if (b->next >= (unsigned long)&b->next) {
757 DBG("Ran out of space in flat device tree blob!\n");
758 BUG();
759 }
760}
761
762void dt_push_u32(struct iseries_flat_dt *dt, u32 value)
763{
764 *((u32*)dt->dt.next) = value;
765 dt->dt.next += sizeof(u32);
766
767 dt_check_blob(&dt->dt);
768}
769
770void dt_push_u64(struct iseries_flat_dt *dt, u64 value)
771{
772 *((u64*)dt->dt.next) = value;
773 dt->dt.next += sizeof(u64);
774
775 dt_check_blob(&dt->dt);
776}
777
778unsigned long dt_push_bytes(struct blob *blob, char *data, int len)
779{
780 unsigned long start = blob->next - (unsigned long)blob->data;
781
782 memcpy((char *)blob->next, data, len);
783 blob->next = _ALIGN(blob->next + len, 4);
784
785 dt_check_blob(blob);
786
787 return start;
788}
789
790void dt_start_node(struct iseries_flat_dt *dt, char *name)
791{
792 dt_push_u32(dt, OF_DT_BEGIN_NODE);
793 dt_push_bytes(&dt->dt, name, strlen(name) + 1);
794}
795
796#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
797
798void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len)
799{
800 unsigned long offset;
801
802 dt_push_u32(dt, OF_DT_PROP);
803
804 /* Length of the data */
805 dt_push_u32(dt, len);
806
807 /* Put the property name in the string blob. */
808 offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1);
809
810 /* The offset of the properties name in the string blob. */
811 dt_push_u32(dt, (u32)offset);
812
813 /* The actual data. */
814 dt_push_bytes(&dt->dt, data, len);
815}
816
817void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data)
818{
819 dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
820}
821
822void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
823{
824 dt_prop(dt, name, (char *)&data, sizeof(u32));
825}
826
827void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
828{
829 dt_prop(dt, name, (char *)&data, sizeof(u64));
830}
831
832void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n)
833{
834 dt_prop(dt, name, (char *)data, sizeof(u64) * n);
835}
836
837void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n)
838{
839 dt_prop(dt, name, (char *)data, sizeof(u32) * n);
840}
841
842void dt_prop_empty(struct iseries_flat_dt *dt, char *name)
843{
844 dt_prop(dt, name, NULL, 0);
845}
846
847void dt_cpus(struct iseries_flat_dt *dt)
848{
849 unsigned char buf[32];
850 unsigned char *p;
851 unsigned int i, index;
852 struct IoHriProcessorVpd *d;
853 u32 pft_size[2];
854
855 /* yuck */
856 snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name);
857 p = strchr(buf, ' ');
858 if (!p) p = buf + strlen(buf);
859
860 dt_start_node(dt, "cpus");
861 dt_prop_u32(dt, "#address-cells", 1);
862 dt_prop_u32(dt, "#size-cells", 0);
863
864 pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA */
865 pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);
866
867 for (i = 0; i < NR_CPUS; i++) {
868 if (lppaca[i].dyn_proc_status >= 2)
869 continue;
870
871 snprintf(p, 32 - (p - buf), "@%d", i);
872 dt_start_node(dt, buf);
873
874 dt_prop_str(dt, "device_type", "cpu");
875
876 index = lppaca[i].dyn_hv_phys_proc_index;
877 d = &xIoHriProcessorVpd[index];
878
879 dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
880 dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize);
881
882 dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024);
883 dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize);
884
885 /* magic conversions to Hz copied from old code */
886 dt_prop_u32(dt, "clock-frequency",
887 ((1UL << 34) * 1000000) / d->xProcFreq);
888 dt_prop_u32(dt, "timebase-frequency",
889 ((1UL << 32) * 1000000) / d->xTimeBaseFreq);
890
891 dt_prop_u32(dt, "reg", i);
892
893 dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2);
894
895 dt_end_node(dt);
896 }
897
898 dt_end_node(dt);
899}
900
901void dt_model(struct iseries_flat_dt *dt)
902{
903 char buf[16] = "IBM,";
904
905 /* "IBM," + mfgId[2:3] + systemSerial[1:5] */
906 strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2);
907 strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5);
908 buf[11] = '\0';
909 dt_prop_str(dt, "system-id", buf);
910
911 /* "IBM," + machineType[0:4] */
912 strne2a(buf + 4, xItExtVpdPanel.machineType, 4);
913 buf[8] = '\0';
914 dt_prop_str(dt, "model", buf);
915
916 dt_prop_str(dt, "compatible", "IBM,iSeries");
917}
918
919void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
920{
921 u64 tmp[2];
922
923 dt_init(dt);
924
925 dt_start_node(dt, "");
926
927 dt_prop_u32(dt, "#address-cells", 2);
928 dt_prop_u32(dt, "#size-cells", 2);
929 dt_model(dt);
930
931 /* /memory */
932 dt_start_node(dt, "memory@0");
933 dt_prop_str(dt, "name", "memory");
934 dt_prop_str(dt, "device_type", "memory");
935 tmp[0] = 0;
936 tmp[1] = phys_mem_size;
937 dt_prop_u64_list(dt, "reg", tmp, 2);
938 dt_end_node(dt);
939
940 /* /chosen */
941 dt_start_node(dt, "chosen");
942 dt_prop_str(dt, "bootargs", cmd_line);
943 if (cmd_mem_limit)
944 dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit);
945 dt_end_node(dt);
946
947 dt_cpus(dt);
948
949 dt_end_node(dt);
950
951 dt_push_u32(dt, OF_DT_END);
952}
953
954void * __init iSeries_early_setup(void) 709void * __init iSeries_early_setup(void)
955{ 710{
956 unsigned long phys_mem_size; 711 unsigned long phys_mem_size;
@@ -965,28 +720,8 @@ void * __init iSeries_early_setup(void)
965 720
966 iSeries_get_cmdline(); 721 iSeries_get_cmdline();
967 722
968 /* Save unparsed command line copy for /proc/cmdline */ 723 return (void *) __pa(build_flat_dt(phys_mem_size));
969 strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
970
971 /* Parse early parameters, in particular mem=x */
972 parse_early_param();
973
974 build_flat_dt(&iseries_dt, phys_mem_size);
975
976 return (void *) __pa(&iseries_dt);
977}
978
979/*
980 * On iSeries we just parse the mem=X option from the command line.
981 * On pSeries it's a bit more complicated, see prom_init_mem()
982 */
983static int __init early_parsemem(char *p)
984{
985 if (p)
986 cmd_mem_limit = ALIGN(memparse(p, &p), PAGE_SIZE);
987 return 0;
988} 724}
989early_param("mem", early_parsemem);
990 725
991static void hvputc(char c) 726static void hvputc(char c)
992{ 727{
diff --git a/arch/powerpc/platforms/iseries/setup.h b/arch/powerpc/platforms/iseries/setup.h
index 5213044ec411..0a47ac53c959 100644
--- a/arch/powerpc/platforms/iseries/setup.h
+++ b/arch/powerpc/platforms/iseries/setup.h
@@ -21,4 +21,6 @@ extern unsigned long iSeries_get_boot_time(void);
21extern int iSeries_set_rtc_time(struct rtc_time *tm); 21extern int iSeries_set_rtc_time(struct rtc_time *tm);
22extern void iSeries_get_rtc_time(struct rtc_time *tm); 22extern void iSeries_get_rtc_time(struct rtc_time *tm);
23 23
24extern void *build_flat_dt(unsigned long phys_mem_size);
25
24#endif /* __ISERIES_SETUP_H__ */ 26#endif /* __ISERIES_SETUP_H__ */
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
deleted file mode 100644
index ad36ab0639f0..000000000000
--- a/arch/powerpc/platforms/iseries/vio.c
+++ /dev/null
@@ -1,131 +0,0 @@
1/*
2 * IBM PowerPC iSeries Virtual I/O Infrastructure Support.
3 *
4 * Copyright (c) 2005 Stephen Rothwell, IBM Corp.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#include <linux/types.h>
12#include <linux/device.h>
13#include <linux/init.h>
14
15#include <asm/vio.h>
16#include <asm/iommu.h>
17#include <asm/tce.h>
18#include <asm/abs_addr.h>
19#include <asm/page.h>
20#include <asm/iseries/vio.h>
21#include <asm/iseries/hv_types.h>
22#include <asm/iseries/hv_lp_config.h>
23#include <asm/iseries/hv_call_xm.h>
24
25#include "iommu.h"
26
27struct device *iSeries_vio_dev = &vio_bus_device.dev;
28EXPORT_SYMBOL(iSeries_vio_dev);
29
30static struct iommu_table veth_iommu_table;
31static struct iommu_table vio_iommu_table;
32
33static void __init iommu_vio_init(void)
34{
35 iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table);
36 veth_iommu_table.it_size /= 2;
37 vio_iommu_table = veth_iommu_table;
38 vio_iommu_table.it_offset += veth_iommu_table.it_size;
39
40 if (!iommu_init_table(&veth_iommu_table))
41 printk("Virtual Bus VETH TCE table failed.\n");
42 if (!iommu_init_table(&vio_iommu_table))
43 printk("Virtual Bus VIO TCE table failed.\n");
44}
45
46/**
47 * vio_register_device_iseries: - Register a new iSeries vio device.
48 * @voidev: The device to register.
49 */
50static struct vio_dev *__init vio_register_device_iseries(char *type,
51 uint32_t unit_num)
52{
53 struct vio_dev *viodev;
54
55 /* allocate a vio_dev for this device */
56 viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
57 if (!viodev)
58 return NULL;
59 memset(viodev, 0, sizeof(struct vio_dev));
60
61 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num);
62
63 viodev->name = viodev->dev.bus_id;
64 viodev->type = type;
65 viodev->unit_address = unit_num;
66 viodev->iommu_table = &vio_iommu_table;
67 if (vio_register_device(viodev) == NULL) {
68 kfree(viodev);
69 return NULL;
70 }
71 return viodev;
72}
73
74void __init probe_bus_iseries(void)
75{
76 HvLpIndexMap vlan_map;
77 struct vio_dev *viodev;
78 int i;
79
80 /* there is only one of each of these */
81 vio_register_device_iseries("viocons", 0);
82 vio_register_device_iseries("vscsi", 0);
83
84 vlan_map = HvLpConfig_getVirtualLanIndexMap();
85 for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
86 if ((vlan_map & (0x8000 >> i)) == 0)
87 continue;
88 viodev = vio_register_device_iseries("vlan", i);
89 /* veth is special and has it own iommu_table */
90 viodev->iommu_table = &veth_iommu_table;
91 }
92 for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
93 vio_register_device_iseries("viodasd", i);
94 for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
95 vio_register_device_iseries("viocd", i);
96 for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
97 vio_register_device_iseries("viotape", i);
98}
99
100/**
101 * vio_match_device_iseries: - Tell if a iSeries VIO device matches a
102 * vio_device_id
103 */
104static int vio_match_device_iseries(const struct vio_device_id *id,
105 const struct vio_dev *dev)
106{
107 return strncmp(dev->type, id->type, strlen(id->type)) == 0;
108}
109
110static struct vio_bus_ops vio_bus_ops_iseries = {
111 .match = vio_match_device_iseries,
112};
113
114/**
115 * vio_bus_init_iseries: - Initialize the iSeries virtual IO bus
116 */
117static int __init vio_bus_init_iseries(void)
118{
119 int err;
120
121 err = vio_bus_init(&vio_bus_ops_iseries);
122 if (err == 0) {
123 iommu_vio_init();
124 vio_bus_device.iommu_table = &vio_iommu_table;
125 iSeries_vio_dev = &vio_bus_device.dev;
126 probe_bus_iseries();
127 }
128 return err;
129}
130
131__initcall(vio_bus_init_iseries);
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index 85d6c93659cc..9a4efc0c3b29 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -437,9 +437,6 @@ void __init maple_pci_init(void)
437 437
438 /* Tell pci.c to not change any resource allocations. */ 438 /* Tell pci.c to not change any resource allocations. */
439 pci_probe_only = 1; 439 pci_probe_only = 1;
440
441 /* Allow all IO */
442 io_page_mask = -1;
443} 440}
444 441
445int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel) 442int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel)
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 24c0aef4ea39..a0505ea48a86 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -189,7 +189,7 @@ void __init maple_setup_arch(void)
189 conswitchp = &dummy_con; 189 conswitchp = &dummy_con;
190#endif 190#endif
191 191
192 printk(KERN_INFO "Using native/NAP idle loop\n"); 192 printk(KERN_DEBUG "Using native/NAP idle loop\n");
193} 193}
194 194
195/* 195/*
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index a5063cd675c5..85e00cb0006e 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -2510,7 +2510,7 @@ found:
2510 if (get_property(np, "flush-on-lock", NULL)) 2510 if (get_property(np, "flush-on-lock", NULL))
2511 break; 2511 break;
2512 powersave_nap = 1; 2512 powersave_nap = 1;
2513 printk(KERN_INFO "Processor NAP mode on idle enabled.\n"); 2513 printk(KERN_DEBUG "Processor NAP mode on idle enabled.\n");
2514 break; 2514 break;
2515 } 2515 }
2516 2516
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index ea179afea632..80035853467b 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -1068,9 +1068,6 @@ void __init pmac_pci_init(void)
1068 /* Tell pci.c to not use the common resource allocation mechanism */ 1068 /* Tell pci.c to not use the common resource allocation mechanism */
1069 pci_probe_only = 1; 1069 pci_probe_only = 1;
1070 1070
1071 /* Allow all IO */
1072 io_page_mask = -1;
1073
1074#else /* CONFIG_PPC64 */ 1071#else /* CONFIG_PPC64 */
1075 init_p2pbridge(); 1072 init_p2pbridge();
1076 fixup_nec_usb2(); 1073 fixup_nec_usb2();
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 930898635c9f..b46ce3b9bb3c 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -2,7 +2,6 @@ obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \
2 setup.o iommu.o ras.o rtasd.o pci_dlpar.o \ 2 setup.o iommu.o ras.o rtasd.o pci_dlpar.o \
3 firmware.o 3 firmware.o
4obj-$(CONFIG_SMP) += smp.o 4obj-$(CONFIG_SMP) += smp.o
5obj-$(CONFIG_IBMVIO) += vio.o
6obj-$(CONFIG_XICS) += xics.o 5obj-$(CONFIG_XICS) += xics.o
7obj-$(CONFIG_SCANLOG) += scanlog.o 6obj-$(CONFIG_SCANLOG) += scanlog.o
8obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o 7obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index 1fba695e32e8..4d45347afabc 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -23,9 +23,8 @@
23 * 23 *
24 */ 24 */
25#include <linux/delay.h> 25#include <linux/delay.h>
26#include <linux/irq.h>
27#include <linux/interrupt.h> 26#include <linux/interrupt.h>
28#include <linux/notifier.h> 27#include <linux/irq.h>
29#include <linux/pci.h> 28#include <linux/pci.h>
30#include <asm/eeh.h> 29#include <asm/eeh.h>
31#include <asm/eeh_event.h> 30#include <asm/eeh_event.h>
@@ -202,7 +201,11 @@ static void eeh_report_failure(struct pci_dev *dev, void *userdata)
202 201
203static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) 202static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
204{ 203{
205 int rc; 204 int cnt, rc;
205
206 /* pcibios will clear the counter; save the value */
207 cnt = pe_dn->eeh_freeze_count;
208
206 if (bus) 209 if (bus)
207 pcibios_remove_pci_devices(bus); 210 pcibios_remove_pci_devices(bus);
208 211
@@ -241,6 +244,7 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
241 ssleep (5); 244 ssleep (5);
242 pcibios_add_pci_devices(bus); 245 pcibios_add_pci_devices(bus);
243 } 246 }
247 pe_dn->eeh_freeze_count = cnt;
244 248
245 return 0; 249 return 0;
246} 250}
@@ -250,7 +254,7 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
250 */ 254 */
251#define MAX_WAIT_FOR_RECOVERY 15 255#define MAX_WAIT_FOR_RECOVERY 15
252 256
253void handle_eeh_events (struct eeh_event *event) 257struct pci_dn * handle_eeh_events (struct eeh_event *event)
254{ 258{
255 struct device_node *frozen_dn; 259 struct device_node *frozen_dn;
256 struct pci_dn *frozen_pdn; 260 struct pci_dn *frozen_pdn;
@@ -265,7 +269,7 @@ void handle_eeh_events (struct eeh_event *event)
265 if (!frozen_dn) { 269 if (!frozen_dn) {
266 printk(KERN_ERR "EEH: Error: Cannot find partition endpoint for %s\n", 270 printk(KERN_ERR "EEH: Error: Cannot find partition endpoint for %s\n",
267 pci_name(event->dev)); 271 pci_name(event->dev));
268 return; 272 return NULL;
269 } 273 }
270 274
271 /* There are two different styles for coming up with the PE. 275 /* There are two different styles for coming up with the PE.
@@ -280,7 +284,7 @@ void handle_eeh_events (struct eeh_event *event)
280 if (!frozen_bus) { 284 if (!frozen_bus) {
281 printk(KERN_ERR "EEH: Cannot find PCI bus for %s\n", 285 printk(KERN_ERR "EEH: Cannot find PCI bus for %s\n",
282 frozen_dn->full_name); 286 frozen_dn->full_name);
283 return; 287 return NULL;
284 } 288 }
285 289
286#if 0 290#if 0
@@ -355,7 +359,7 @@ void handle_eeh_events (struct eeh_event *event)
355 /* Tell all device drivers that they can resume operations */ 359 /* Tell all device drivers that they can resume operations */
356 pci_walk_bus(frozen_bus, eeh_report_resume, NULL); 360 pci_walk_bus(frozen_bus, eeh_report_resume, NULL);
357 361
358 return; 362 return frozen_pdn;
359 363
360excess_failures: 364excess_failures:
361 /* 365 /*
@@ -384,6 +388,8 @@ perm_error:
384 388
385 /* Shut down the device drivers for good. */ 389 /* Shut down the device drivers for good. */
386 pcibios_remove_pci_devices(frozen_bus); 390 pcibios_remove_pci_devices(frozen_bus);
391
392 return NULL;
387} 393}
388 394
389/* ---------- end of file ---------- */ 395/* ---------- end of file ---------- */
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c
index 40020c65c89e..8f2d12935b99 100644
--- a/arch/powerpc/platforms/pseries/eeh_event.c
+++ b/arch/powerpc/platforms/pseries/eeh_event.c
@@ -18,6 +18,7 @@
18 * Copyright (c) 2005 Linas Vepstas <linas@linas.org> 18 * Copyright (c) 2005 Linas Vepstas <linas@linas.org>
19 */ 19 */
20 20
21#include <linux/delay.h>
21#include <linux/list.h> 22#include <linux/list.h>
22#include <linux/mutex.h> 23#include <linux/mutex.h>
23#include <linux/pci.h> 24#include <linux/pci.h>
@@ -56,38 +57,43 @@ static int eeh_event_handler(void * dummy)
56{ 57{
57 unsigned long flags; 58 unsigned long flags;
58 struct eeh_event *event; 59 struct eeh_event *event;
60 struct pci_dn *pdn;
59 61
60 daemonize ("eehd"); 62 daemonize ("eehd");
63 set_current_state(TASK_INTERRUPTIBLE);
61 64
62 while (1) { 65 spin_lock_irqsave(&eeh_eventlist_lock, flags);
63 set_current_state(TASK_INTERRUPTIBLE); 66 event = NULL;
64 67
65 spin_lock_irqsave(&eeh_eventlist_lock, flags); 68 /* Unqueue the event, get ready to process. */
66 event = NULL; 69 if (!list_empty(&eeh_eventlist)) {
70 event = list_entry(eeh_eventlist.next, struct eeh_event, list);
71 list_del(&event->list);
72 }
73 spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
67 74
68 /* Unqueue the event, get ready to process. */ 75 if (event == NULL)
69 if (!list_empty(&eeh_eventlist)) { 76 return 0;
70 event = list_entry(eeh_eventlist.next, struct eeh_event, list);
71 list_del(&event->list);
72 }
73 spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
74 77
75 if (event == NULL) 78 /* Serialize processing of EEH events */
76 break; 79 mutex_lock(&eeh_event_mutex);
80 eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
77 81
78 /* Serialize processing of EEH events */ 82 printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
79 mutex_lock(&eeh_event_mutex); 83 pci_name(event->dev));
80 eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
81 84
82 printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n", 85 pdn = handle_eeh_events(event);
83 pci_name(event->dev));
84 86
85 handle_eeh_events(event); 87 eeh_clear_slot(event->dn, EEH_MODE_RECOVERING);
88 pci_dev_put(event->dev);
89 kfree(event);
90 mutex_unlock(&eeh_event_mutex);
86 91
87 eeh_clear_slot(event->dn, EEH_MODE_RECOVERING); 92 /* If there are no new errors after an hour, clear the counter. */
88 pci_dev_put(event->dev); 93 if (pdn && pdn->eeh_freeze_count>0) {
89 kfree(event); 94 msleep_interruptible (3600*1000);
90 mutex_unlock(&eeh_event_mutex); 95 if (pdn->eeh_freeze_count>0)
96 pdn->eeh_freeze_count--;
91 } 97 }
92 98
93 return 0; 99 return 0;
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 2643078433f0..44a507e6fb34 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -1,23 +1,24 @@
1/* 1/*
2 * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation 2 * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
3 * 3 *
4 * Rewrite, cleanup: 4 * Rewrite, cleanup:
5 * 5 *
6 * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation 6 * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
7 * Copyright (C) 2006 Olof Johansson <olof@lixom.net>
7 * 8 *
8 * Dynamic DMA mapping support, pSeries-specific parts, both SMP and LPAR. 9 * Dynamic DMA mapping support, pSeries-specific parts, both SMP and LPAR.
9 * 10 *
10 * 11 *
11 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by 13 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or 14 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version. 15 * (at your option) any later version.
15 * 16 *
16 * This program is distributed in the hope that it will be useful, 17 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details. 20 * GNU General Public License for more details.
20 * 21 *
21 * You should have received a copy of the GNU General Public License 22 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software 23 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -49,52 +50,46 @@
49 50
50#define DBG(fmt...) 51#define DBG(fmt...)
51 52
52static void tce_build_pSeries(struct iommu_table *tbl, long index, 53static void tce_build_pSeries(struct iommu_table *tbl, long index,
53 long npages, unsigned long uaddr, 54 long npages, unsigned long uaddr,
54 enum dma_data_direction direction) 55 enum dma_data_direction direction)
55{ 56{
56 union tce_entry t; 57 u64 proto_tce;
57 union tce_entry *tp; 58 u64 *tcep;
59 u64 rpn;
58 60
59 index <<= TCE_PAGE_FACTOR; 61 index <<= TCE_PAGE_FACTOR;
60 npages <<= TCE_PAGE_FACTOR; 62 npages <<= TCE_PAGE_FACTOR;
61 63
62 t.te_word = 0; 64 proto_tce = TCE_PCI_READ; // Read allowed
63 t.te_rdwr = 1; // Read allowed
64 65
65 if (direction != DMA_TO_DEVICE) 66 if (direction != DMA_TO_DEVICE)
66 t.te_pciwr = 1; 67 proto_tce |= TCE_PCI_WRITE;
67 68
68 tp = ((union tce_entry *)tbl->it_base) + index; 69 tcep = ((u64 *)tbl->it_base) + index;
69 70
70 while (npages--) { 71 while (npages--) {
71 /* can't move this out since we might cross LMB boundary */ 72 /* can't move this out since we might cross LMB boundary */
72 t.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; 73 rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
73 74 *tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
74 tp->te_word = t.te_word;
75 75
76 uaddr += TCE_PAGE_SIZE; 76 uaddr += TCE_PAGE_SIZE;
77 tp++; 77 tcep++;
78 } 78 }
79} 79}
80 80
81 81
82static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages) 82static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages)
83{ 83{
84 union tce_entry t; 84 u64 *tcep;
85 union tce_entry *tp;
86 85
87 npages <<= TCE_PAGE_FACTOR; 86 npages <<= TCE_PAGE_FACTOR;
88 index <<= TCE_PAGE_FACTOR; 87 index <<= TCE_PAGE_FACTOR;
89 88
90 t.te_word = 0; 89 tcep = ((u64 *)tbl->it_base) + index;
91 tp = ((union tce_entry *)tbl->it_base) + index; 90
92 91 while (npages--)
93 while (npages--) { 92 *(tcep++) = 0;
94 tp->te_word = t.te_word;
95
96 tp++;
97 }
98} 93}
99 94
100 95
@@ -103,43 +98,44 @@ static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
103 enum dma_data_direction direction) 98 enum dma_data_direction direction)
104{ 99{
105 u64 rc; 100 u64 rc;
106 union tce_entry tce; 101 u64 proto_tce, tce;
102 u64 rpn;
107 103
108 tcenum <<= TCE_PAGE_FACTOR; 104 tcenum <<= TCE_PAGE_FACTOR;
109 npages <<= TCE_PAGE_FACTOR; 105 npages <<= TCE_PAGE_FACTOR;
110 106
111 tce.te_word = 0; 107 rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
112 tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; 108 proto_tce = TCE_PCI_READ;
113 tce.te_rdwr = 1;
114 if (direction != DMA_TO_DEVICE) 109 if (direction != DMA_TO_DEVICE)
115 tce.te_pciwr = 1; 110 proto_tce |= TCE_PCI_WRITE;
116 111
117 while (npages--) { 112 while (npages--) {
118 rc = plpar_tce_put((u64)tbl->it_index, 113 tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
119 (u64)tcenum << 12, 114 rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce);
120 tce.te_word ); 115
121
122 if (rc && printk_ratelimit()) { 116 if (rc && printk_ratelimit()) {
123 printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); 117 printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
124 printk("\tindex = 0x%lx\n", (u64)tbl->it_index); 118 printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
125 printk("\ttcenum = 0x%lx\n", (u64)tcenum); 119 printk("\ttcenum = 0x%lx\n", (u64)tcenum);
126 printk("\ttce val = 0x%lx\n", tce.te_word ); 120 printk("\ttce val = 0x%lx\n", tce );
127 show_stack(current, (unsigned long *)__get_SP()); 121 show_stack(current, (unsigned long *)__get_SP());
128 } 122 }
129 123
130 tcenum++; 124 tcenum++;
131 tce.te_rpn++; 125 rpn++;
132 } 126 }
133} 127}
134 128
135static DEFINE_PER_CPU(void *, tce_page) = NULL; 129static DEFINE_PER_CPU(u64 *, tce_page) = NULL;
136 130
137static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, 131static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
138 long npages, unsigned long uaddr, 132 long npages, unsigned long uaddr,
139 enum dma_data_direction direction) 133 enum dma_data_direction direction)
140{ 134{
141 u64 rc; 135 u64 rc;
142 union tce_entry tce, *tcep; 136 u64 proto_tce;
137 u64 *tcep;
138 u64 rpn;
143 long l, limit; 139 long l, limit;
144 140
145 if (TCE_PAGE_FACTOR == 0 && npages == 1) 141 if (TCE_PAGE_FACTOR == 0 && npages == 1)
@@ -152,7 +148,7 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
152 * from iommu_alloc{,_sg}() 148 * from iommu_alloc{,_sg}()
153 */ 149 */
154 if (!tcep) { 150 if (!tcep) {
155 tcep = (void *)__get_free_page(GFP_ATOMIC); 151 tcep = (u64 *)__get_free_page(GFP_ATOMIC);
156 /* If allocation fails, fall back to the loop implementation */ 152 /* If allocation fails, fall back to the loop implementation */
157 if (!tcep) 153 if (!tcep)
158 return tce_build_pSeriesLP(tbl, tcenum, npages, 154 return tce_build_pSeriesLP(tbl, tcenum, npages,
@@ -163,11 +159,10 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
163 tcenum <<= TCE_PAGE_FACTOR; 159 tcenum <<= TCE_PAGE_FACTOR;
164 npages <<= TCE_PAGE_FACTOR; 160 npages <<= TCE_PAGE_FACTOR;
165 161
166 tce.te_word = 0; 162 rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
167 tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; 163 proto_tce = TCE_PCI_READ;
168 tce.te_rdwr = 1;
169 if (direction != DMA_TO_DEVICE) 164 if (direction != DMA_TO_DEVICE)
170 tce.te_pciwr = 1; 165 proto_tce |= TCE_PCI_WRITE;
171 166
172 /* We can map max one pageful of TCEs at a time */ 167 /* We can map max one pageful of TCEs at a time */
173 do { 168 do {
@@ -175,11 +170,11 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
175 * Set up the page with TCE data, looping through and setting 170 * Set up the page with TCE data, looping through and setting
176 * the values. 171 * the values.
177 */ 172 */
178 limit = min_t(long, npages, 4096/sizeof(union tce_entry)); 173 limit = min_t(long, npages, 4096/TCE_ENTRY_SIZE);
179 174
180 for (l = 0; l < limit; l++) { 175 for (l = 0; l < limit; l++) {
181 tcep[l] = tce; 176 tcep[l] = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
182 tce.te_rpn++; 177 rpn++;
183 } 178 }
184 179
185 rc = plpar_tce_put_indirect((u64)tbl->it_index, 180 rc = plpar_tce_put_indirect((u64)tbl->it_index,
@@ -195,7 +190,7 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
195 printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); 190 printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
196 printk("\tindex = 0x%lx\n", (u64)tbl->it_index); 191 printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
197 printk("\tnpages = 0x%lx\n", (u64)npages); 192 printk("\tnpages = 0x%lx\n", (u64)npages);
198 printk("\ttce[0] val = 0x%lx\n", tcep[0].te_word); 193 printk("\ttce[0] val = 0x%lx\n", tcep[0]);
199 show_stack(current, (unsigned long *)__get_SP()); 194 show_stack(current, (unsigned long *)__get_SP());
200 } 195 }
201} 196}
@@ -203,23 +198,17 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
203static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) 198static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
204{ 199{
205 u64 rc; 200 u64 rc;
206 union tce_entry tce;
207 201
208 tcenum <<= TCE_PAGE_FACTOR; 202 tcenum <<= TCE_PAGE_FACTOR;
209 npages <<= TCE_PAGE_FACTOR; 203 npages <<= TCE_PAGE_FACTOR;
210 204
211 tce.te_word = 0;
212
213 while (npages--) { 205 while (npages--) {
214 rc = plpar_tce_put((u64)tbl->it_index, 206 rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, 0);
215 (u64)tcenum << 12,
216 tce.te_word);
217 207
218 if (rc && printk_ratelimit()) { 208 if (rc && printk_ratelimit()) {
219 printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); 209 printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
220 printk("\tindex = 0x%lx\n", (u64)tbl->it_index); 210 printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
221 printk("\ttcenum = 0x%lx\n", (u64)tcenum); 211 printk("\ttcenum = 0x%lx\n", (u64)tcenum);
222 printk("\ttce val = 0x%lx\n", tce.te_word );
223 show_stack(current, (unsigned long *)__get_SP()); 212 show_stack(current, (unsigned long *)__get_SP());
224 } 213 }
225 214
@@ -231,31 +220,24 @@ static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages
231static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) 220static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
232{ 221{
233 u64 rc; 222 u64 rc;
234 union tce_entry tce;
235 223
236 tcenum <<= TCE_PAGE_FACTOR; 224 tcenum <<= TCE_PAGE_FACTOR;
237 npages <<= TCE_PAGE_FACTOR; 225 npages <<= TCE_PAGE_FACTOR;
238 226
239 tce.te_word = 0; 227 rc = plpar_tce_stuff((u64)tbl->it_index, (u64)tcenum << 12, 0, npages);
240
241 rc = plpar_tce_stuff((u64)tbl->it_index,
242 (u64)tcenum << 12,
243 tce.te_word,
244 npages);
245 228
246 if (rc && printk_ratelimit()) { 229 if (rc && printk_ratelimit()) {
247 printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n"); 230 printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n");
248 printk("\trc = %ld\n", rc); 231 printk("\trc = %ld\n", rc);
249 printk("\tindex = 0x%lx\n", (u64)tbl->it_index); 232 printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
250 printk("\tnpages = 0x%lx\n", (u64)npages); 233 printk("\tnpages = 0x%lx\n", (u64)npages);
251 printk("\ttce val = 0x%lx\n", tce.te_word );
252 show_stack(current, (unsigned long *)__get_SP()); 234 show_stack(current, (unsigned long *)__get_SP());
253 } 235 }
254} 236}
255 237
256static void iommu_table_setparms(struct pci_controller *phb, 238static void iommu_table_setparms(struct pci_controller *phb,
257 struct device_node *dn, 239 struct device_node *dn,
258 struct iommu_table *tbl) 240 struct iommu_table *tbl)
259{ 241{
260 struct device_node *node; 242 struct device_node *node;
261 unsigned long *basep; 243 unsigned long *basep;
@@ -275,16 +257,16 @@ static void iommu_table_setparms(struct pci_controller *phb,
275 memset((void *)tbl->it_base, 0, *sizep); 257 memset((void *)tbl->it_base, 0, *sizep);
276 258
277 tbl->it_busno = phb->bus->number; 259 tbl->it_busno = phb->bus->number;
278 260
279 /* Units of tce entries */ 261 /* Units of tce entries */
280 tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT; 262 tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT;
281 263
282 /* Test if we are going over 2GB of DMA space */ 264 /* Test if we are going over 2GB of DMA space */
283 if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) { 265 if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) {
284 udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); 266 udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
285 panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); 267 panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
286 } 268 }
287 269
288 phb->dma_window_base_cur += phb->dma_window_size; 270 phb->dma_window_base_cur += phb->dma_window_size;
289 271
290 /* Set the tce table size - measured in entries */ 272 /* Set the tce table size - measured in entries */
@@ -299,30 +281,22 @@ static void iommu_table_setparms(struct pci_controller *phb,
299 * iommu_table_setparms_lpar 281 * iommu_table_setparms_lpar
300 * 282 *
301 * Function: On pSeries LPAR systems, return TCE table info, given a pci bus. 283 * Function: On pSeries LPAR systems, return TCE table info, given a pci bus.
302 *
303 * ToDo: properly interpret the ibm,dma-window property. The definition is:
304 * logical-bus-number (1 word)
305 * phys-address (#address-cells words)
306 * size (#cell-size words)
307 *
308 * Currently we hard code these sizes (more or less).
309 */ 284 */
310static void iommu_table_setparms_lpar(struct pci_controller *phb, 285static void iommu_table_setparms_lpar(struct pci_controller *phb,
311 struct device_node *dn, 286 struct device_node *dn,
312 struct iommu_table *tbl, 287 struct iommu_table *tbl,
313 unsigned int *dma_window) 288 unsigned char *dma_window)
314{ 289{
290 unsigned long offset, size;
291
315 tbl->it_busno = PCI_DN(dn)->bussubno; 292 tbl->it_busno = PCI_DN(dn)->bussubno;
293 of_parse_dma_window(dn, dma_window, &tbl->it_index, &offset, &size);
316 294
317 /* TODO: Parse field size properties properly. */
318 tbl->it_size = (((unsigned long)dma_window[4] << 32) |
319 (unsigned long)dma_window[5]) >> PAGE_SHIFT;
320 tbl->it_offset = (((unsigned long)dma_window[2] << 32) |
321 (unsigned long)dma_window[3]) >> PAGE_SHIFT;
322 tbl->it_base = 0; 295 tbl->it_base = 0;
323 tbl->it_index = dma_window[0];
324 tbl->it_blocksize = 16; 296 tbl->it_blocksize = 16;
325 tbl->it_type = TCE_PCI; 297 tbl->it_type = TCE_PCI;
298 tbl->it_offset = offset >> PAGE_SHIFT;
299 tbl->it_size = size >> PAGE_SHIFT;
326} 300}
327 301
328static void iommu_bus_setup_pSeries(struct pci_bus *bus) 302static void iommu_bus_setup_pSeries(struct pci_bus *bus)
@@ -414,7 +388,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
414 struct iommu_table *tbl; 388 struct iommu_table *tbl;
415 struct device_node *dn, *pdn; 389 struct device_node *dn, *pdn;
416 struct pci_dn *ppci; 390 struct pci_dn *ppci;
417 unsigned int *dma_window = NULL; 391 unsigned char *dma_window = NULL;
418 392
419 DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self); 393 DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self);
420 394
@@ -422,7 +396,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
422 396
423 /* Find nearest ibm,dma-window, walking up the device tree */ 397 /* Find nearest ibm,dma-window, walking up the device tree */
424 for (pdn = dn; pdn != NULL; pdn = pdn->parent) { 398 for (pdn = dn; pdn != NULL; pdn = pdn->parent) {
425 dma_window = (unsigned int *)get_property(pdn, "ibm,dma-window", NULL); 399 dma_window = get_property(pdn, "ibm,dma-window", NULL);
426 if (dma_window != NULL) 400 if (dma_window != NULL)
427 break; 401 break;
428 } 402 }
@@ -442,7 +416,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
442 416
443 tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), 417 tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
444 GFP_KERNEL); 418 GFP_KERNEL);
445 419
446 iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); 420 iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);
447 421
448 ppci->iommu_table = iommu_init_table(tbl); 422 ppci->iommu_table = iommu_init_table(tbl);
@@ -516,7 +490,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
516{ 490{
517 struct device_node *pdn, *dn; 491 struct device_node *pdn, *dn;
518 struct iommu_table *tbl; 492 struct iommu_table *tbl;
519 int *dma_window = NULL; 493 unsigned char *dma_window = NULL;
520 struct pci_dn *pci; 494 struct pci_dn *pci;
521 495
522 DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, pci_name(dev)); 496 DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, pci_name(dev));
@@ -531,8 +505,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
531 505
532 for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table; 506 for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;
533 pdn = pdn->parent) { 507 pdn = pdn->parent) {
534 dma_window = (unsigned int *) 508 dma_window = get_property(pdn, "ibm,dma-window", NULL);
535 get_property(pdn, "ibm,dma-window", NULL);
536 if (dma_window) 509 if (dma_window)
537 break; 510 break;
538 } 511 }
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c
index e0000ce769e5..2e4e04042d85 100644
--- a/arch/powerpc/platforms/pseries/rtasd.c
+++ b/arch/powerpc/platforms/pseries/rtasd.c
@@ -348,7 +348,7 @@ static int enable_surveillance(int timeout)
348 return 0; 348 return 0;
349 349
350 if (error == -EINVAL) { 350 if (error == -EINVAL) {
351 printk(KERN_INFO "rtasd: surveillance not supported\n"); 351 printk(KERN_DEBUG "rtasd: surveillance not supported\n");
352 return 0; 352 return 0;
353 } 353 }
354 354
@@ -440,7 +440,7 @@ static int rtasd(void *unused)
440 goto error; 440 goto error;
441 } 441 }
442 442
443 printk(KERN_INFO "RTAS daemon started\n"); 443 printk(KERN_DEBUG "RTAS daemon started\n");
444 444
445 DEBUG("will sleep for %d milliseconds\n", (30000/rtas_event_scan_rate)); 445 DEBUG("will sleep for %d milliseconds\n", (30000/rtas_event_scan_rate));
446 446
@@ -487,7 +487,7 @@ static int __init rtas_init(void)
487 487
488 /* No RTAS */ 488 /* No RTAS */
489 if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) { 489 if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) {
490 printk(KERN_INFO "rtasd: no event-scan on system\n"); 490 printk(KERN_DEBUG "rtasd: no event-scan on system\n");
491 return -ENODEV; 491 return -ENODEV;
492 } 492 }
493 493
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 5f79f01c44f2..ee89d19c436a 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -235,14 +235,14 @@ static void __init pSeries_setup_arch(void)
235 if (firmware_has_feature(FW_FEATURE_SPLPAR)) { 235 if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
236 vpa_init(boot_cpuid); 236 vpa_init(boot_cpuid);
237 if (get_lppaca()->shared_proc) { 237 if (get_lppaca()->shared_proc) {
238 printk(KERN_INFO "Using shared processor idle loop\n"); 238 printk(KERN_DEBUG "Using shared processor idle loop\n");
239 ppc_md.power_save = pseries_shared_idle_sleep; 239 ppc_md.power_save = pseries_shared_idle_sleep;
240 } else { 240 } else {
241 printk(KERN_INFO "Using dedicated idle loop\n"); 241 printk(KERN_DEBUG "Using dedicated idle loop\n");
242 ppc_md.power_save = pseries_dedicated_idle_sleep; 242 ppc_md.power_save = pseries_dedicated_idle_sleep;
243 } 243 }
244 } else { 244 } else {
245 printk(KERN_INFO "Using default idle loop\n"); 245 printk(KERN_DEBUG "Using default idle loop\n");
246 } 246 }
247 247
248 if (firmware_has_feature(FW_FEATURE_LPAR)) 248 if (firmware_has_feature(FW_FEATURE_LPAR))
diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c
deleted file mode 100644
index 8e53e04ada8b..000000000000
--- a/arch/powerpc/platforms/pseries/vio.c
+++ /dev/null
@@ -1,274 +0,0 @@
1/*
2 * IBM PowerPC pSeries Virtual I/O Infrastructure Support.
3 *
4 * Copyright (c) 2003-2005 IBM Corp.
5 * Dave Engebretsen engebret@us.ibm.com
6 * Santiago Leon santil@us.ibm.com
7 * Hollis Blanchard <hollisb@us.ibm.com>
8 * Stephen Rothwell
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#include <linux/init.h>
17#include <linux/module.h>
18#include <linux/mm.h>
19#include <linux/kobject.h>
20#include <asm/iommu.h>
21#include <asm/dma.h>
22#include <asm/prom.h>
23#include <asm/vio.h>
24#include <asm/hvcall.h>
25#include <asm/tce.h>
26
27extern struct subsystem devices_subsys; /* needed for vio_find_name() */
28
29static void probe_bus_pseries(void)
30{
31 struct device_node *node_vroot, *of_node;
32
33 node_vroot = find_devices("vdevice");
34 if ((node_vroot == NULL) || (node_vroot->child == NULL))
35 /* this machine doesn't do virtual IO, and that's ok */
36 return;
37
38 /*
39 * Create struct vio_devices for each virtual device in the device tree.
40 * Drivers will associate with them later.
41 */
42 for (of_node = node_vroot->child; of_node != NULL;
43 of_node = of_node->sibling) {
44 printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node);
45 vio_register_device_node(of_node);
46 }
47}
48
49/**
50 * vio_match_device_pseries: - Tell if a pSeries VIO device matches a
51 * vio_device_id
52 */
53static int vio_match_device_pseries(const struct vio_device_id *id,
54 const struct vio_dev *dev)
55{
56 return (strncmp(dev->type, id->type, strlen(id->type)) == 0) &&
57 device_is_compatible(dev->dev.platform_data, id->compat);
58}
59
60static void vio_release_device_pseries(struct device *dev)
61{
62 /* XXX free TCE table */
63 of_node_put(dev->platform_data);
64}
65
66static ssize_t viodev_show_devspec(struct device *dev,
67 struct device_attribute *attr, char *buf)
68{
69 struct device_node *of_node = dev->platform_data;
70
71 return sprintf(buf, "%s\n", of_node->full_name);
72}
73DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL);
74
75static void vio_unregister_device_pseries(struct vio_dev *viodev)
76{
77 device_remove_file(&viodev->dev, &dev_attr_devspec);
78}
79
80static struct vio_bus_ops vio_bus_ops_pseries = {
81 .match = vio_match_device_pseries,
82 .unregister_device = vio_unregister_device_pseries,
83 .release_device = vio_release_device_pseries,
84};
85
86/**
87 * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus
88 */
89static int __init vio_bus_init_pseries(void)
90{
91 int err;
92
93 err = vio_bus_init(&vio_bus_ops_pseries);
94 if (err == 0)
95 probe_bus_pseries();
96 return err;
97}
98
99__initcall(vio_bus_init_pseries);
100
101/**
102 * vio_build_iommu_table: - gets the dma information from OF and
103 * builds the TCE tree.
104 * @dev: the virtual device.
105 *
106 * Returns a pointer to the built tce tree, or NULL if it can't
107 * find property.
108*/
109static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
110{
111 unsigned int *dma_window;
112 struct iommu_table *newTceTable;
113 unsigned long offset;
114 int dma_window_property_size;
115
116 dma_window = (unsigned int *) get_property(dev->dev.platform_data, "ibm,my-dma-window", &dma_window_property_size);
117 if(!dma_window) {
118 return NULL;
119 }
120
121 newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
122
123 /* There should be some code to extract the phys-encoded offset
124 using prom_n_addr_cells(). However, according to a comment
125 on earlier versions, it's always zero, so we don't bother */
126 offset = dma_window[1] >> PAGE_SHIFT;
127
128 /* TCE table size - measured in tce entries */
129 newTceTable->it_size = dma_window[4] >> PAGE_SHIFT;
130 /* offset for VIO should always be 0 */
131 newTceTable->it_offset = offset;
132 newTceTable->it_busno = 0;
133 newTceTable->it_index = (unsigned long)dma_window[0];
134 newTceTable->it_type = TCE_VB;
135
136 return iommu_init_table(newTceTable);
137}
138
139/**
140 * vio_register_device_node: - Register a new vio device.
141 * @of_node: The OF node for this device.
142 *
143 * Creates and initializes a vio_dev structure from the data in
144 * of_node (dev.platform_data) and adds it to the list of virtual devices.
145 * Returns a pointer to the created vio_dev or NULL if node has
146 * NULL device_type or compatible fields.
147 */
148struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
149{
150 struct vio_dev *viodev;
151 unsigned int *unit_address;
152 unsigned int *irq_p;
153
154 /* we need the 'device_type' property, in order to match with drivers */
155 if ((NULL == of_node->type)) {
156 printk(KERN_WARNING
157 "%s: node %s missing 'device_type'\n", __FUNCTION__,
158 of_node->name ? of_node->name : "<unknown>");
159 return NULL;
160 }
161
162 unit_address = (unsigned int *)get_property(of_node, "reg", NULL);
163 if (!unit_address) {
164 printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__,
165 of_node->name ? of_node->name : "<unknown>");
166 return NULL;
167 }
168
169 /* allocate a vio_dev for this node */
170 viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
171 if (!viodev) {
172 return NULL;
173 }
174 memset(viodev, 0, sizeof(struct vio_dev));
175
176 viodev->dev.platform_data = of_node_get(of_node);
177
178 viodev->irq = NO_IRQ;
179 irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL);
180 if (irq_p) {
181 int virq = virt_irq_create_mapping(*irq_p);
182 if (virq == NO_IRQ) {
183 printk(KERN_ERR "Unable to allocate interrupt "
184 "number for %s\n", of_node->full_name);
185 } else
186 viodev->irq = irq_offset_up(virq);
187 }
188
189 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
190 viodev->name = of_node->name;
191 viodev->type = of_node->type;
192 viodev->unit_address = *unit_address;
193 viodev->iommu_table = vio_build_iommu_table(viodev);
194
195 /* register with generic device framework */
196 if (vio_register_device(viodev) == NULL) {
197 /* XXX free TCE table */
198 kfree(viodev);
199 return NULL;
200 }
201 device_create_file(&viodev->dev, &dev_attr_devspec);
202
203 return viodev;
204}
205EXPORT_SYMBOL(vio_register_device_node);
206
207/**
208 * vio_get_attribute: - get attribute for virtual device
209 * @vdev: The vio device to get property.
210 * @which: The property/attribute to be extracted.
211 * @length: Pointer to length of returned data size (unused if NULL).
212 *
213 * Calls prom.c's get_property() to return the value of the
214 * attribute specified by the preprocessor constant @which
215*/
216const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length)
217{
218 return get_property(vdev->dev.platform_data, (char*)which, length);
219}
220EXPORT_SYMBOL(vio_get_attribute);
221
222/* vio_find_name() - internal because only vio.c knows how we formatted the
223 * kobject name
224 * XXX once vio_bus_type.devices is actually used as a kset in
225 * drivers/base/bus.c, this function should be removed in favor of
226 * "device_find(kobj_name, &vio_bus_type)"
227 */
228static struct vio_dev *vio_find_name(const char *kobj_name)
229{
230 struct kobject *found;
231
232 found = kset_find_obj(&devices_subsys.kset, kobj_name);
233 if (!found)
234 return NULL;
235
236 return to_vio_dev(container_of(found, struct device, kobj));
237}
238
239/**
240 * vio_find_node - find an already-registered vio_dev
241 * @vnode: device_node of the virtual device we're looking for
242 */
243struct vio_dev *vio_find_node(struct device_node *vnode)
244{
245 uint32_t *unit_address;
246 char kobj_name[BUS_ID_SIZE];
247
248 /* construct the kobject name from the device node */
249 unit_address = (uint32_t *)get_property(vnode, "reg", NULL);
250 if (!unit_address)
251 return NULL;
252 snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);
253
254 return vio_find_name(kobj_name);
255}
256EXPORT_SYMBOL(vio_find_node);
257
258int vio_enable_interrupts(struct vio_dev *dev)
259{
260 int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
261 if (rc != H_SUCCESS)
262 printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
263 return rc;
264}
265EXPORT_SYMBOL(vio_enable_interrupts);
266
267int vio_disable_interrupts(struct vio_dev *dev)
268{
269 int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);
270 if (rc != H_SUCCESS)
271 printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
272 return rc;
273}
274EXPORT_SYMBOL(vio_disable_interrupts);
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 2d60ea30fed6..b14f9b5c114e 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -522,7 +522,7 @@ nextnode:
522 522
523 np = of_find_node_by_type(NULL, "interrupt-controller"); 523 np = of_find_node_by_type(NULL, "interrupt-controller");
524 if (!np) { 524 if (!np) {
525 printk(KERN_WARNING "xics: no ISA interrupt controller\n"); 525 printk(KERN_DEBUG "xics: no ISA interrupt controller\n");
526 xics_irq_8259_cascade_real = -1; 526 xics_irq_8259_cascade_real = -1;
527 xics_irq_8259_cascade = -1; 527 xics_irq_8259_cascade = -1;
528 } else { 528 } else {
@@ -641,23 +641,26 @@ void xics_teardown_cpu(int secondary)
641 ops->cppr_info(cpu, 0x00); 641 ops->cppr_info(cpu, 0x00);
642 iosync(); 642 iosync();
643 643
644 /* Clear IPI */
645 ops->qirr_info(cpu, 0xff);
646
647 /*
648 * we need to EOI the IPI if we got here from kexec down IPI
649 *
650 * probably need to check all the other interrupts too
651 * should we be flagging idle loop instead?
652 * or creating some task to be scheduled?
653 */
654 ops->xirr_info_set(cpu, XICS_IPI);
655
644 /* 656 /*
645 * Some machines need to have at least one cpu in the GIQ, 657 * Some machines need to have at least one cpu in the GIQ,
646 * so leave the master cpu in the group. 658 * so leave the master cpu in the group.
647 */ 659 */
648 if (secondary) { 660 if (secondary)
649 /*
650 * we need to EOI the IPI if we got here from kexec down IPI
651 *
652 * probably need to check all the other interrupts too
653 * should we be flagging idle loop instead?
654 * or creating some task to be scheduled?
655 */
656 ops->xirr_info_set(cpu, XICS_IPI);
657 rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, 661 rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
658 (1UL << interrupt_server_size) - 1 - 662 (1UL << interrupt_server_size) - 1 -
659 default_distrib_server, 0); 663 default_distrib_server, 0);
660 }
661} 664}
662 665
663#ifdef CONFIG_HOTPLUG_CPU 666#ifdef CONFIG_HOTPLUG_CPU