aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/iseries
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/iseries')
-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.c46
-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
12 files changed, 748 insertions, 742 deletions
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..e3bd2015f2c9 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,15 +162,18 @@ 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);
171 if (pdn->iommu_table == NULL) 175 if (pdn->iommu_table == NULL)
172 pdn->iommu_table = iommu_init_table(tbl); 176 pdn->iommu_table = iommu_init_table(tbl, -1);
173 else 177 else
174 kfree(tbl); 178 kfree(tbl);
175} 179}
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);