aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2006-05-19 02:46:28 -0400
committerPaul Mackerras <paulus@samba.org>2006-05-24 02:08:56 -0400
commit0d177df15d12926dc2ef7c814f317f02de52ce17 (patch)
treeda10171a931af0ff709016a8ce5111a3c39e83d2 /arch
parent66b3851a6947482987b4c05aa781a33696287648 (diff)
[PATCH] powerpc: move iSeries PCI devices to the device tree
Move the probing of PCI devices to setup.c and put them all into the flattened device tree. The later probing is now done by traversing the device tree. Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-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/pci.c273
-rw-r--r--arch/powerpc/platforms/iseries/setup.c204
4 files changed, 286 insertions, 200 deletions
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index be3fbfc24e6..62bbbcf5ded 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 b9c801ba5a4..188aa808abd 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/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 91a94747eda..9d571e74909 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -49,14 +49,9 @@
49 * Forward declares of prototypes. 49 * Forward declares of prototypes.
50 */ 50 */
51static struct device_node *find_Device_Node(int bus, int devfn); 51static struct device_node *find_Device_Node(int bus, int devfn);
52static void scan_PHB_slots(struct pci_controller *Phb);
53static void scan_EADS_bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel);
54static int scan_bridge_slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo *Info);
55 52
56LIST_HEAD(iSeries_Global_Device_List); 53LIST_HEAD(iSeries_Global_Device_List);
57 54
58static int DeviceCount;
59
60static int Pci_Retry_Max = 3; /* Only retry 3 times */ 55static int Pci_Retry_Max = 3; /* Only retry 3 times */
61static int Pci_Error_Flag = 1; /* Set Retry Error on. */ 56static int Pci_Error_Flag = 1; /* Set Retry Error on. */
62 57
@@ -162,32 +157,6 @@ static void pci_Log_Error(char *Error_Text, int Bus, int SubBus,
162} 157}
163 158
164/* 159/*
165 * build_device_node(u16 Bus, int SubBus, u8 DevFn)
166 */
167static struct device_node *build_device_node(HvBusNumber Bus,
168 HvSubBusNumber SubBus, int AgentId, int Function)
169{
170 struct device_node *node;
171 struct pci_dn *pdn;
172
173 node = kzalloc(sizeof(struct device_node), GFP_KERNEL);
174 if (node == NULL)
175 return NULL;
176 pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
177 if (pdn == NULL) {
178 kfree(node);
179 return NULL;
180 }
181 node->data = pdn;
182 pdn->node = node;
183 list_add_tail(&pdn->Device_List, &iSeries_Global_Device_List);
184 pdn->busno = Bus;
185 pdn->bussubno = SubBus;
186 pdn->devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function);
187 return node;
188}
189
190/*
191 * iSeries_pcibios_init 160 * iSeries_pcibios_init
192 * 161 *
193 * Description: 162 * Description:
@@ -199,33 +168,86 @@ static struct device_node *build_device_node(HvBusNumber Bus,
199void iSeries_pcibios_init(void) 168void iSeries_pcibios_init(void)
200{ 169{
201 struct pci_controller *phb; 170 struct pci_controller *phb;
202 HvBusNumber bus; 171 struct device_node *node;
203 172 struct device_node *dn;
204 /* Check all possible buses. */ 173
205 for (bus = 0; bus < 256; bus++) { 174 for_each_node_by_type(node, "pci") {
206 int ret = HvCallXm_testBus(bus); 175 HvBusNumber bus;
207 if (ret == 0) { 176 u32 *busp;
208 printk("bus %d appears to exist\n", bus); 177
209 178 busp = (u32 *)get_property(node, "bus-range", NULL);
210 phb = pcibios_alloc_controller(NULL); 179 if (busp == NULL)
211 if (phb == NULL) 180 continue;
212 return -ENOMEM; 181 bus = *busp;
182 printk("bus %d appears to exist\n", bus);
183 phb = pcibios_alloc_controller(node);
184 if (phb == NULL)
185 continue;
186
187 phb->pci_mem_offset = phb->local_number = bus;
188 phb->first_busno = bus;
189 phb->last_busno = bus;
190 phb->ops = &iSeries_pci_ops;
191
192 /* Find and connect the devices. */
193 for (dn = NULL; (dn = of_get_next_child(node, dn)) != NULL;) {
194 struct pci_dn *pdn;
195 u8 irq;
196 int err;
197 u32 *agent;
198 u32 *reg;
199 u32 *lsn;
200
201 reg = (u32 *)get_property(dn, "reg", NULL);
202 if (reg == NULL) {
203 printk(KERN_DEBUG "no reg property!\n");
204 continue;
205 }
206 busp = (u32 *)get_property(dn, "linux,subbus", NULL);
207 if (busp == NULL) {
208 printk(KERN_DEBUG "no subbus property!\n");
209 continue;
210 }
211 agent = (u32 *)get_property(dn, "linux,agent-id", NULL);
212 if (agent == NULL) {
213 printk(KERN_DEBUG "no agent-id\n");
214 continue;
215 }
216 lsn = (u32 *)get_property(dn,
217 "linux,logical-slot-number", NULL);
218 if (lsn == NULL) {
219 printk(KERN_DEBUG "no logical-slot-number\n");
220 continue;
221 }
213 222
214 phb->pci_mem_offset = phb->local_number = bus; 223 irq = iSeries_allocate_IRQ(bus, 0, *busp);
215 phb->first_busno = bus; 224 err = HvCallXm_connectBusUnit(bus, *busp, *agent, irq);
216 phb->last_busno = bus; 225 if (err) {
217 phb->ops = &iSeries_pci_ops; 226 pci_Log_Error("Connect Bus Unit",
227 bus, *busp, *agent, err);
228 continue;
229 }
230 err = HvCallPci_configStore8(bus, *busp, *agent,
231 PCI_INTERRUPT_LINE, irq);
232 if (err) {
233 pci_Log_Error("PciCfgStore Irq Failed!",
234 bus, *busp, *agent, err);
235 continue;
236 }
218 237
219 /* Find and connect the devices. */ 238 pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
220 scan_PHB_slots(phb); 239 if (pdn == NULL)
240 return;
241 dn->data = pdn;
242 pdn->node = dn;
243 pdn->busno = bus;
244 pdn->devfn = (reg[0] >> 8) & 0xff;
245 pdn->bussubno = *busp;
246 pdn->Irq = irq;
247 pdn->LogicalSlot = *lsn;
248 list_add_tail(&pdn->Device_List,
249 &iSeries_Global_Device_List);
221 } 250 }
222 /*
223 * Check for Unexpected Return code, a clue that something
224 * has gone wrong.
225 */
226 else if (ret != 0x0301)
227 printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X",
228 bus, ret);
229 } 251 }
230} 252}
231 253
@@ -272,147 +294,6 @@ void pcibios_fixup_resources(struct pci_dev *pdev)
272} 294}
273 295
274/* 296/*
275 * Loop through each node function to find usable EADs bridges.
276 */
277static void scan_PHB_slots(struct pci_controller *Phb)
278{
279 struct HvCallPci_DeviceInfo *DevInfo;
280 HvBusNumber bus = Phb->local_number; /* System Bus */
281 const HvSubBusNumber SubBus = 0; /* EADs is always 0. */
282 int HvRc = 0;
283 int IdSel;
284 const int MaxAgents = 8;
285
286 DevInfo = kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL);
287 if (DevInfo == NULL)
288 return;
289
290 /*
291 * Probe for EADs Bridges
292 */
293 for (IdSel = 1; IdSel < MaxAgents; ++IdSel) {
294 HvRc = HvCallPci_getDeviceInfo(bus, SubBus, IdSel,
295 iseries_hv_addr(DevInfo),
296 sizeof(struct HvCallPci_DeviceInfo));
297 if (HvRc == 0) {
298 if (DevInfo->deviceType == HvCallPci_NodeDevice)
299 scan_EADS_bridge(bus, SubBus, IdSel);
300 else
301 printk("PCI: Invalid System Configuration(0x%02X)"
302 " for bus 0x%02x id 0x%02x.\n",
303 DevInfo->deviceType, bus, IdSel);
304 }
305 else
306 pci_Log_Error("getDeviceInfo", bus, SubBus, IdSel, HvRc);
307 }
308 kfree(DevInfo);
309}
310
311static void scan_EADS_bridge(HvBusNumber bus, HvSubBusNumber SubBus,
312 int IdSel)
313{
314 struct HvCallPci_BridgeInfo *BridgeInfo;
315 HvAgentId AgentId;
316 int Function;
317 int HvRc;
318
319 BridgeInfo = (struct HvCallPci_BridgeInfo *)
320 kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL);
321 if (BridgeInfo == NULL)
322 return;
323
324 /* Note: hvSubBus and irq is always be 0 at this level! */
325 for (Function = 0; Function < 8; ++Function) {
326 AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
327 HvRc = HvCallXm_connectBusUnit(bus, SubBus, AgentId, 0);
328 if (HvRc == 0) {
329 printk("found device at bus %d idsel %d func %d (AgentId %x)\n",
330 bus, IdSel, Function, AgentId);
331 /* Connect EADs: 0x18.00.12 = 0x00 */
332 HvRc = HvCallPci_getBusUnitInfo(bus, SubBus, AgentId,
333 iseries_hv_addr(BridgeInfo),
334 sizeof(struct HvCallPci_BridgeInfo));
335 if (HvRc == 0) {
336 printk("bridge info: type %x subbus %x maxAgents %x maxsubbus %x logslot %x\n",
337 BridgeInfo->busUnitInfo.deviceType,
338 BridgeInfo->subBusNumber,
339 BridgeInfo->maxAgents,
340 BridgeInfo->maxSubBusNumber,
341 BridgeInfo->logicalSlotNumber);
342 if (BridgeInfo->busUnitInfo.deviceType ==
343 HvCallPci_BridgeDevice) {
344 /* Scan_Bridge_Slot...: 0x18.00.12 */
345 scan_bridge_slot(bus, BridgeInfo);
346 } else
347 printk("PCI: Invalid Bridge Configuration(0x%02X)",
348 BridgeInfo->busUnitInfo.deviceType);
349 }
350 } else if (HvRc != 0x000B)
351 pci_Log_Error("EADs Connect",
352 bus, SubBus, AgentId, HvRc);
353 }
354 kfree(BridgeInfo);
355}
356
357/*
358 * This assumes that the node slot is always on the primary bus!
359 */
360static int scan_bridge_slot(HvBusNumber Bus,
361 struct HvCallPci_BridgeInfo *BridgeInfo)
362{
363 struct device_node *node;
364 HvSubBusNumber SubBus = BridgeInfo->subBusNumber;
365 u16 VendorId = 0;
366 int HvRc = 0;
367 u8 Irq = 0;
368 int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus);
369 int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus);
370 HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function);
371
372 /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */
373 Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel);
374
375 /*
376 * Connect all functions of any device found.
377 */
378 for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) {
379 for (Function = 0; Function < 8; ++Function) {
380 HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
381 HvRc = HvCallXm_connectBusUnit(Bus, SubBus,
382 AgentId, Irq);
383 if (HvRc != 0) {
384 pci_Log_Error("Connect Bus Unit",
385 Bus, SubBus, AgentId, HvRc);
386 continue;
387 }
388
389 HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId,
390 PCI_VENDOR_ID, &VendorId);
391 if (HvRc != 0) {
392 pci_Log_Error("Read Vendor",
393 Bus, SubBus, AgentId, HvRc);
394 continue;
395 }
396 printk("read vendor ID: %x\n", VendorId);
397
398 /* FoundDevice: 0x18.28.10 = 0x12AE */
399 HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId,
400 PCI_INTERRUPT_LINE, Irq);
401 if (HvRc != 0)
402 pci_Log_Error("PciCfgStore Irq Failed!",
403 Bus, SubBus, AgentId, HvRc);
404
405 ++DeviceCount;
406 node = build_device_node(Bus, SubBus, EADsIdSel, Function);
407 PCI_DN(node)->Irq = Irq;
408 PCI_DN(node)->LogicalSlot = BridgeInfo->logicalSlotNumber;
409
410 } /* for (Function = 0; Function < 8; ++Function) */
411 } /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */
412 return HvRc;
413}
414
415/*
416 * I/0 Memory copy MUST use mmio commands on iSeries 297 * I/0 Memory copy MUST use mmio commands on iSeries
417 * To do; For performance, include the hv call directly 298 * To do; For performance, include the hv call directly
418 */ 299 */
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index fd6d0ebe8dd..d83f5ed4ec1 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -66,6 +66,8 @@
66#include "main_store.h" 66#include "main_store.h"
67#include "call_sm.h" 67#include "call_sm.h"
68#include "call_hpt.h" 68#include "call_hpt.h"
69#include "call_pci.h"
70#include "pci.h"
69 71
70#ifdef DEBUG 72#ifdef DEBUG
71#define DBG(fmt...) udbg_printf(fmt) 73#define DBG(fmt...) udbg_printf(fmt)
@@ -1000,6 +1002,207 @@ void dt_vdevices(struct iseries_flat_dt *dt)
1000 dt_end_node(dt); 1002 dt_end_node(dt);
1001} 1003}
1002 1004
1005/*
1006 * This assumes that the node slot is always on the primary bus!
1007 */
1008static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus,
1009 struct HvCallPci_BridgeInfo *bridge_info)
1010{
1011 HvSubBusNumber sub_bus = bridge_info->subBusNumber;
1012 u16 vendor_id;
1013 u16 device_id;
1014 u32 class_id;
1015 int err;
1016 char buf[32];
1017 u32 reg[5];
1018 int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus);
1019 int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus);
1020 HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function);
1021
1022 /*
1023 * Connect all functions of any device found.
1024 */
1025 for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) {
1026 for (function = 0; function < 8; function++) {
1027 u8 devfn;
1028
1029 HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel,
1030 function);
1031 err = HvCallXm_connectBusUnit(bus, sub_bus,
1032 agent_id, 0);
1033 if (err) {
1034 if (err != 0x302)
1035 printk(KERN_DEBUG
1036 "connectBusUnit(%x, %x, %x) "
1037 "== %x\n",
1038 bus, sub_bus, agent_id, err);
1039 continue;
1040 }
1041
1042 err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
1043 PCI_VENDOR_ID, &vendor_id);
1044 if (err) {
1045 printk(KERN_DEBUG
1046 "ReadVendor(%x, %x, %x) == %x\n",
1047 bus, sub_bus, agent_id, err);
1048 continue;
1049 }
1050 err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
1051 PCI_DEVICE_ID, &device_id);
1052 if (err) {
1053 printk(KERN_DEBUG
1054 "ReadDevice(%x, %x, %x) == %x\n",
1055 bus, sub_bus, agent_id, err);
1056 continue;
1057 }
1058 err = HvCallPci_configLoad32(bus, sub_bus, agent_id,
1059 PCI_CLASS_REVISION , &class_id);
1060 if (err) {
1061 printk(KERN_DEBUG
1062 "ReadClass(%x, %x, %x) == %x\n",
1063 bus, sub_bus, agent_id, err);
1064 continue;
1065 }
1066
1067 devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel),
1068 function);
1069 if (function == 0)
1070 snprintf(buf, sizeof(buf), "pci@%x",
1071 PCI_SLOT(devfn));
1072 else
1073 snprintf(buf, sizeof(buf), "pci@%x,%d",
1074 PCI_SLOT(devfn), function);
1075 dt_start_node(dt, buf);
1076 reg[0] = (bus << 18) | (devfn << 8);
1077 reg[1] = 0;
1078 reg[2] = 0;
1079 reg[3] = 0;
1080 reg[4] = 0;
1081 dt_prop_u32_list(dt, "reg", reg, 5);
1082 dt_prop_u32(dt, "vendor-id", vendor_id);
1083 dt_prop_u32(dt, "device-id", device_id);
1084 dt_prop_u32(dt, "class-code", class_id >> 8);
1085 dt_prop_u32(dt, "revision-id", class_id & 0xff);
1086 dt_prop_u32(dt, "linux,subbus", sub_bus);
1087 dt_prop_u32(dt, "linux,agent-id", agent_id);
1088 dt_prop_u32(dt, "linux,logical-slot-number",
1089 bridge_info->logicalSlotNumber);
1090 dt_end_node(dt);
1091
1092 }
1093 }
1094}
1095
1096static void scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus,
1097 HvSubBusNumber sub_bus, int id_sel)
1098{
1099 struct HvCallPci_BridgeInfo bridge_info;
1100 HvAgentId agent_id;
1101 int function;
1102 int ret;
1103
1104 /* Note: hvSubBus and irq is always be 0 at this level! */
1105 for (function = 0; function < 8; ++function) {
1106 agent_id = ISERIES_PCI_AGENTID(id_sel, function);
1107 ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0);
1108 if (ret != 0) {
1109 if (ret != 0xb)
1110 printk(KERN_DEBUG "connectBusUnit(%x, %x, %x) "
1111 "== %x\n",
1112 bus, sub_bus, agent_id, ret);
1113 continue;
1114 }
1115 printk("found device at bus %d idsel %d func %d (AgentId %x)\n",
1116 bus, id_sel, function, agent_id);
1117 ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id,
1118 iseries_hv_addr(&bridge_info),
1119 sizeof(struct HvCallPci_BridgeInfo));
1120 if (ret != 0)
1121 continue;
1122 printk("bridge info: type %x subbus %x "
1123 "maxAgents %x maxsubbus %x logslot %x\n",
1124 bridge_info.busUnitInfo.deviceType,
1125 bridge_info.subBusNumber,
1126 bridge_info.maxAgents,
1127 bridge_info.maxSubBusNumber,
1128 bridge_info.logicalSlotNumber);
1129 if (bridge_info.busUnitInfo.deviceType ==
1130 HvCallPci_BridgeDevice)
1131 scan_bridge_slot(dt, bus, &bridge_info);
1132 else
1133 printk("PCI: Invalid Bridge Configuration(0x%02X)",
1134 bridge_info.busUnitInfo.deviceType);
1135 }
1136}
1137
1138static void scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus)
1139{
1140 struct HvCallPci_DeviceInfo dev_info;
1141 const HvSubBusNumber sub_bus = 0; /* EADs is always 0. */
1142 int err;
1143 int id_sel;
1144 const int max_agents = 8;
1145
1146 /*
1147 * Probe for EADs Bridges
1148 */
1149 for (id_sel = 1; id_sel < max_agents; ++id_sel) {
1150 err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel,
1151 iseries_hv_addr(&dev_info),
1152 sizeof(struct HvCallPci_DeviceInfo));
1153 if (err) {
1154 if (err != 0x302)
1155 printk(KERN_DEBUG "getDeviceInfo(%x, %x, %x) "
1156 "== %x\n",
1157 bus, sub_bus, id_sel, err);
1158 continue;
1159 }
1160 if (dev_info.deviceType != HvCallPci_NodeDevice) {
1161 printk(KERN_DEBUG "PCI: Invalid System Configuration"
1162 "(0x%02X) for bus 0x%02x id 0x%02x.\n",
1163 dev_info.deviceType, bus, id_sel);
1164 continue;
1165 }
1166 scan_bridge(dt, bus, sub_bus, id_sel);
1167 }
1168}
1169
1170static void dt_pci_devices(struct iseries_flat_dt *dt)
1171{
1172 HvBusNumber bus;
1173 char buf[32];
1174 u32 buses[2];
1175 int phb_num = 0;
1176
1177 /* Check all possible buses. */
1178 for (bus = 0; bus < 256; bus++) {
1179 int err = HvCallXm_testBus(bus);
1180
1181 if (err) {
1182 /*
1183 * Check for Unexpected Return code, a clue that
1184 * something has gone wrong.
1185 */
1186 if (err != 0x0301)
1187 printk(KERN_ERR "Unexpected Return on Probe"
1188 "(0x%02X): 0x%04X", bus, err);
1189 continue;
1190 }
1191 printk("bus %d appears to exist\n", bus);
1192 snprintf(buf, 32, "pci@%d", phb_num);
1193 dt_start_node(dt, buf);
1194 dt_prop_str(dt, "device_type", "pci");
1195 dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB");
1196 dt_prop_u32(dt, "#address-cells", 3);
1197 dt_prop_u32(dt, "#size-cells", 2);
1198 buses[0] = buses[1] = bus;
1199 dt_prop_u32_list(dt, "bus-range", buses, 2);
1200 scan_phb(dt, bus);
1201 dt_end_node(dt);
1202 phb_num++;
1203 }
1204}
1205
1003void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) 1206void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
1004{ 1207{
1005 u64 tmp[2]; 1208 u64 tmp[2];
@@ -1029,6 +1232,7 @@ void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
1029 dt_cpus(dt); 1232 dt_cpus(dt);
1030 1233
1031 dt_vdevices(dt); 1234 dt_vdevices(dt);
1235 dt_pci_devices(dt);
1032 1236
1033 dt_end_node(dt); 1237 dt_end_node(dt);
1034 1238