* [PATCH 02/14] powerpc: reintroduce HvCallPci_configLoad32
2006-05-19 6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
@ 2006-05-19 6:43 ` Stephen Rothwell
2006-05-19 6:46 ` [PATCH 03/14] powerpc: move iSeries PCI devices to the device tree Stephen Rothwell
` (11 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19 6:43 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
This function was removed during iSeries cleanup but will prove useful
in the following patches.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/platforms/iseries/call_pci.h | 19 +++++++++++++++++++
1 files changed, 19 insertions(+), 0 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
59ad1dcb0d8d81e3a96f869109315652abf271f7
diff --git a/arch/powerpc/platforms/iseries/call_pci.h b/arch/powerpc/platforms/iseries/call_pci.h
index 59d4e0a..dbdf698 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
return retVal.rc;
}
+static inline u64 HvCallPci_configLoad32(u16 busNumber, u8 subBusNumber,
+ u8 deviceId, u32 offset, u32 *value)
+{
+ struct HvCallPci_DsaAddr dsa;
+ struct HvCallPci_LoadReturn retVal;
+
+ *((u64*)&dsa) = 0;
+
+ dsa.busNumber = busNumber;
+ dsa.subBusNumber = subBusNumber;
+ dsa.deviceId = deviceId;
+
+ HvCall3Ret16(HvCallPciConfigLoad32, &retVal, *(u64 *)&dsa, offset, 0);
+
+ *value = retVal.value;
+
+ return retVal.rc;
+}
+
static inline u64 HvCallPci_configStore8(u16 busNumber, u8 subBusNumber,
u8 deviceId, u32 offset, u8 value)
{
--
1.3.1.ge923
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 03/14] powerpc: move iSeries PCI devices to the device tree
2006-05-19 6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
2006-05-19 6:43 ` [PATCH 02/14] powerpc: reintroduce HvCallPci_configLoad32 Stephen Rothwell
@ 2006-05-19 6:46 ` Stephen Rothwell
2006-05-19 6:48 ` [PATCH 04/14] powerpc: remove iSeries_Global_Device_List Stephen Rothwell
` (10 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19 6:46 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
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>
---
arch/powerpc/platforms/iseries/irq.c | 7 -
arch/powerpc/platforms/iseries/irq.h | 2
arch/powerpc/platforms/iseries/pci.c | 273 +++++++++-----------------------
arch/powerpc/platforms/iseries/setup.c | 204 ++++++++++++++++++++++++
4 files changed, 286 insertions(+), 200 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
97c92bf9859c9d883da1b8459f62dec2ab20804e
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index be3fbfc..62bbbcf 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -42,6 +42,7 @@ #include <asm/iseries/hv_call_xm.h>
#include <asm/iseries/it_lp_queue.h>
#include "irq.h"
+#include "pci.h"
#include "call_pci.h"
#if defined(CONFIG_SMP)
@@ -312,12 +313,12 @@ static hw_irq_controller iSeries_IRQ_han
* Note that sub_bus is always 0 (at the moment at least).
*/
int __init iSeries_allocate_IRQ(HvBusNumber bus,
- HvSubBusNumber sub_bus, HvAgentId dev_id)
+ HvSubBusNumber sub_bus, u32 bsubbus)
{
int virtirq;
unsigned int realirq;
- u8 idsel = (dev_id >> 4);
- u8 function = dev_id & 7;
+ u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus);
+ u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus);
realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3)
+ function;
diff --git a/arch/powerpc/platforms/iseries/irq.h b/arch/powerpc/platforms/iseries/irq.h
index b9c801b..188aa80 100644
--- a/arch/powerpc/platforms/iseries/irq.h
+++ b/arch/powerpc/platforms/iseries/irq.h
@@ -2,7 +2,7 @@ #ifndef _ISERIES_IRQ_H
#define _ISERIES_IRQ_H
extern void iSeries_init_IRQ(void);
-extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId);
+extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, u32);
extern void iSeries_activate_IRQs(void);
extern int iSeries_get_irq(struct pt_regs *);
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 91a9474..9d571e7 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -49,14 +49,9 @@ #include "call_pci.h"
* Forward declares of prototypes.
*/
static struct device_node *find_Device_Node(int bus, int devfn);
-static void scan_PHB_slots(struct pci_controller *Phb);
-static void scan_EADS_bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel);
-static int scan_bridge_slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo *Info);
LIST_HEAD(iSeries_Global_Device_List);
-static int DeviceCount;
-
static int Pci_Retry_Max = 3; /* Only retry 3 times */
static int Pci_Error_Flag = 1; /* Set Retry Error on. */
@@ -162,32 +157,6 @@ static void pci_Log_Error(char *Error_Te
}
/*
- * build_device_node(u16 Bus, int SubBus, u8 DevFn)
- */
-static struct device_node *build_device_node(HvBusNumber Bus,
- HvSubBusNumber SubBus, int AgentId, int Function)
-{
- struct device_node *node;
- struct pci_dn *pdn;
-
- node = kzalloc(sizeof(struct device_node), GFP_KERNEL);
- if (node == NULL)
- return NULL;
- pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
- if (pdn == NULL) {
- kfree(node);
- return NULL;
- }
- node->data = pdn;
- pdn->node = node;
- list_add_tail(&pdn->Device_List, &iSeries_Global_Device_List);
- pdn->busno = Bus;
- pdn->bussubno = SubBus;
- pdn->devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function);
- return node;
-}
-
-/*
* iSeries_pcibios_init
*
* Description:
@@ -199,33 +168,86 @@ static struct device_node *build_device_
void iSeries_pcibios_init(void)
{
struct pci_controller *phb;
- HvBusNumber bus;
-
- /* Check all possible buses. */
- for (bus = 0; bus < 256; bus++) {
- int ret = HvCallXm_testBus(bus);
- if (ret == 0) {
- printk("bus %d appears to exist\n", bus);
-
- phb = pcibios_alloc_controller(NULL);
- if (phb == NULL)
- return -ENOMEM;
+ struct device_node *node;
+ struct device_node *dn;
+
+ for_each_node_by_type(node, "pci") {
+ HvBusNumber bus;
+ u32 *busp;
+
+ busp = (u32 *)get_property(node, "bus-range", NULL);
+ if (busp == NULL)
+ continue;
+ bus = *busp;
+ printk("bus %d appears to exist\n", bus);
+ phb = pcibios_alloc_controller(node);
+ if (phb == NULL)
+ continue;
+
+ phb->pci_mem_offset = phb->local_number = bus;
+ phb->first_busno = bus;
+ phb->last_busno = bus;
+ phb->ops = &iSeries_pci_ops;
+
+ /* Find and connect the devices. */
+ for (dn = NULL; (dn = of_get_next_child(node, dn)) != NULL;) {
+ struct pci_dn *pdn;
+ u8 irq;
+ int err;
+ u32 *agent;
+ u32 *reg;
+ u32 *lsn;
+
+ reg = (u32 *)get_property(dn, "reg", NULL);
+ if (reg == NULL) {
+ printk(KERN_DEBUG "no reg property!\n");
+ continue;
+ }
+ busp = (u32 *)get_property(dn, "linux,subbus", NULL);
+ if (busp == NULL) {
+ printk(KERN_DEBUG "no subbus property!\n");
+ continue;
+ }
+ agent = (u32 *)get_property(dn, "linux,agent-id", NULL);
+ if (agent == NULL) {
+ printk(KERN_DEBUG "no agent-id\n");
+ continue;
+ }
+ lsn = (u32 *)get_property(dn,
+ "linux,logical-slot-number", NULL);
+ if (lsn == NULL) {
+ printk(KERN_DEBUG "no logical-slot-number\n");
+ continue;
+ }
- phb->pci_mem_offset = phb->local_number = bus;
- phb->first_busno = bus;
- phb->last_busno = bus;
- phb->ops = &iSeries_pci_ops;
+ irq = iSeries_allocate_IRQ(bus, 0, *busp);
+ err = HvCallXm_connectBusUnit(bus, *busp, *agent, irq);
+ if (err) {
+ pci_Log_Error("Connect Bus Unit",
+ bus, *busp, *agent, err);
+ continue;
+ }
+ err = HvCallPci_configStore8(bus, *busp, *agent,
+ PCI_INTERRUPT_LINE, irq);
+ if (err) {
+ pci_Log_Error("PciCfgStore Irq Failed!",
+ bus, *busp, *agent, err);
+ continue;
+ }
- /* Find and connect the devices. */
- scan_PHB_slots(phb);
+ pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
+ if (pdn == NULL)
+ return;
+ dn->data = pdn;
+ pdn->node = dn;
+ pdn->busno = bus;
+ pdn->devfn = (reg[0] >> 8) & 0xff;
+ pdn->bussubno = *busp;
+ pdn->Irq = irq;
+ pdn->LogicalSlot = *lsn;
+ list_add_tail(&pdn->Device_List,
+ &iSeries_Global_Device_List);
}
- /*
- * Check for Unexpected Return code, a clue that something
- * has gone wrong.
- */
- else if (ret != 0x0301)
- printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X",
- bus, ret);
}
}
@@ -272,147 +294,6 @@ void pcibios_fixup_resources(struct pci_
}
/*
- * Loop through each node function to find usable EADs bridges.
- */
-static void scan_PHB_slots(struct pci_controller *Phb)
-{
- struct HvCallPci_DeviceInfo *DevInfo;
- HvBusNumber bus = Phb->local_number; /* System Bus */
- const HvSubBusNumber SubBus = 0; /* EADs is always 0. */
- int HvRc = 0;
- int IdSel;
- const int MaxAgents = 8;
-
- DevInfo = kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL);
- if (DevInfo == NULL)
- return;
-
- /*
- * Probe for EADs Bridges
- */
- for (IdSel = 1; IdSel < MaxAgents; ++IdSel) {
- HvRc = HvCallPci_getDeviceInfo(bus, SubBus, IdSel,
- iseries_hv_addr(DevInfo),
- sizeof(struct HvCallPci_DeviceInfo));
- if (HvRc == 0) {
- if (DevInfo->deviceType == HvCallPci_NodeDevice)
- scan_EADS_bridge(bus, SubBus, IdSel);
- else
- printk("PCI: Invalid System Configuration(0x%02X)"
- " for bus 0x%02x id 0x%02x.\n",
- DevInfo->deviceType, bus, IdSel);
- }
- else
- pci_Log_Error("getDeviceInfo", bus, SubBus, IdSel, HvRc);
- }
- kfree(DevInfo);
-}
-
-static void scan_EADS_bridge(HvBusNumber bus, HvSubBusNumber SubBus,
- int IdSel)
-{
- struct HvCallPci_BridgeInfo *BridgeInfo;
- HvAgentId AgentId;
- int Function;
- int HvRc;
-
- BridgeInfo = (struct HvCallPci_BridgeInfo *)
- kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL);
- if (BridgeInfo == NULL)
- return;
-
- /* Note: hvSubBus and irq is always be 0 at this level! */
- for (Function = 0; Function < 8; ++Function) {
- AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
- HvRc = HvCallXm_connectBusUnit(bus, SubBus, AgentId, 0);
- if (HvRc == 0) {
- printk("found device at bus %d idsel %d func %d (AgentId %x)\n",
- bus, IdSel, Function, AgentId);
- /* Connect EADs: 0x18.00.12 = 0x00 */
- HvRc = HvCallPci_getBusUnitInfo(bus, SubBus, AgentId,
- iseries_hv_addr(BridgeInfo),
- sizeof(struct HvCallPci_BridgeInfo));
- if (HvRc == 0) {
- printk("bridge info: type %x subbus %x maxAgents %x maxsubbus %x logslot %x\n",
- BridgeInfo->busUnitInfo.deviceType,
- BridgeInfo->subBusNumber,
- BridgeInfo->maxAgents,
- BridgeInfo->maxSubBusNumber,
- BridgeInfo->logicalSlotNumber);
- if (BridgeInfo->busUnitInfo.deviceType ==
- HvCallPci_BridgeDevice) {
- /* Scan_Bridge_Slot...: 0x18.00.12 */
- scan_bridge_slot(bus, BridgeInfo);
- } else
- printk("PCI: Invalid Bridge Configuration(0x%02X)",
- BridgeInfo->busUnitInfo.deviceType);
- }
- } else if (HvRc != 0x000B)
- pci_Log_Error("EADs Connect",
- bus, SubBus, AgentId, HvRc);
- }
- kfree(BridgeInfo);
-}
-
-/*
- * This assumes that the node slot is always on the primary bus!
- */
-static int scan_bridge_slot(HvBusNumber Bus,
- struct HvCallPci_BridgeInfo *BridgeInfo)
-{
- struct device_node *node;
- HvSubBusNumber SubBus = BridgeInfo->subBusNumber;
- u16 VendorId = 0;
- int HvRc = 0;
- u8 Irq = 0;
- int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus);
- int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus);
- HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function);
-
- /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */
- Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel);
-
- /*
- * Connect all functions of any device found.
- */
- for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) {
- for (Function = 0; Function < 8; ++Function) {
- HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
- HvRc = HvCallXm_connectBusUnit(Bus, SubBus,
- AgentId, Irq);
- if (HvRc != 0) {
- pci_Log_Error("Connect Bus Unit",
- Bus, SubBus, AgentId, HvRc);
- continue;
- }
-
- HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId,
- PCI_VENDOR_ID, &VendorId);
- if (HvRc != 0) {
- pci_Log_Error("Read Vendor",
- Bus, SubBus, AgentId, HvRc);
- continue;
- }
- printk("read vendor ID: %x\n", VendorId);
-
- /* FoundDevice: 0x18.28.10 = 0x12AE */
- HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId,
- PCI_INTERRUPT_LINE, Irq);
- if (HvRc != 0)
- pci_Log_Error("PciCfgStore Irq Failed!",
- Bus, SubBus, AgentId, HvRc);
-
- ++DeviceCount;
- node = build_device_node(Bus, SubBus, EADsIdSel, Function);
- PCI_DN(node)->Irq = Irq;
- PCI_DN(node)->LogicalSlot = BridgeInfo->logicalSlotNumber;
-
- } /* for (Function = 0; Function < 8; ++Function) */
- } /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */
- return HvRc;
-}
-
-/*
* I/0 Memory copy MUST use mmio commands on iSeries
* To do; For performance, include the hv call directly
*/
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index fd6d0eb..d83f5ed 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -66,6 +66,8 @@ #include "processor_vpd.h"
#include "main_store.h"
#include "call_sm.h"
#include "call_hpt.h"
+#include "call_pci.h"
+#include "pci.h"
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
@@ -1000,6 +1002,207 @@ void dt_vdevices(struct iseries_flat_dt
dt_end_node(dt);
}
+/*
+ * This assumes that the node slot is always on the primary bus!
+ */
+static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus,
+ struct HvCallPci_BridgeInfo *bridge_info)
+{
+ HvSubBusNumber sub_bus = bridge_info->subBusNumber;
+ u16 vendor_id;
+ u16 device_id;
+ u32 class_id;
+ int err;
+ char buf[32];
+ u32 reg[5];
+ int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus);
+ int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus);
+ HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function);
+
+ /*
+ * Connect all functions of any device found.
+ */
+ for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) {
+ for (function = 0; function < 8; function++) {
+ u8 devfn;
+
+ HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel,
+ function);
+ err = HvCallXm_connectBusUnit(bus, sub_bus,
+ agent_id, 0);
+ if (err) {
+ if (err != 0x302)
+ printk(KERN_DEBUG
+ "connectBusUnit(%x, %x, %x) "
+ "== %x\n",
+ bus, sub_bus, agent_id, err);
+ continue;
+ }
+
+ err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
+ PCI_VENDOR_ID, &vendor_id);
+ if (err) {
+ printk(KERN_DEBUG
+ "ReadVendor(%x, %x, %x) == %x\n",
+ bus, sub_bus, agent_id, err);
+ continue;
+ }
+ err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
+ PCI_DEVICE_ID, &device_id);
+ if (err) {
+ printk(KERN_DEBUG
+ "ReadDevice(%x, %x, %x) == %x\n",
+ bus, sub_bus, agent_id, err);
+ continue;
+ }
+ err = HvCallPci_configLoad32(bus, sub_bus, agent_id,
+ PCI_CLASS_REVISION , &class_id);
+ if (err) {
+ printk(KERN_DEBUG
+ "ReadClass(%x, %x, %x) == %x\n",
+ bus, sub_bus, agent_id, err);
+ continue;
+ }
+
+ devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel),
+ function);
+ if (function == 0)
+ snprintf(buf, sizeof(buf), "pci@%x",
+ PCI_SLOT(devfn));
+ else
+ snprintf(buf, sizeof(buf), "pci@%x,%d",
+ PCI_SLOT(devfn), function);
+ dt_start_node(dt, buf);
+ reg[0] = (bus << 18) | (devfn << 8);
+ reg[1] = 0;
+ reg[2] = 0;
+ reg[3] = 0;
+ reg[4] = 0;
+ dt_prop_u32_list(dt, "reg", reg, 5);
+ dt_prop_u32(dt, "vendor-id", vendor_id);
+ dt_prop_u32(dt, "device-id", device_id);
+ dt_prop_u32(dt, "class-code", class_id >> 8);
+ dt_prop_u32(dt, "revision-id", class_id & 0xff);
+ dt_prop_u32(dt, "linux,subbus", sub_bus);
+ dt_prop_u32(dt, "linux,agent-id", agent_id);
+ dt_prop_u32(dt, "linux,logical-slot-number",
+ bridge_info->logicalSlotNumber);
+ dt_end_node(dt);
+
+ }
+ }
+}
+
+static void scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus,
+ HvSubBusNumber sub_bus, int id_sel)
+{
+ struct HvCallPci_BridgeInfo bridge_info;
+ HvAgentId agent_id;
+ int function;
+ int ret;
+
+ /* Note: hvSubBus and irq is always be 0 at this level! */
+ for (function = 0; function < 8; ++function) {
+ agent_id = ISERIES_PCI_AGENTID(id_sel, function);
+ ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0);
+ if (ret != 0) {
+ if (ret != 0xb)
+ printk(KERN_DEBUG "connectBusUnit(%x, %x, %x) "
+ "== %x\n",
+ bus, sub_bus, agent_id, ret);
+ continue;
+ }
+ printk("found device at bus %d idsel %d func %d (AgentId %x)\n",
+ bus, id_sel, function, agent_id);
+ ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id,
+ iseries_hv_addr(&bridge_info),
+ sizeof(struct HvCallPci_BridgeInfo));
+ if (ret != 0)
+ continue;
+ printk("bridge info: type %x subbus %x "
+ "maxAgents %x maxsubbus %x logslot %x\n",
+ bridge_info.busUnitInfo.deviceType,
+ bridge_info.subBusNumber,
+ bridge_info.maxAgents,
+ bridge_info.maxSubBusNumber,
+ bridge_info.logicalSlotNumber);
+ if (bridge_info.busUnitInfo.deviceType ==
+ HvCallPci_BridgeDevice)
+ scan_bridge_slot(dt, bus, &bridge_info);
+ else
+ printk("PCI: Invalid Bridge Configuration(0x%02X)",
+ bridge_info.busUnitInfo.deviceType);
+ }
+}
+
+static void scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus)
+{
+ struct HvCallPci_DeviceInfo dev_info;
+ const HvSubBusNumber sub_bus = 0; /* EADs is always 0. */
+ int err;
+ int id_sel;
+ const int max_agents = 8;
+
+ /*
+ * Probe for EADs Bridges
+ */
+ for (id_sel = 1; id_sel < max_agents; ++id_sel) {
+ err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel,
+ iseries_hv_addr(&dev_info),
+ sizeof(struct HvCallPci_DeviceInfo));
+ if (err) {
+ if (err != 0x302)
+ printk(KERN_DEBUG "getDeviceInfo(%x, %x, %x) "
+ "== %x\n",
+ bus, sub_bus, id_sel, err);
+ continue;
+ }
+ if (dev_info.deviceType != HvCallPci_NodeDevice) {
+ printk(KERN_DEBUG "PCI: Invalid System Configuration"
+ "(0x%02X) for bus 0x%02x id 0x%02x.\n",
+ dev_info.deviceType, bus, id_sel);
+ continue;
+ }
+ scan_bridge(dt, bus, sub_bus, id_sel);
+ }
+}
+
+static void dt_pci_devices(struct iseries_flat_dt *dt)
+{
+ HvBusNumber bus;
+ char buf[32];
+ u32 buses[2];
+ int phb_num = 0;
+
+ /* Check all possible buses. */
+ for (bus = 0; bus < 256; bus++) {
+ int err = HvCallXm_testBus(bus);
+
+ if (err) {
+ /*
+ * Check for Unexpected Return code, a clue that
+ * something has gone wrong.
+ */
+ if (err != 0x0301)
+ printk(KERN_ERR "Unexpected Return on Probe"
+ "(0x%02X): 0x%04X", bus, err);
+ continue;
+ }
+ printk("bus %d appears to exist\n", bus);
+ snprintf(buf, 32, "pci@%d", phb_num);
+ dt_start_node(dt, buf);
+ dt_prop_str(dt, "device_type", "pci");
+ dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB");
+ dt_prop_u32(dt, "#address-cells", 3);
+ dt_prop_u32(dt, "#size-cells", 2);
+ buses[0] = buses[1] = bus;
+ dt_prop_u32_list(dt, "bus-range", buses, 2);
+ scan_phb(dt, bus);
+ dt_end_node(dt);
+ phb_num++;
+ }
+}
+
void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
{
u64 tmp[2];
@@ -1029,6 +1232,7 @@ void build_flat_dt(struct iseries_flat_d
dt_cpus(dt);
dt_vdevices(dt);
+ dt_pci_devices(dt);
dt_end_node(dt);
--
1.3.1.ge923
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 04/14] powerpc: remove iSeries_Global_Device_List
2006-05-19 6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
2006-05-19 6:43 ` [PATCH 02/14] powerpc: reintroduce HvCallPci_configLoad32 Stephen Rothwell
2006-05-19 6:46 ` [PATCH 03/14] powerpc: move iSeries PCI devices to the device tree Stephen Rothwell
@ 2006-05-19 6:48 ` Stephen Rothwell
2006-05-19 6:50 ` [PATCH 05/14] powerpc: remove Irq from pci_dn Stephen Rothwell
` (9 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19 6:48 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
We can now scan the list of device nodes instead. This also allows us
to remove the Device_list member of struct pci_dn.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/platforms/iseries/iommu.c | 15 +++++++++------
arch/powerpc/platforms/iseries/pci.c | 14 ++++++--------
include/asm-powerpc/pci-bridge.h | 1 -
3 files changed, 15 insertions(+), 15 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
80052bf80f481996ffec6dddc8fab45bb36db0a3
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index 3ac2206..75a5a1e 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -32,13 +32,11 @@ #include <asm/iommu.h>
#include <asm/tce.h>
#include <asm/machdep.h>
#include <asm/abs_addr.h>
+#include <asm/prom.h>
#include <asm/pci-bridge.h>
#include <asm/iseries/hv_call_xm.h>
#include <asm/iseries/iommu.h>
-extern struct list_head iSeries_Global_Device_List;
-
-
static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
unsigned long uaddr, enum dma_data_direction direction)
{
@@ -140,10 +138,15 @@ #ifdef CONFIG_PCI
*/
static struct iommu_table *iommu_table_find(struct iommu_table * tbl)
{
- struct pci_dn *pdn;
+ struct device_node *node;
+
+ for (node = NULL; (node = of_find_all_nodes(node)); ) {
+ struct pci_dn *pdn = PCI_DN(node);
+ struct iommu_table *it;
- list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) {
- struct iommu_table *it = pdn->iommu_table;
+ if (pdn == NULL)
+ continue;
+ it = pdn->iommu_table;
if ((it != NULL) &&
(it->it_type == TCE_PCI) &&
(it->it_offset == tbl->it_offset) &&
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 9d571e7..5bc08d4 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -50,8 +50,6 @@ #include "call_pci.h"
*/
static struct device_node *find_Device_Node(int bus, int devfn);
-LIST_HEAD(iSeries_Global_Device_List);
-
static int Pci_Retry_Max = 3; /* Only retry 3 times */
static int Pci_Error_Flag = 1; /* Set Retry Error on. */
@@ -245,8 +243,6 @@ void iSeries_pcibios_init(void)
pdn->bussubno = *busp;
pdn->Irq = irq;
pdn->LogicalSlot = *lsn;
- list_add_tail(&pdn->Device_List,
- &iSeries_Global_Device_List);
}
}
}
@@ -338,11 +334,13 @@ EXPORT_SYMBOL(iSeries_memcpy_fromio);
*/
static struct device_node *find_Device_Node(int bus, int devfn)
{
- struct pci_dn *pdn;
+ struct device_node *node;
+
+ for (node = NULL; (node = of_find_all_nodes(node)); ) {
+ struct pci_dn *pdn = PCI_DN(node);
- list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) {
- if ((bus == pdn->busno) && (devfn == pdn->devfn))
- return pdn->node;
+ if (pdn && (bus == pdn->busno) && (devfn == pdn->devfn))
+ return node;
}
return NULL;
}
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
index 38de92d..59794b4 100644
--- a/include/asm-powerpc/pci-bridge.h
+++ b/include/asm-powerpc/pci-bridge.h
@@ -79,7 +79,6 @@ #endif
struct pci_dev *pcidev; /* back-pointer to the pci device */
struct device_node *node; /* back-pointer to the device_node */
#ifdef CONFIG_PPC_ISERIES
- struct list_head Device_List;
int Irq; /* Assigned IRQ */
int Flags; /* Possible flags(disable/bist)*/
u8 LogicalSlot; /* Hv Slot Index for Tces */
--
1.3.1.ge923
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 05/14] powerpc: remove Irq from pci_dn
2006-05-19 6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
` (2 preceding siblings ...)
2006-05-19 6:48 ` [PATCH 04/14] powerpc: remove iSeries_Global_Device_List Stephen Rothwell
@ 2006-05-19 6:50 ` Stephen Rothwell
2006-05-19 6:51 ` [PATCH 06/14] powerpc: remove LogicalSlot " Stephen Rothwell
` (8 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19 6:50 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
As we now store enough information in the device_node to allocate the
irq number in pcibios_final_fixup.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/platforms/iseries/pci.c | 53 ++++++++++++++++++----------------
include/asm-powerpc/pci-bridge.h | 1 -
2 files changed, 28 insertions(+), 26 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
0a0cf362cf41de98069fb817acf23a4d041b45f4
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 5bc08d4..edaafbb 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -190,9 +190,6 @@ void iSeries_pcibios_init(void)
/* Find and connect the devices. */
for (dn = NULL; (dn = of_get_next_child(node, dn)) != NULL;) {
struct pci_dn *pdn;
- u8 irq;
- int err;
- u32 *agent;
u32 *reg;
u32 *lsn;
@@ -206,11 +203,6 @@ void iSeries_pcibios_init(void)
printk(KERN_DEBUG "no subbus property!\n");
continue;
}
- agent = (u32 *)get_property(dn, "linux,agent-id", NULL);
- if (agent == NULL) {
- printk(KERN_DEBUG "no agent-id\n");
- continue;
- }
lsn = (u32 *)get_property(dn,
"linux,logical-slot-number", NULL);
if (lsn == NULL) {
@@ -218,21 +210,6 @@ void iSeries_pcibios_init(void)
continue;
}
- irq = iSeries_allocate_IRQ(bus, 0, *busp);
- err = HvCallXm_connectBusUnit(bus, *busp, *agent, irq);
- if (err) {
- pci_Log_Error("Connect Bus Unit",
- bus, *busp, *agent, err);
- continue;
- }
- err = HvCallPci_configStore8(bus, *busp, *agent,
- PCI_INTERRUPT_LINE, irq);
- if (err) {
- pci_Log_Error("PciCfgStore Irq Failed!",
- bus, *busp, *agent, err);
- continue;
- }
-
pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
if (pdn == NULL)
return;
@@ -241,7 +218,6 @@ void iSeries_pcibios_init(void)
pdn->busno = bus;
pdn->devfn = (reg[0] >> 8) & 0xff;
pdn->bussubno = *busp;
- pdn->Irq = irq;
pdn->LogicalSlot = *lsn;
}
}
@@ -266,6 +242,34 @@ void __init iSeries_pci_final_fixup(void
pdev->bus->number, pdev->devfn, node);
if (node != NULL) {
+ struct pci_dn *pdn = PCI_DN(node);
+ u32 *agent;
+
+ agent = (u32 *)get_property(node, "linux,agent-id",
+ NULL);
+ if ((pdn != NULL) && (agent != NULL)) {
+ u8 irq = iSeries_allocate_IRQ(pdn->busno, 0,
+ pdn->bussubno);
+ int err;
+
+ err = HvCallXm_connectBusUnit(pdn->busno, pdn->bussubno,
+ *agent, irq);
+ if (err)
+ pci_Log_Error("Connect Bus Unit",
+ pdn->busno, pdn->bussubno, *agent, err);
+ else {
+ err = HvCallPci_configStore8(pdn->busno, pdn->bussubno,
+ *agent,
+ PCI_INTERRUPT_LINE,
+ irq);
+ if (err)
+ pci_Log_Error("PciCfgStore Irq Failed!",
+ pdn->busno, pdn->bussubno, *agent, err);
+ }
+ if (!err)
+ pdev->irq = irq;
+ }
+
++DeviceCount;
pdev->sysdata = (void *)node;
PCI_DN(node)->pcidev = pdev;
@@ -275,7 +279,6 @@ void __init iSeries_pci_final_fixup(void
} else
printk("PCI: Device Tree not found for 0x%016lX\n",
(unsigned long)pdev);
- pdev->irq = PCI_DN(node)->Irq;
}
iSeries_activate_IRQs();
mf_display_src(0xC9000200);
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
index 59794b4..09079e4 100644
--- a/include/asm-powerpc/pci-bridge.h
+++ b/include/asm-powerpc/pci-bridge.h
@@ -79,7 +79,6 @@ #endif
struct pci_dev *pcidev; /* back-pointer to the pci device */
struct device_node *node; /* back-pointer to the device_node */
#ifdef CONFIG_PPC_ISERIES
- int Irq; /* Assigned IRQ */
int Flags; /* Possible flags(disable/bist)*/
u8 LogicalSlot; /* Hv Slot Index for Tces */
#endif
--
1.3.1.ge923
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 06/14] powerpc: remove LogicalSlot from pci_dn
2006-05-19 6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
` (3 preceding siblings ...)
2006-05-19 6:50 ` [PATCH 05/14] powerpc: remove Irq from pci_dn Stephen Rothwell
@ 2006-05-19 6:51 ` Stephen Rothwell
2006-05-19 6:53 ` [PATCH 07/14] powerpc: iSeries PCI devices can now have a devpsec attribute Stephen Rothwell
` (7 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19 6:51 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
As we now store enough information in the device_node.
Also the Flags field was not used either, do remove that.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/platforms/iseries/iommu.c | 5 ++++-
arch/powerpc/platforms/iseries/pci.c | 8 --------
include/asm-powerpc/pci-bridge.h | 4 ----
3 files changed, 4 insertions(+), 13 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
bf52061e7db75eb167e5f7749d706614de5bcc81
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index 75a5a1e..a992f6a 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -162,10 +162,13 @@ void iommu_devnode_init_iSeries(struct d
{
struct iommu_table *tbl;
struct pci_dn *pdn = PCI_DN(dn);
+ u32 *lsn = (u32 *)get_property(dn, "linux,logical-slot-number", NULL);
+
+ BUG_ON(lsn == NULL);
tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
- iommu_table_getparms_iSeries(pdn->busno, pdn->LogicalSlot, 0, tbl);
+ iommu_table_getparms_iSeries(pdn->busno, *lsn, 0, tbl);
/* Look for existing tce table */
pdn->iommu_table = iommu_table_find(tbl);
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index edaafbb..86a8698 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -191,7 +191,6 @@ void iSeries_pcibios_init(void)
for (dn = NULL; (dn = of_get_next_child(node, dn)) != NULL;) {
struct pci_dn *pdn;
u32 *reg;
- u32 *lsn;
reg = (u32 *)get_property(dn, "reg", NULL);
if (reg == NULL) {
@@ -203,12 +202,6 @@ void iSeries_pcibios_init(void)
printk(KERN_DEBUG "no subbus property!\n");
continue;
}
- lsn = (u32 *)get_property(dn,
- "linux,logical-slot-number", NULL);
- if (lsn == NULL) {
- printk(KERN_DEBUG "no logical-slot-number\n");
- continue;
- }
pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
if (pdn == NULL)
@@ -218,7 +211,6 @@ void iSeries_pcibios_init(void)
pdn->busno = bus;
pdn->devfn = (reg[0] >> 8) & 0xff;
pdn->bussubno = *busp;
- pdn->LogicalSlot = *lsn;
}
}
}
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
index 09079e4..84a3075 100644
--- a/include/asm-powerpc/pci-bridge.h
+++ b/include/asm-powerpc/pci-bridge.h
@@ -78,10 +78,6 @@ #endif
struct iommu_table *iommu_table; /* for phb's or bridges */
struct pci_dev *pcidev; /* back-pointer to the pci device */
struct device_node *node; /* back-pointer to the device_node */
-#ifdef CONFIG_PPC_ISERIES
- int Flags; /* Possible flags(disable/bist)*/
- u8 LogicalSlot; /* Hv Slot Index for Tces */
-#endif
u32 config_space[16]; /* saved PCI config space */
};
--
1.3.1.ge923
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 07/14] powerpc: iSeries PCI devices can now have a devpsec attribute
2006-05-19 6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
` (4 preceding siblings ...)
2006-05-19 6:51 ` [PATCH 06/14] powerpc: remove LogicalSlot " Stephen Rothwell
@ 2006-05-19 6:53 ` Stephen Rothwell
2006-05-19 6:54 ` [PATCH 08/14] powerpc: clean up iSeries PCI probe Stephen Rothwell
` (6 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19 6:53 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/kernel/pci_64.c | 7 ++-----
1 files changed, 2 insertions(+), 5 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
bfe21d083414576fccd84ead574adffea99968c1
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index e1b3b3e..30a4e6a 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -886,8 +886,8 @@ int pci_mmap_page_range(struct pci_dev *
return ret;
}
-#ifdef CONFIG_PPC_MULTIPLATFORM
-static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t pci_show_devspec(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct pci_dev *pdev;
struct device_node *np;
@@ -899,13 +899,10 @@ static ssize_t pci_show_devspec(struct d
return sprintf(buf, "%s", np->full_name);
}
static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-#endif /* CONFIG_PPC_MULTIPLATFORM */
void pcibios_add_platform_entries(struct pci_dev *pdev)
{
-#ifdef CONFIG_PPC_MULTIPLATFORM
device_create_file(&pdev->dev, &dev_attr_devspec);
-#endif /* CONFIG_PPC_MULTIPLATFORM */
}
#ifdef CONFIG_PPC_MULTIPLATFORM
--
1.3.1.ge923
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 08/14] powerpc: clean up iSeries PCI probe
2006-05-19 6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
` (5 preceding siblings ...)
2006-05-19 6:53 ` [PATCH 07/14] powerpc: iSeries PCI devices can now have a devpsec attribute Stephen Rothwell
@ 2006-05-19 6:54 ` Stephen Rothwell
2006-05-19 6:55 ` [PATCH 09/14] powerpc: make iSeries flat device tree stuff static Stephen Rothwell
` (5 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19 6:54 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
Only scan the host bridges and then use the existing pci_devs_phb_init()
routine.
Also fix typo in setup of reg property.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/kernel/pci_dn.c | 6 +++++
arch/powerpc/platforms/iseries/pci.c | 42 +++++++++++---------------------
arch/powerpc/platforms/iseries/setup.c | 2 +-
3 files changed, 21 insertions(+), 29 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
979e33e7df3519bb4bbc550ad7e52b5ad2b30221
diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
index 12c4c9e..1c18953 100644
--- a/arch/powerpc/kernel/pci_dn.c
+++ b/arch/powerpc/kernel/pci_dn.c
@@ -31,6 +31,7 @@ #include <asm/prom.h>
#include <asm/pci-bridge.h>
#include <asm/pSeries_reconfig.h>
#include <asm/ppc-pci.h>
+#include <asm/firmware.h>
/*
* Traverse_func that inits the PCI fields of the device node.
@@ -59,6 +60,11 @@ static void * __devinit update_dn_pci_in
pdn->busno = (regs[0] >> 16) & 0xff;
pdn->devfn = (regs[0] >> 8) & 0xff;
}
+ if (firmware_has_feature(FW_FEATURE_ISERIES)) {
+ u32 *busp = (u32 *)get_property(dn, "linux,subbus", NULL);
+ if (busp)
+ pdn->bussubno = *busp;
+ }
pdn->pci_ext_config_space = (type && *type == 1);
return NULL;
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 86a8698..35bcc98 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -166,13 +166,21 @@ static void pci_Log_Error(char *Error_Te
void iSeries_pcibios_init(void)
{
struct pci_controller *phb;
- struct device_node *node;
- struct device_node *dn;
+ struct device_node *root = of_find_node_by_path("/");
+ struct device_node *node = NULL;
- for_each_node_by_type(node, "pci") {
+ if (root == NULL) {
+ printk(KERN_CRIT "iSeries_pcibios_init: can't find root "
+ "of device tree\n");
+ return;
+ }
+ while ((node = of_get_next_child(root, node)) != NULL) {
HvBusNumber bus;
u32 *busp;
+ if ((node->type == NULL) || (strcmp(node->type, "pci") != 0))
+ continue;
+
busp = (u32 *)get_property(node, "bus-range", NULL);
if (busp == NULL)
continue;
@@ -186,33 +194,11 @@ void iSeries_pcibios_init(void)
phb->first_busno = bus;
phb->last_busno = bus;
phb->ops = &iSeries_pci_ops;
+ }
- /* Find and connect the devices. */
- for (dn = NULL; (dn = of_get_next_child(node, dn)) != NULL;) {
- struct pci_dn *pdn;
- u32 *reg;
-
- reg = (u32 *)get_property(dn, "reg", NULL);
- if (reg == NULL) {
- printk(KERN_DEBUG "no reg property!\n");
- continue;
- }
- busp = (u32 *)get_property(dn, "linux,subbus", NULL);
- if (busp == NULL) {
- printk(KERN_DEBUG "no subbus property!\n");
- continue;
- }
+ of_node_put(root);
- pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
- if (pdn == NULL)
- return;
- dn->data = pdn;
- pdn->node = dn;
- pdn->busno = bus;
- pdn->devfn = (reg[0] >> 8) & 0xff;
- pdn->bussubno = *busp;
- }
- }
+ pci_devs_phb_init();
}
/*
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index d83f5ed..0f49412 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -1073,7 +1073,7 @@ static void scan_bridge_slot(struct iser
snprintf(buf, sizeof(buf), "pci@%x,%d",
PCI_SLOT(devfn), function);
dt_start_node(dt, buf);
- reg[0] = (bus << 18) | (devfn << 8);
+ reg[0] = (bus << 16) | (devfn << 8);
reg[1] = 0;
reg[2] = 0;
reg[3] = 0;
--
1.3.1.ge923
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 09/14] powerpc: make iSeries flat device tree stuff static
2006-05-19 6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
` (6 preceding siblings ...)
2006-05-19 6:54 ` [PATCH 08/14] powerpc: clean up iSeries PCI probe Stephen Rothwell
@ 2006-05-19 6:55 ` Stephen Rothwell
2006-05-19 6:58 ` [PATCH 10/14] powerpc: give iSeries device tree nodes better names Stephen Rothwell
` (4 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19 6:55 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/platforms/iseries/setup.c | 40 ++++++++++++++++++--------------
1 files changed, 22 insertions(+), 18 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
ef5523ad5d01ff256b792ef5a44719c4a56771d9
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 0f49412..9586414 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -723,9 +723,9 @@ struct iseries_flat_dt {
struct blob strings;
};
-struct iseries_flat_dt iseries_dt;
+static struct iseries_flat_dt iseries_dt;
-void dt_init(struct iseries_flat_dt *dt)
+static void dt_init(struct iseries_flat_dt *dt)
{
dt->header.off_mem_rsvmap =
offsetof(struct iseries_flat_dt, reserve_map);
@@ -748,7 +748,7 @@ void dt_init(struct iseries_flat_dt *dt)
dt->reserve_map[1] = 0;
}
-void dt_check_blob(struct blob *b)
+static void dt_check_blob(struct blob *b)
{
if (b->next >= (unsigned long)&b->next) {
DBG("Ran out of space in flat device tree blob!\n");
@@ -756,7 +756,7 @@ void dt_check_blob(struct blob *b)
}
}
-void dt_push_u32(struct iseries_flat_dt *dt, u32 value)
+static void dt_push_u32(struct iseries_flat_dt *dt, u32 value)
{
*((u32*)dt->dt.next) = value;
dt->dt.next += sizeof(u32);
@@ -764,15 +764,17 @@ void dt_push_u32(struct iseries_flat_dt
dt_check_blob(&dt->dt);
}
-void dt_push_u64(struct iseries_flat_dt *dt, u64 value)
+#ifdef notyet
+static void dt_push_u64(struct iseries_flat_dt *dt, u64 value)
{
*((u64*)dt->dt.next) = value;
dt->dt.next += sizeof(u64);
dt_check_blob(&dt->dt);
}
+#endif
-unsigned long dt_push_bytes(struct blob *blob, char *data, int len)
+static unsigned long dt_push_bytes(struct blob *blob, char *data, int len)
{
unsigned long start = blob->next - (unsigned long)blob->data;
@@ -784,7 +786,7 @@ unsigned long dt_push_bytes(struct blob
return start;
}
-void dt_start_node(struct iseries_flat_dt *dt, char *name)
+static void dt_start_node(struct iseries_flat_dt *dt, char *name)
{
dt_push_u32(dt, OF_DT_BEGIN_NODE);
dt_push_bytes(&dt->dt, name, strlen(name) + 1);
@@ -792,7 +794,7 @@ void dt_start_node(struct iseries_flat_d
#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
-void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len)
+static void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len)
{
unsigned long offset;
@@ -811,37 +813,39 @@ void dt_prop(struct iseries_flat_dt *dt,
dt_push_bytes(&dt->dt, data, len);
}
-void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data)
+static void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data)
{
dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
}
-void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
+static void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
{
dt_prop(dt, name, (char *)&data, sizeof(u32));
}
-void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
+static void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
{
dt_prop(dt, name, (char *)&data, sizeof(u64));
}
-void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n)
+static void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n)
{
dt_prop(dt, name, (char *)data, sizeof(u64) * n);
}
-void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n)
+static void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n)
{
dt_prop(dt, name, (char *)data, sizeof(u32) * n);
}
-void dt_prop_empty(struct iseries_flat_dt *dt, char *name)
+#ifdef notyet
+static void dt_prop_empty(struct iseries_flat_dt *dt, char *name)
{
dt_prop(dt, name, NULL, 0);
}
+#endif
-void dt_cpus(struct iseries_flat_dt *dt)
+static void dt_cpus(struct iseries_flat_dt *dt)
{
unsigned char buf[32];
unsigned char *p;
@@ -895,7 +899,7 @@ void dt_cpus(struct iseries_flat_dt *dt)
dt_end_node(dt);
}
-void dt_model(struct iseries_flat_dt *dt)
+static void dt_model(struct iseries_flat_dt *dt)
{
char buf[16] = "IBM,";
@@ -913,7 +917,7 @@ void dt_model(struct iseries_flat_dt *dt
dt_prop_str(dt, "compatible", "IBM,iSeries");
}
-void dt_vdevices(struct iseries_flat_dt *dt)
+static void dt_vdevices(struct iseries_flat_dt *dt)
{
u32 reg = 0;
HvLpIndexMap vlan_map;
@@ -1203,7 +1207,7 @@ static void dt_pci_devices(struct iserie
}
}
-void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
+static void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
{
u64 tmp[2];
--
1.3.1.ge923
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 10/14] powerpc: give iSeries device tree nodes better names
2006-05-19 6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
` (7 preceding siblings ...)
2006-05-19 6:55 ` [PATCH 09/14] powerpc: make iSeries flat device tree stuff static Stephen Rothwell
@ 2006-05-19 6:58 ` Stephen Rothwell
2006-05-19 7:00 ` [PATCH 11/14] powerpc: split device tree stuff out of iseries/setup.c Stephen Rothwell
` (3 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19 6:58 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
Use the PCI class code to choose a name for the PCI device nodes and
to guess a device_type. Failing that, base the name on the vendor and
device ids as specified in the spec.
Mark just about everything __init{data}.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/platforms/iseries/setup.c | 95 ++++++++++++++++++++++----------
1 files changed, 66 insertions(+), 29 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
753e3e7ff975a03dbcc5a761041f0f855215e7c5
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 9586414..5661bd0 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -725,7 +725,7 @@ struct iseries_flat_dt {
static struct iseries_flat_dt iseries_dt;
-static void dt_init(struct iseries_flat_dt *dt)
+static void __init dt_init(struct iseries_flat_dt *dt)
{
dt->header.off_mem_rsvmap =
offsetof(struct iseries_flat_dt, reserve_map);
@@ -748,7 +748,7 @@ static void dt_init(struct iseries_flat_
dt->reserve_map[1] = 0;
}
-static void dt_check_blob(struct blob *b)
+static void __init dt_check_blob(struct blob *b)
{
if (b->next >= (unsigned long)&b->next) {
DBG("Ran out of space in flat device tree blob!\n");
@@ -756,7 +756,7 @@ static void dt_check_blob(struct blob *b
}
}
-static void dt_push_u32(struct iseries_flat_dt *dt, u32 value)
+static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value)
{
*((u32*)dt->dt.next) = value;
dt->dt.next += sizeof(u32);
@@ -765,7 +765,7 @@ static void dt_push_u32(struct iseries_f
}
#ifdef notyet
-static void dt_push_u64(struct iseries_flat_dt *dt, u64 value)
+static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value)
{
*((u64*)dt->dt.next) = value;
dt->dt.next += sizeof(u64);
@@ -774,7 +774,7 @@ static void dt_push_u64(struct iseries_f
}
#endif
-static unsigned long dt_push_bytes(struct blob *blob, char *data, int len)
+static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len)
{
unsigned long start = blob->next - (unsigned long)blob->data;
@@ -786,7 +786,7 @@ static unsigned long dt_push_bytes(struc
return start;
}
-static void dt_start_node(struct iseries_flat_dt *dt, char *name)
+static void __init dt_start_node(struct iseries_flat_dt *dt, char *name)
{
dt_push_u32(dt, OF_DT_BEGIN_NODE);
dt_push_bytes(&dt->dt, name, strlen(name) + 1);
@@ -794,7 +794,8 @@ static void dt_start_node(struct iseries
#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
-static void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len)
+static void __init dt_prop(struct iseries_flat_dt *dt, char *name,
+ char *data, int len)
{
unsigned long offset;
@@ -813,39 +814,42 @@ static void dt_prop(struct iseries_flat_
dt_push_bytes(&dt->dt, data, len);
}
-static void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data)
+static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name,
+ char *data)
{
dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
}
-static void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
+static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
{
dt_prop(dt, name, (char *)&data, sizeof(u32));
}
-static void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
+static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
{
dt_prop(dt, name, (char *)&data, sizeof(u64));
}
-static void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n)
+static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name,
+ u64 *data, int n)
{
dt_prop(dt, name, (char *)data, sizeof(u64) * n);
}
-static void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n)
+static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name,
+ u32 *data, int n)
{
dt_prop(dt, name, (char *)data, sizeof(u32) * n);
}
#ifdef notyet
-static void dt_prop_empty(struct iseries_flat_dt *dt, char *name)
+static void __init dt_prop_empty(struct iseries_flat_dt *dt, char *name)
{
dt_prop(dt, name, NULL, 0);
}
#endif
-static void dt_cpus(struct iseries_flat_dt *dt)
+static void __init dt_cpus(struct iseries_flat_dt *dt)
{
unsigned char buf[32];
unsigned char *p;
@@ -899,7 +903,7 @@ static void dt_cpus(struct iseries_flat_
dt_end_node(dt);
}
-static void dt_model(struct iseries_flat_dt *dt)
+static void __init dt_model(struct iseries_flat_dt *dt)
{
char buf[16] = "IBM,";
@@ -917,7 +921,7 @@ static void dt_model(struct iseries_flat
dt_prop_str(dt, "compatible", "IBM,iSeries");
}
-static void dt_vdevices(struct iseries_flat_dt *dt)
+static void __init dt_vdevices(struct iseries_flat_dt *dt)
{
u32 reg = 0;
HvLpIndexMap vlan_map;
@@ -1006,11 +1010,32 @@ static void dt_vdevices(struct iseries_f
dt_end_node(dt);
}
+struct pci_class_name {
+ u16 code;
+ char *name;
+ char *type;
+};
+
+static struct pci_class_name __initdata pci_class_name[] = {
+ { PCI_CLASS_NETWORK_ETHERNET, "ethernet", "network" },
+};
+
+static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code)
+{
+ struct pci_class_name *cp;
+
+ for (cp = pci_class_name;
+ cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++)
+ if (cp->code == class_code)
+ return cp;
+ return NULL;
+}
+
/*
* This assumes that the node slot is always on the primary bus!
*/
-static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus,
- struct HvCallPci_BridgeInfo *bridge_info)
+static void __init scan_bridge_slot(struct iseries_flat_dt *dt,
+ HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info)
{
HvSubBusNumber sub_bus = bridge_info->subBusNumber;
u16 vendor_id;
@@ -1022,14 +1047,14 @@ static void scan_bridge_slot(struct iser
int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus);
int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus);
HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function);
+ u8 devfn;
+ struct pci_class_name *cp;
/*
* Connect all functions of any device found.
*/
for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) {
for (function = 0; function < 8; function++) {
- u8 devfn;
-
HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel,
function);
err = HvCallXm_connectBusUnit(bus, sub_bus,
@@ -1070,12 +1095,20 @@ static void scan_bridge_slot(struct iser
devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel),
function);
- if (function == 0)
- snprintf(buf, sizeof(buf), "pci@%x",
- PCI_SLOT(devfn));
+ cp = dt_find_pci_class_name(class_id >> 16);
+ if (cp && cp->name)
+ strncpy(buf, cp->name, sizeof(buf) - 1);
else
- snprintf(buf, sizeof(buf), "pci@%x,%d",
- PCI_SLOT(devfn), function);
+ snprintf(buf, sizeof(buf), "pci%x,%x",
+ vendor_id, device_id);
+ buf[sizeof(buf) - 1] = '\0';
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+ "@%x", PCI_SLOT(devfn));
+ buf[sizeof(buf) - 1] = '\0';
+ if (function != 0)
+ snprintf(buf + strlen(buf),
+ sizeof(buf) - strlen(buf),
+ ",%x", function);
dt_start_node(dt, buf);
reg[0] = (bus << 16) | (devfn << 8);
reg[1] = 0;
@@ -1083,6 +1116,9 @@ static void scan_bridge_slot(struct iser
reg[3] = 0;
reg[4] = 0;
dt_prop_u32_list(dt, "reg", reg, 5);
+ if (cp && (cp->type || cp->name))
+ dt_prop_str(dt, "device_type",
+ cp->type ? cp->type : cp->name);
dt_prop_u32(dt, "vendor-id", vendor_id);
dt_prop_u32(dt, "device-id", device_id);
dt_prop_u32(dt, "class-code", class_id >> 8);
@@ -1097,7 +1133,7 @@ static void scan_bridge_slot(struct iser
}
}
-static void scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus,
+static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus,
HvSubBusNumber sub_bus, int id_sel)
{
struct HvCallPci_BridgeInfo bridge_info;
@@ -1139,7 +1175,7 @@ static void scan_bridge(struct iseries_f
}
}
-static void scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus)
+static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus)
{
struct HvCallPci_DeviceInfo dev_info;
const HvSubBusNumber sub_bus = 0; /* EADs is always 0. */
@@ -1171,7 +1207,7 @@ static void scan_phb(struct iseries_flat
}
}
-static void dt_pci_devices(struct iseries_flat_dt *dt)
+static void __init dt_pci_devices(struct iseries_flat_dt *dt)
{
HvBusNumber bus;
char buf[32];
@@ -1207,7 +1243,8 @@ static void dt_pci_devices(struct iserie
}
}
-static void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
+static void __init build_flat_dt(struct iseries_flat_dt *dt,
+ unsigned long phys_mem_size)
{
u64 tmp[2];
--
1.3.1.ge923
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 11/14] powerpc: split device tree stuff out of iseries/setup.c
2006-05-19 6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
` (8 preceding siblings ...)
2006-05-19 6:58 ` [PATCH 10/14] powerpc: give iSeries device tree nodes better names Stephen Rothwell
@ 2006-05-19 7:00 ` Stephen Rothwell
2006-05-19 7:04 ` [PATCH 13/14] powerpc: make iSeries flattened device tree dynamic - part 2 Stephen Rothwell
` (2 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19 7:00 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/platforms/iseries/Makefile | 2
arch/powerpc/platforms/iseries/dt.c | 618 +++++++++++++++++++++++++++++++
arch/powerpc/platforms/iseries/setup.c | 578 -----------------------------
arch/powerpc/platforms/iseries/setup.h | 2
4 files changed, 622 insertions(+), 578 deletions(-)
create mode 100644 arch/powerpc/platforms/iseries/dt.c
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
5909be4784e723a8a0444a556801cb320a4ddffc
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
index 7e67a20..3230621 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -1,6 +1,6 @@
EXTRA_CFLAGS += -mno-minimal-toc
-obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \
+obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt.o mf.o lpevents.o \
hvcall.o proc.o htab.o iommu.o misc.o irq.o
obj-$(CONFIG_PCI) += pci.o vpdinfo.o
obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
new file mode 100644
index 0000000..93d4233
--- /dev/null
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -0,0 +1,618 @@
+/*
+ * Copyright (c) 2005-2006 Michael Ellerman, IBM Corporation
+ *
+ * Description:
+ * This file contains all the routines to build a flattened device
+ * tree for a legacy iSeries machine.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#undef DEBUG
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/pci_ids.h>
+#include <linux/threads.h>
+#include <linux/bitops.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/if_ether.h> /* ETH_ALEN */
+
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/lppaca.h>
+#include <asm/page.h>
+#include <asm/cputable.h>
+#include <asm/abs_addr.h>
+#include <asm/iseries/hv_types.h>
+#include <asm/iseries/hv_lp_config.h>
+#include <asm/iseries/hv_call_xm.h>
+#include <asm/iseries/it_exp_vpd_panel.h>
+#include <asm/udbg.h>
+
+#include "processor_vpd.h"
+#include "call_hpt.h"
+#include "call_pci.h"
+#include "pci.h"
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+struct blob {
+ unsigned char data[PAGE_SIZE * 2];
+ unsigned long next;
+};
+
+struct iseries_flat_dt {
+ struct boot_param_header header;
+ u64 reserve_map[2];
+ struct blob dt;
+ struct blob strings;
+};
+
+static struct iseries_flat_dt iseries_dt;
+
+static void __init dt_init(struct iseries_flat_dt *dt)
+{
+ dt->header.off_mem_rsvmap =
+ offsetof(struct iseries_flat_dt, reserve_map);
+ dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt);
+ dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings);
+ dt->header.totalsize = sizeof(struct iseries_flat_dt);
+ dt->header.dt_strings_size = sizeof(struct blob);
+
+ /* There is no notion of hardware cpu id on iSeries */
+ dt->header.boot_cpuid_phys = smp_processor_id();
+
+ dt->dt.next = (unsigned long)&dt->dt.data;
+ dt->strings.next = (unsigned long)&dt->strings.data;
+
+ dt->header.magic = OF_DT_HEADER;
+ dt->header.version = 0x10;
+ dt->header.last_comp_version = 0x10;
+
+ dt->reserve_map[0] = 0;
+ dt->reserve_map[1] = 0;
+}
+
+static void __init dt_check_blob(struct blob *b)
+{
+ if (b->next >= (unsigned long)&b->next) {
+ DBG("Ran out of space in flat device tree blob!\n");
+ BUG();
+ }
+}
+
+static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value)
+{
+ *((u32*)dt->dt.next) = value;
+ dt->dt.next += sizeof(u32);
+
+ dt_check_blob(&dt->dt);
+}
+
+#ifdef notyet
+static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value)
+{
+ *((u64*)dt->dt.next) = value;
+ dt->dt.next += sizeof(u64);
+
+ dt_check_blob(&dt->dt);
+}
+#endif
+
+static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len)
+{
+ unsigned long start = blob->next - (unsigned long)blob->data;
+
+ memcpy((char *)blob->next, data, len);
+ blob->next = _ALIGN(blob->next + len, 4);
+
+ dt_check_blob(blob);
+
+ return start;
+}
+
+static void __init dt_start_node(struct iseries_flat_dt *dt, char *name)
+{
+ dt_push_u32(dt, OF_DT_BEGIN_NODE);
+ dt_push_bytes(&dt->dt, name, strlen(name) + 1);
+}
+
+#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
+
+static void __init dt_prop(struct iseries_flat_dt *dt, char *name,
+ char *data, int len)
+{
+ unsigned long offset;
+
+ dt_push_u32(dt, OF_DT_PROP);
+
+ /* Length of the data */
+ dt_push_u32(dt, len);
+
+ /* Put the property name in the string blob. */
+ offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1);
+
+ /* The offset of the properties name in the string blob. */
+ dt_push_u32(dt, (u32)offset);
+
+ /* The actual data. */
+ dt_push_bytes(&dt->dt, data, len);
+}
+
+static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name,
+ char *data)
+{
+ dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
+}
+
+static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
+{
+ dt_prop(dt, name, (char *)&data, sizeof(u32));
+}
+
+static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
+{
+ dt_prop(dt, name, (char *)&data, sizeof(u64));
+}
+
+static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name,
+ u64 *data, int n)
+{
+ dt_prop(dt, name, (char *)data, sizeof(u64) * n);
+}
+
+static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name,
+ u32 *data, int n)
+{
+ dt_prop(dt, name, (char *)data, sizeof(u32) * n);
+}
+
+#ifdef notyet
+static void __init dt_prop_empty(struct iseries_flat_dt *dt, char *name)
+{
+ dt_prop(dt, name, NULL, 0);
+}
+#endif
+
+static void __init dt_cpus(struct iseries_flat_dt *dt)
+{
+ unsigned char buf[32];
+ unsigned char *p;
+ unsigned int i, index;
+ struct IoHriProcessorVpd *d;
+ u32 pft_size[2];
+
+ /* yuck */
+ snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name);
+ p = strchr(buf, ' ');
+ if (!p) p = buf + strlen(buf);
+
+ dt_start_node(dt, "cpus");
+ dt_prop_u32(dt, "#address-cells", 1);
+ dt_prop_u32(dt, "#size-cells", 0);
+
+ pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA */
+ pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);
+
+ for (i = 0; i < NR_CPUS; i++) {
+ if (lppaca[i].dyn_proc_status >= 2)
+ continue;
+
+ snprintf(p, 32 - (p - buf), "@%d", i);
+ dt_start_node(dt, buf);
+
+ dt_prop_str(dt, "device_type", "cpu");
+
+ index = lppaca[i].dyn_hv_phys_proc_index;
+ d = &xIoHriProcessorVpd[index];
+
+ dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
+ dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize);
+
+ dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024);
+ dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize);
+
+ /* magic conversions to Hz copied from old code */
+ dt_prop_u32(dt, "clock-frequency",
+ ((1UL << 34) * 1000000) / d->xProcFreq);
+ dt_prop_u32(dt, "timebase-frequency",
+ ((1UL << 32) * 1000000) / d->xTimeBaseFreq);
+
+ dt_prop_u32(dt, "reg", i);
+
+ dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2);
+
+ dt_end_node(dt);
+ }
+
+ dt_end_node(dt);
+}
+
+static void __init dt_model(struct iseries_flat_dt *dt)
+{
+ char buf[16] = "IBM,";
+
+ /* "IBM," + mfgId[2:3] + systemSerial[1:5] */
+ strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2);
+ strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5);
+ buf[11] = '\0';
+ dt_prop_str(dt, "system-id", buf);
+
+ /* "IBM," + machineType[0:4] */
+ strne2a(buf + 4, xItExtVpdPanel.machineType, 4);
+ buf[8] = '\0';
+ dt_prop_str(dt, "model", buf);
+
+ dt_prop_str(dt, "compatible", "IBM,iSeries");
+}
+
+static void __init dt_vdevices(struct iseries_flat_dt *dt)
+{
+ u32 reg = 0;
+ HvLpIndexMap vlan_map;
+ int i;
+ char buf[32];
+
+ dt_start_node(dt, "vdevice");
+ dt_prop_str(dt, "device_type", "vdevice");
+ dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice");
+ dt_prop_u32(dt, "#address-cells", 1);
+ dt_prop_u32(dt, "#size-cells", 0);
+
+ snprintf(buf, sizeof(buf), "vty@%08x", reg);
+ dt_start_node(dt, buf);
+ dt_prop_str(dt, "device_type", "serial");
+ dt_prop_u32(dt, "reg", reg);
+ dt_end_node(dt);
+ reg++;
+
+ snprintf(buf, sizeof(buf), "v-scsi@%08x", reg);
+ dt_start_node(dt, buf);
+ dt_prop_str(dt, "device_type", "vscsi");
+ dt_prop_str(dt, "compatible", "IBM,v-scsi");
+ dt_prop_u32(dt, "reg", reg);
+ dt_end_node(dt);
+ reg++;
+
+ vlan_map = HvLpConfig_getVirtualLanIndexMap();
+ for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
+ unsigned char mac_addr[ETH_ALEN];
+
+ if ((vlan_map & (0x8000 >> i)) == 0)
+ continue;
+ snprintf(buf, 32, "l-lan@%08x", reg + i);
+ dt_start_node(dt, buf);
+ dt_prop_str(dt, "device_type", "network");
+ dt_prop_str(dt, "compatible", "IBM,iSeries-l-lan");
+ dt_prop_u32(dt, "reg", reg + i);
+ dt_prop_u32(dt, "linux,unit_address", i);
+
+ mac_addr[0] = 0x02;
+ mac_addr[1] = 0x01;
+ mac_addr[2] = 0xff;
+ mac_addr[3] = i;
+ mac_addr[4] = 0xff;
+ mac_addr[5] = HvLpConfig_getLpIndex_outline();
+ dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN);
+ dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN);
+ dt_prop_u32(dt, "max-frame-size", 9000);
+ dt_prop_u32(dt, "address-bits", 48);
+
+ dt_end_node(dt);
+ }
+ reg += HVMAXARCHITECTEDVIRTUALLANS;
+
+ for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) {
+ snprintf(buf, 32, "viodasd@%08x", reg + i);
+ dt_start_node(dt, buf);
+ dt_prop_str(dt, "device_type", "block");
+ dt_prop_str(dt, "compatible", "IBM,iSeries-viodasd");
+ dt_prop_u32(dt, "reg", reg + i);
+ dt_prop_u32(dt, "linux,unit_address", i);
+ dt_end_node(dt);
+ }
+ reg += HVMAXARCHITECTEDVIRTUALDISKS;
+ for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) {
+ snprintf(buf, 32, "viocd@%08x", reg + i);
+ dt_start_node(dt, buf);
+ dt_prop_str(dt, "device_type", "block");
+ dt_prop_str(dt, "compatible", "IBM,iSeries-viocd");
+ dt_prop_u32(dt, "reg", reg + i);
+ dt_prop_u32(dt, "linux,unit_address", i);
+ dt_end_node(dt);
+ }
+ reg += HVMAXARCHITECTEDVIRTUALCDROMS;
+ for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) {
+ snprintf(buf, 32, "viotape@%08x", reg + i);
+ dt_start_node(dt, buf);
+ dt_prop_str(dt, "device_type", "byte");
+ dt_prop_str(dt, "compatible", "IBM,iSeries-viotape");
+ dt_prop_u32(dt, "reg", reg + i);
+ dt_prop_u32(dt, "linux,unit_address", i);
+ dt_end_node(dt);
+ }
+
+ dt_end_node(dt);
+}
+
+struct pci_class_name {
+ u16 code;
+ char *name;
+ char *type;
+};
+
+static struct pci_class_name __initdata pci_class_name[] = {
+ { PCI_CLASS_NETWORK_ETHERNET, "ethernet", "network" },
+};
+
+static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code)
+{
+ struct pci_class_name *cp;
+
+ for (cp = pci_class_name;
+ cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++)
+ if (cp->code == class_code)
+ return cp;
+ return NULL;
+}
+
+/*
+ * This assumes that the node slot is always on the primary bus!
+ */
+static void __init scan_bridge_slot(struct iseries_flat_dt *dt,
+ HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info)
+{
+ HvSubBusNumber sub_bus = bridge_info->subBusNumber;
+ u16 vendor_id;
+ u16 device_id;
+ u32 class_id;
+ int err;
+ char buf[32];
+ u32 reg[5];
+ int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus);
+ int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus);
+ HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function);
+ u8 devfn;
+ struct pci_class_name *cp;
+
+ /*
+ * Connect all functions of any device found.
+ */
+ for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) {
+ for (function = 0; function < 8; function++) {
+ HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel,
+ function);
+ err = HvCallXm_connectBusUnit(bus, sub_bus,
+ agent_id, 0);
+ if (err) {
+ if (err != 0x302)
+ printk(KERN_DEBUG
+ "connectBusUnit(%x, %x, %x) "
+ "== %x\n",
+ bus, sub_bus, agent_id, err);
+ continue;
+ }
+
+ err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
+ PCI_VENDOR_ID, &vendor_id);
+ if (err) {
+ printk(KERN_DEBUG
+ "ReadVendor(%x, %x, %x) == %x\n",
+ bus, sub_bus, agent_id, err);
+ continue;
+ }
+ err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
+ PCI_DEVICE_ID, &device_id);
+ if (err) {
+ printk(KERN_DEBUG
+ "ReadDevice(%x, %x, %x) == %x\n",
+ bus, sub_bus, agent_id, err);
+ continue;
+ }
+ err = HvCallPci_configLoad32(bus, sub_bus, agent_id,
+ PCI_CLASS_REVISION , &class_id);
+ if (err) {
+ printk(KERN_DEBUG
+ "ReadClass(%x, %x, %x) == %x\n",
+ bus, sub_bus, agent_id, err);
+ continue;
+ }
+
+ devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel),
+ function);
+ cp = dt_find_pci_class_name(class_id >> 16);
+ if (cp && cp->name)
+ strncpy(buf, cp->name, sizeof(buf) - 1);
+ else
+ snprintf(buf, sizeof(buf), "pci%x,%x",
+ vendor_id, device_id);
+ buf[sizeof(buf) - 1] = '\0';
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+ "@%x", PCI_SLOT(devfn));
+ buf[sizeof(buf) - 1] = '\0';
+ if (function != 0)
+ snprintf(buf + strlen(buf),
+ sizeof(buf) - strlen(buf),
+ ",%x", function);
+ dt_start_node(dt, buf);
+ reg[0] = (bus << 16) | (devfn << 8);
+ reg[1] = 0;
+ reg[2] = 0;
+ reg[3] = 0;
+ reg[4] = 0;
+ dt_prop_u32_list(dt, "reg", reg, 5);
+ if (cp && (cp->type || cp->name))
+ dt_prop_str(dt, "device_type",
+ cp->type ? cp->type : cp->name);
+ dt_prop_u32(dt, "vendor-id", vendor_id);
+ dt_prop_u32(dt, "device-id", device_id);
+ dt_prop_u32(dt, "class-code", class_id >> 8);
+ dt_prop_u32(dt, "revision-id", class_id & 0xff);
+ dt_prop_u32(dt, "linux,subbus", sub_bus);
+ dt_prop_u32(dt, "linux,agent-id", agent_id);
+ dt_prop_u32(dt, "linux,logical-slot-number",
+ bridge_info->logicalSlotNumber);
+ dt_end_node(dt);
+
+ }
+ }
+}
+
+static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus,
+ HvSubBusNumber sub_bus, int id_sel)
+{
+ struct HvCallPci_BridgeInfo bridge_info;
+ HvAgentId agent_id;
+ int function;
+ int ret;
+
+ /* Note: hvSubBus and irq is always be 0 at this level! */
+ for (function = 0; function < 8; ++function) {
+ agent_id = ISERIES_PCI_AGENTID(id_sel, function);
+ ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0);
+ if (ret != 0) {
+ if (ret != 0xb)
+ printk(KERN_DEBUG "connectBusUnit(%x, %x, %x) "
+ "== %x\n",
+ bus, sub_bus, agent_id, ret);
+ continue;
+ }
+ printk("found device at bus %d idsel %d func %d (AgentId %x)\n",
+ bus, id_sel, function, agent_id);
+ ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id,
+ iseries_hv_addr(&bridge_info),
+ sizeof(struct HvCallPci_BridgeInfo));
+ if (ret != 0)
+ continue;
+ printk("bridge info: type %x subbus %x "
+ "maxAgents %x maxsubbus %x logslot %x\n",
+ bridge_info.busUnitInfo.deviceType,
+ bridge_info.subBusNumber,
+ bridge_info.maxAgents,
+ bridge_info.maxSubBusNumber,
+ bridge_info.logicalSlotNumber);
+ if (bridge_info.busUnitInfo.deviceType ==
+ HvCallPci_BridgeDevice)
+ scan_bridge_slot(dt, bus, &bridge_info);
+ else
+ printk("PCI: Invalid Bridge Configuration(0x%02X)",
+ bridge_info.busUnitInfo.deviceType);
+ }
+}
+
+static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus)
+{
+ struct HvCallPci_DeviceInfo dev_info;
+ const HvSubBusNumber sub_bus = 0; /* EADs is always 0. */
+ int err;
+ int id_sel;
+ const int max_agents = 8;
+
+ /*
+ * Probe for EADs Bridges
+ */
+ for (id_sel = 1; id_sel < max_agents; ++id_sel) {
+ err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel,
+ iseries_hv_addr(&dev_info),
+ sizeof(struct HvCallPci_DeviceInfo));
+ if (err) {
+ if (err != 0x302)
+ printk(KERN_DEBUG "getDeviceInfo(%x, %x, %x) "
+ "== %x\n",
+ bus, sub_bus, id_sel, err);
+ continue;
+ }
+ if (dev_info.deviceType != HvCallPci_NodeDevice) {
+ printk(KERN_DEBUG "PCI: Invalid System Configuration"
+ "(0x%02X) for bus 0x%02x id 0x%02x.\n",
+ dev_info.deviceType, bus, id_sel);
+ continue;
+ }
+ scan_bridge(dt, bus, sub_bus, id_sel);
+ }
+}
+
+static void __init dt_pci_devices(struct iseries_flat_dt *dt)
+{
+ HvBusNumber bus;
+ char buf[32];
+ u32 buses[2];
+ int phb_num = 0;
+
+ /* Check all possible buses. */
+ for (bus = 0; bus < 256; bus++) {
+ int err = HvCallXm_testBus(bus);
+
+ if (err) {
+ /*
+ * Check for Unexpected Return code, a clue that
+ * something has gone wrong.
+ */
+ if (err != 0x0301)
+ printk(KERN_ERR "Unexpected Return on Probe"
+ "(0x%02X): 0x%04X", bus, err);
+ continue;
+ }
+ printk("bus %d appears to exist\n", bus);
+ snprintf(buf, 32, "pci@%d", phb_num);
+ dt_start_node(dt, buf);
+ dt_prop_str(dt, "device_type", "pci");
+ dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB");
+ dt_prop_u32(dt, "#address-cells", 3);
+ dt_prop_u32(dt, "#size-cells", 2);
+ buses[0] = buses[1] = bus;
+ dt_prop_u32_list(dt, "bus-range", buses, 2);
+ scan_phb(dt, bus);
+ dt_end_node(dt);
+ phb_num++;
+ }
+}
+
+void * __init build_flat_dt(unsigned long phys_mem_size)
+{
+ u64 tmp[2];
+
+ dt_init(&iseries_dt);
+
+ dt_start_node(&iseries_dt, "");
+
+ dt_prop_u32(&iseries_dt, "#address-cells", 2);
+ dt_prop_u32(&iseries_dt, "#size-cells", 2);
+ dt_model(&iseries_dt);
+
+ /* /memory */
+ dt_start_node(&iseries_dt, "memory@0");
+ dt_prop_str(&iseries_dt, "name", "memory");
+ dt_prop_str(&iseries_dt, "device_type", "memory");
+ tmp[0] = 0;
+ tmp[1] = phys_mem_size;
+ dt_prop_u64_list(&iseries_dt, "reg", tmp, 2);
+ dt_end_node(&iseries_dt);
+
+ /* /chosen */
+ dt_start_node(&iseries_dt, "chosen");
+ dt_prop_str(&iseries_dt, "bootargs", cmd_line);
+ dt_end_node(&iseries_dt);
+
+ dt_cpus(&iseries_dt);
+
+ dt_vdevices(&iseries_dt);
+ dt_pci_devices(&iseries_dt);
+
+ dt_end_node(&iseries_dt);
+
+ dt_push_u32(&iseries_dt, OF_DT_END);
+
+ return &iseries_dt;
+}
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 5661bd0..617c724 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -28,7 +28,6 @@ #include <linux/kdev_t.h>
#include <linux/major.h>
#include <linux/root_dev.h>
#include <linux/kernel.h>
-#include <linux/if_ether.h> /* ETH_ALEN */
#include <asm/processor.h>
#include <asm/machdep.h>
@@ -46,13 +45,11 @@ #include <asm/paca.h>
#include <asm/cache.h>
#include <asm/sections.h>
#include <asm/abs_addr.h>
-#include <asm/iseries/hv_types.h>
#include <asm/iseries/hv_lp_config.h>
#include <asm/iseries/hv_call_event.h>
#include <asm/iseries/hv_call_xm.h>
#include <asm/iseries/it_lp_queue.h>
#include <asm/iseries/mf.h>
-#include <asm/iseries/it_exp_vpd_panel.h>
#include <asm/iseries/hv_lp_event.h>
#include <asm/iseries/lpar_map.h>
#include <asm/udbg.h>
@@ -66,8 +63,6 @@ #include "processor_vpd.h"
#include "main_store.h"
#include "call_sm.h"
#include "call_hpt.h"
-#include "call_pci.h"
-#include "pci.h"
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
@@ -711,575 +706,6 @@ define_machine(iseries) {
/* XXX Implement enable_pmcs for iSeries */
};
-struct blob {
- unsigned char data[PAGE_SIZE * 2];
- unsigned long next;
-};
-
-struct iseries_flat_dt {
- struct boot_param_header header;
- u64 reserve_map[2];
- struct blob dt;
- struct blob strings;
-};
-
-static struct iseries_flat_dt iseries_dt;
-
-static void __init dt_init(struct iseries_flat_dt *dt)
-{
- dt->header.off_mem_rsvmap =
- offsetof(struct iseries_flat_dt, reserve_map);
- dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt);
- dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings);
- dt->header.totalsize = sizeof(struct iseries_flat_dt);
- dt->header.dt_strings_size = sizeof(struct blob);
-
- /* There is no notion of hardware cpu id on iSeries */
- dt->header.boot_cpuid_phys = smp_processor_id();
-
- dt->dt.next = (unsigned long)&dt->dt.data;
- dt->strings.next = (unsigned long)&dt->strings.data;
-
- dt->header.magic = OF_DT_HEADER;
- dt->header.version = 0x10;
- dt->header.last_comp_version = 0x10;
-
- dt->reserve_map[0] = 0;
- dt->reserve_map[1] = 0;
-}
-
-static void __init dt_check_blob(struct blob *b)
-{
- if (b->next >= (unsigned long)&b->next) {
- DBG("Ran out of space in flat device tree blob!\n");
- BUG();
- }
-}
-
-static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value)
-{
- *((u32*)dt->dt.next) = value;
- dt->dt.next += sizeof(u32);
-
- dt_check_blob(&dt->dt);
-}
-
-#ifdef notyet
-static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value)
-{
- *((u64*)dt->dt.next) = value;
- dt->dt.next += sizeof(u64);
-
- dt_check_blob(&dt->dt);
-}
-#endif
-
-static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len)
-{
- unsigned long start = blob->next - (unsigned long)blob->data;
-
- memcpy((char *)blob->next, data, len);
- blob->next = _ALIGN(blob->next + len, 4);
-
- dt_check_blob(blob);
-
- return start;
-}
-
-static void __init dt_start_node(struct iseries_flat_dt *dt, char *name)
-{
- dt_push_u32(dt, OF_DT_BEGIN_NODE);
- dt_push_bytes(&dt->dt, name, strlen(name) + 1);
-}
-
-#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
-
-static void __init dt_prop(struct iseries_flat_dt *dt, char *name,
- char *data, int len)
-{
- unsigned long offset;
-
- dt_push_u32(dt, OF_DT_PROP);
-
- /* Length of the data */
- dt_push_u32(dt, len);
-
- /* Put the property name in the string blob. */
- offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1);
-
- /* The offset of the properties name in the string blob. */
- dt_push_u32(dt, (u32)offset);
-
- /* The actual data. */
- dt_push_bytes(&dt->dt, data, len);
-}
-
-static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name,
- char *data)
-{
- dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
-}
-
-static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
-{
- dt_prop(dt, name, (char *)&data, sizeof(u32));
-}
-
-static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
-{
- dt_prop(dt, name, (char *)&data, sizeof(u64));
-}
-
-static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name,
- u64 *data, int n)
-{
- dt_prop(dt, name, (char *)data, sizeof(u64) * n);
-}
-
-static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name,
- u32 *data, int n)
-{
- dt_prop(dt, name, (char *)data, sizeof(u32) * n);
-}
-
-#ifdef notyet
-static void __init dt_prop_empty(struct iseries_flat_dt *dt, char *name)
-{
- dt_prop(dt, name, NULL, 0);
-}
-#endif
-
-static void __init dt_cpus(struct iseries_flat_dt *dt)
-{
- unsigned char buf[32];
- unsigned char *p;
- unsigned int i, index;
- struct IoHriProcessorVpd *d;
- u32 pft_size[2];
-
- /* yuck */
- snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name);
- p = strchr(buf, ' ');
- if (!p) p = buf + strlen(buf);
-
- dt_start_node(dt, "cpus");
- dt_prop_u32(dt, "#address-cells", 1);
- dt_prop_u32(dt, "#size-cells", 0);
-
- pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA */
- pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);
-
- for (i = 0; i < NR_CPUS; i++) {
- if (lppaca[i].dyn_proc_status >= 2)
- continue;
-
- snprintf(p, 32 - (p - buf), "@%d", i);
- dt_start_node(dt, buf);
-
- dt_prop_str(dt, "device_type", "cpu");
-
- index = lppaca[i].dyn_hv_phys_proc_index;
- d = &xIoHriProcessorVpd[index];
-
- dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
- dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize);
-
- dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024);
- dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize);
-
- /* magic conversions to Hz copied from old code */
- dt_prop_u32(dt, "clock-frequency",
- ((1UL << 34) * 1000000) / d->xProcFreq);
- dt_prop_u32(dt, "timebase-frequency",
- ((1UL << 32) * 1000000) / d->xTimeBaseFreq);
-
- dt_prop_u32(dt, "reg", i);
-
- dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2);
-
- dt_end_node(dt);
- }
-
- dt_end_node(dt);
-}
-
-static void __init dt_model(struct iseries_flat_dt *dt)
-{
- char buf[16] = "IBM,";
-
- /* "IBM," + mfgId[2:3] + systemSerial[1:5] */
- strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2);
- strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5);
- buf[11] = '\0';
- dt_prop_str(dt, "system-id", buf);
-
- /* "IBM," + machineType[0:4] */
- strne2a(buf + 4, xItExtVpdPanel.machineType, 4);
- buf[8] = '\0';
- dt_prop_str(dt, "model", buf);
-
- dt_prop_str(dt, "compatible", "IBM,iSeries");
-}
-
-static void __init dt_vdevices(struct iseries_flat_dt *dt)
-{
- u32 reg = 0;
- HvLpIndexMap vlan_map;
- int i;
- char buf[32];
-
- dt_start_node(dt, "vdevice");
- dt_prop_str(dt, "device_type", "vdevice");
- dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice");
- dt_prop_u32(dt, "#address-cells", 1);
- dt_prop_u32(dt, "#size-cells", 0);
-
- snprintf(buf, sizeof(buf), "vty@%08x", reg);
- dt_start_node(dt, buf);
- dt_prop_str(dt, "device_type", "serial");
- dt_prop_u32(dt, "reg", reg);
- dt_end_node(dt);
- reg++;
-
- snprintf(buf, sizeof(buf), "v-scsi@%08x", reg);
- dt_start_node(dt, buf);
- dt_prop_str(dt, "device_type", "vscsi");
- dt_prop_str(dt, "compatible", "IBM,v-scsi");
- dt_prop_u32(dt, "reg", reg);
- dt_end_node(dt);
- reg++;
-
- vlan_map = HvLpConfig_getVirtualLanIndexMap();
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
- unsigned char mac_addr[ETH_ALEN];
-
- if ((vlan_map & (0x8000 >> i)) == 0)
- continue;
- snprintf(buf, 32, "l-lan@%08x", reg + i);
- dt_start_node(dt, buf);
- dt_prop_str(dt, "device_type", "network");
- dt_prop_str(dt, "compatible", "IBM,iSeries-l-lan");
- dt_prop_u32(dt, "reg", reg + i);
- dt_prop_u32(dt, "linux,unit_address", i);
-
- mac_addr[0] = 0x02;
- mac_addr[1] = 0x01;
- mac_addr[2] = 0xff;
- mac_addr[3] = i;
- mac_addr[4] = 0xff;
- mac_addr[5] = HvLpConfig_getLpIndex_outline();
- dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN);
- dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN);
- dt_prop_u32(dt, "max-frame-size", 9000);
- dt_prop_u32(dt, "address-bits", 48);
-
- dt_end_node(dt);
- }
- reg += HVMAXARCHITECTEDVIRTUALLANS;
-
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) {
- snprintf(buf, 32, "viodasd@%08x", reg + i);
- dt_start_node(dt, buf);
- dt_prop_str(dt, "device_type", "block");
- dt_prop_str(dt, "compatible", "IBM,iSeries-viodasd");
- dt_prop_u32(dt, "reg", reg + i);
- dt_prop_u32(dt, "linux,unit_address", i);
- dt_end_node(dt);
- }
- reg += HVMAXARCHITECTEDVIRTUALDISKS;
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) {
- snprintf(buf, 32, "viocd@%08x", reg + i);
- dt_start_node(dt, buf);
- dt_prop_str(dt, "device_type", "block");
- dt_prop_str(dt, "compatible", "IBM,iSeries-viocd");
- dt_prop_u32(dt, "reg", reg + i);
- dt_prop_u32(dt, "linux,unit_address", i);
- dt_end_node(dt);
- }
- reg += HVMAXARCHITECTEDVIRTUALCDROMS;
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) {
- snprintf(buf, 32, "viotape@%08x", reg + i);
- dt_start_node(dt, buf);
- dt_prop_str(dt, "device_type", "byte");
- dt_prop_str(dt, "compatible", "IBM,iSeries-viotape");
- dt_prop_u32(dt, "reg", reg + i);
- dt_prop_u32(dt, "linux,unit_address", i);
- dt_end_node(dt);
- }
-
- dt_end_node(dt);
-}
-
-struct pci_class_name {
- u16 code;
- char *name;
- char *type;
-};
-
-static struct pci_class_name __initdata pci_class_name[] = {
- { PCI_CLASS_NETWORK_ETHERNET, "ethernet", "network" },
-};
-
-static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code)
-{
- struct pci_class_name *cp;
-
- for (cp = pci_class_name;
- cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++)
- if (cp->code == class_code)
- return cp;
- return NULL;
-}
-
-/*
- * This assumes that the node slot is always on the primary bus!
- */
-static void __init scan_bridge_slot(struct iseries_flat_dt *dt,
- HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info)
-{
- HvSubBusNumber sub_bus = bridge_info->subBusNumber;
- u16 vendor_id;
- u16 device_id;
- u32 class_id;
- int err;
- char buf[32];
- u32 reg[5];
- int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus);
- int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus);
- HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function);
- u8 devfn;
- struct pci_class_name *cp;
-
- /*
- * Connect all functions of any device found.
- */
- for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) {
- for (function = 0; function < 8; function++) {
- HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel,
- function);
- err = HvCallXm_connectBusUnit(bus, sub_bus,
- agent_id, 0);
- if (err) {
- if (err != 0x302)
- printk(KERN_DEBUG
- "connectBusUnit(%x, %x, %x) "
- "== %x\n",
- bus, sub_bus, agent_id, err);
- continue;
- }
-
- err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
- PCI_VENDOR_ID, &vendor_id);
- if (err) {
- printk(KERN_DEBUG
- "ReadVendor(%x, %x, %x) == %x\n",
- bus, sub_bus, agent_id, err);
- continue;
- }
- err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
- PCI_DEVICE_ID, &device_id);
- if (err) {
- printk(KERN_DEBUG
- "ReadDevice(%x, %x, %x) == %x\n",
- bus, sub_bus, agent_id, err);
- continue;
- }
- err = HvCallPci_configLoad32(bus, sub_bus, agent_id,
- PCI_CLASS_REVISION , &class_id);
- if (err) {
- printk(KERN_DEBUG
- "ReadClass(%x, %x, %x) == %x\n",
- bus, sub_bus, agent_id, err);
- continue;
- }
-
- devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel),
- function);
- cp = dt_find_pci_class_name(class_id >> 16);
- if (cp && cp->name)
- strncpy(buf, cp->name, sizeof(buf) - 1);
- else
- snprintf(buf, sizeof(buf), "pci%x,%x",
- vendor_id, device_id);
- buf[sizeof(buf) - 1] = '\0';
- snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
- "@%x", PCI_SLOT(devfn));
- buf[sizeof(buf) - 1] = '\0';
- if (function != 0)
- snprintf(buf + strlen(buf),
- sizeof(buf) - strlen(buf),
- ",%x", function);
- dt_start_node(dt, buf);
- reg[0] = (bus << 16) | (devfn << 8);
- reg[1] = 0;
- reg[2] = 0;
- reg[3] = 0;
- reg[4] = 0;
- dt_prop_u32_list(dt, "reg", reg, 5);
- if (cp && (cp->type || cp->name))
- dt_prop_str(dt, "device_type",
- cp->type ? cp->type : cp->name);
- dt_prop_u32(dt, "vendor-id", vendor_id);
- dt_prop_u32(dt, "device-id", device_id);
- dt_prop_u32(dt, "class-code", class_id >> 8);
- dt_prop_u32(dt, "revision-id", class_id & 0xff);
- dt_prop_u32(dt, "linux,subbus", sub_bus);
- dt_prop_u32(dt, "linux,agent-id", agent_id);
- dt_prop_u32(dt, "linux,logical-slot-number",
- bridge_info->logicalSlotNumber);
- dt_end_node(dt);
-
- }
- }
-}
-
-static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus,
- HvSubBusNumber sub_bus, int id_sel)
-{
- struct HvCallPci_BridgeInfo bridge_info;
- HvAgentId agent_id;
- int function;
- int ret;
-
- /* Note: hvSubBus and irq is always be 0 at this level! */
- for (function = 0; function < 8; ++function) {
- agent_id = ISERIES_PCI_AGENTID(id_sel, function);
- ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0);
- if (ret != 0) {
- if (ret != 0xb)
- printk(KERN_DEBUG "connectBusUnit(%x, %x, %x) "
- "== %x\n",
- bus, sub_bus, agent_id, ret);
- continue;
- }
- printk("found device at bus %d idsel %d func %d (AgentId %x)\n",
- bus, id_sel, function, agent_id);
- ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id,
- iseries_hv_addr(&bridge_info),
- sizeof(struct HvCallPci_BridgeInfo));
- if (ret != 0)
- continue;
- printk("bridge info: type %x subbus %x "
- "maxAgents %x maxsubbus %x logslot %x\n",
- bridge_info.busUnitInfo.deviceType,
- bridge_info.subBusNumber,
- bridge_info.maxAgents,
- bridge_info.maxSubBusNumber,
- bridge_info.logicalSlotNumber);
- if (bridge_info.busUnitInfo.deviceType ==
- HvCallPci_BridgeDevice)
- scan_bridge_slot(dt, bus, &bridge_info);
- else
- printk("PCI: Invalid Bridge Configuration(0x%02X)",
- bridge_info.busUnitInfo.deviceType);
- }
-}
-
-static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus)
-{
- struct HvCallPci_DeviceInfo dev_info;
- const HvSubBusNumber sub_bus = 0; /* EADs is always 0. */
- int err;
- int id_sel;
- const int max_agents = 8;
-
- /*
- * Probe for EADs Bridges
- */
- for (id_sel = 1; id_sel < max_agents; ++id_sel) {
- err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel,
- iseries_hv_addr(&dev_info),
- sizeof(struct HvCallPci_DeviceInfo));
- if (err) {
- if (err != 0x302)
- printk(KERN_DEBUG "getDeviceInfo(%x, %x, %x) "
- "== %x\n",
- bus, sub_bus, id_sel, err);
- continue;
- }
- if (dev_info.deviceType != HvCallPci_NodeDevice) {
- printk(KERN_DEBUG "PCI: Invalid System Configuration"
- "(0x%02X) for bus 0x%02x id 0x%02x.\n",
- dev_info.deviceType, bus, id_sel);
- continue;
- }
- scan_bridge(dt, bus, sub_bus, id_sel);
- }
-}
-
-static void __init dt_pci_devices(struct iseries_flat_dt *dt)
-{
- HvBusNumber bus;
- char buf[32];
- u32 buses[2];
- int phb_num = 0;
-
- /* Check all possible buses. */
- for (bus = 0; bus < 256; bus++) {
- int err = HvCallXm_testBus(bus);
-
- if (err) {
- /*
- * Check for Unexpected Return code, a clue that
- * something has gone wrong.
- */
- if (err != 0x0301)
- printk(KERN_ERR "Unexpected Return on Probe"
- "(0x%02X): 0x%04X", bus, err);
- continue;
- }
- printk("bus %d appears to exist\n", bus);
- snprintf(buf, 32, "pci@%d", phb_num);
- dt_start_node(dt, buf);
- dt_prop_str(dt, "device_type", "pci");
- dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB");
- dt_prop_u32(dt, "#address-cells", 3);
- dt_prop_u32(dt, "#size-cells", 2);
- buses[0] = buses[1] = bus;
- dt_prop_u32_list(dt, "bus-range", buses, 2);
- scan_phb(dt, bus);
- dt_end_node(dt);
- phb_num++;
- }
-}
-
-static void __init build_flat_dt(struct iseries_flat_dt *dt,
- unsigned long phys_mem_size)
-{
- u64 tmp[2];
-
- dt_init(dt);
-
- dt_start_node(dt, "");
-
- dt_prop_u32(dt, "#address-cells", 2);
- dt_prop_u32(dt, "#size-cells", 2);
- dt_model(dt);
-
- /* /memory */
- dt_start_node(dt, "memory@0");
- dt_prop_str(dt, "name", "memory");
- dt_prop_str(dt, "device_type", "memory");
- tmp[0] = 0;
- tmp[1] = phys_mem_size;
- dt_prop_u64_list(dt, "reg", tmp, 2);
- dt_end_node(dt);
-
- /* /chosen */
- dt_start_node(dt, "chosen");
- dt_prop_str(dt, "bootargs", cmd_line);
- dt_end_node(dt);
-
- dt_cpus(dt);
-
- dt_vdevices(dt);
- dt_pci_devices(dt);
-
- dt_end_node(dt);
-
- dt_push_u32(dt, OF_DT_END);
-}
-
void * __init iSeries_early_setup(void)
{
unsigned long phys_mem_size;
@@ -1294,9 +720,7 @@ void * __init iSeries_early_setup(void)
iSeries_get_cmdline();
- build_flat_dt(&iseries_dt, phys_mem_size);
-
- return (void *) __pa(&iseries_dt);
+ return (void *) __pa(build_flat_dt(phys_mem_size));
}
static void hvputc(char c)
diff --git a/arch/powerpc/platforms/iseries/setup.h b/arch/powerpc/platforms/iseries/setup.h
index 5213044..0a47ac5 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_ti
extern int iSeries_set_rtc_time(struct rtc_time *tm);
extern void iSeries_get_rtc_time(struct rtc_time *tm);
+extern void *build_flat_dt(unsigned long phys_mem_size);
+
#endif /* __ISERIES_SETUP_H__ */
--
1.3.1.ge923
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 13/14] powerpc: make iSeries flattened device tree dynamic - part 2
2006-05-19 6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
` (9 preceding siblings ...)
2006-05-19 7:00 ` [PATCH 11/14] powerpc: split device tree stuff out of iseries/setup.c Stephen Rothwell
@ 2006-05-19 7:04 ` Stephen Rothwell
2006-05-19 7:04 ` [PATCH 12/14] powerpc: make iSeries flattened device tree dynamic Stephen Rothwell
2006-05-19 7:06 ` [PATCH 14/14] powerpc: cleanup of iSeries flat device tree Stephen Rothwell
12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19 7:04 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
This actually simplies things as we just figure out how much space we
used at the end and adjust klimit then.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/platforms/iseries/dt.c | 62 +++++++++++------------------------
1 files changed, 19 insertions(+), 43 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
0496bb52c33374b4f014df39c0e8a1b53325e93b
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index 0371329..2a51ec1 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -27,7 +27,6 @@ #include <linux/if_ether.h> /* ETH_ALEN
#include <asm/machdep.h>
#include <asm/prom.h>
#include <asm/lppaca.h>
-#include <asm/page.h>
#include <asm/cputable.h>
#include <asm/abs_addr.h>
#include <asm/system.h>
@@ -51,15 +50,10 @@ #endif
extern char __dt_strings_start[];
extern char __dt_strings_end[];
-struct blob {
- unsigned char data[PAGE_SIZE * 2];
- unsigned long next;
-};
-
struct iseries_flat_dt {
struct boot_param_header header;
u64 reserve_map[2];
- struct blob *dt;
+ void *data;
};
static struct iseries_flat_dt *iseries_dt;
@@ -76,15 +70,12 @@ static struct iseries_flat_dt * __init d
dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8);
dt->header.off_dt_struct = dt->header.off_dt_strings
+ ALIGN(str_len, 8);
- dt->dt = (struct blob *)((unsigned long)dt + dt->header.off_dt_struct);
- klimit = ALIGN((unsigned long)(dt->dt) + sizeof(struct blob), 8);
- dt->header.totalsize = klimit - (unsigned long)dt;
+ dt->data = (void *)((unsigned long)dt + dt->header.off_dt_struct);
dt->header.dt_strings_size = str_len;
/* There is no notion of hardware cpu id on iSeries */
dt->header.boot_cpuid_phys = smp_processor_id();
- dt->dt->next = (unsigned long)&dt->dt->data;
memcpy((char *)dt + dt->header.off_dt_strings, __dt_strings_start,
str_len);
@@ -98,54 +89,37 @@ static struct iseries_flat_dt * __init d
return dt;
}
-static void __init dt_check_blob(struct blob *b)
-{
- if (b->next >= (unsigned long)&b->next) {
- DBG("Ran out of space in flat device tree blob!\n");
- BUG();
- }
-}
-
static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value)
{
- *((u32*)dt->dt->next) = value;
- dt->dt->next += sizeof(u32);
-
- dt_check_blob(dt->dt);
+ *((u32 *)dt->data) = value;
+ dt->data += sizeof(u32);
}
#ifdef notyet
static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value)
{
- *((u64*)dt->dt->next) = value;
- dt->dt->next += sizeof(u64);
-
- dt_check_blob(dt->dt);
+ *((u64 *)dt->data) = value;
+ dt->data += sizeof(u64);
}
#endif
-static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len)
+static void __init dt_push_bytes(struct iseries_flat_dt *dt, char *data,
+ int len)
{
- unsigned long start = blob->next - (unsigned long)blob->data;
-
- memcpy((char *)blob->next, data, len);
- blob->next = _ALIGN(blob->next + len, 4);
-
- dt_check_blob(blob);
-
- return start;
+ memcpy(dt->data, data, len);
+ dt->data += ALIGN(len, 4);
}
static void __init dt_start_node(struct iseries_flat_dt *dt, char *name)
{
dt_push_u32(dt, OF_DT_BEGIN_NODE);
- dt_push_bytes(dt->dt, name, strlen(name) + 1);
+ dt_push_bytes(dt, name, strlen(name) + 1);
}
#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
static void __init dt_prop(struct iseries_flat_dt *dt, char *name,
- char *data, int len)
+ void *data, int len)
{
unsigned long offset;
@@ -160,7 +134,7 @@ static void __init dt_prop(struct iserie
dt_push_u32(dt, (u32)offset);
/* The actual data. */
- dt_push_bytes(dt->dt, data, len);
+ dt_push_bytes(dt, data, len);
}
static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name,
@@ -171,24 +145,24 @@ static void __init dt_prop_str(struct is
static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
{
- dt_prop(dt, name, (char *)&data, sizeof(u32));
+ dt_prop(dt, name, &data, sizeof(u32));
}
static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
{
- dt_prop(dt, name, (char *)&data, sizeof(u64));
+ dt_prop(dt, name, &data, sizeof(u64));
}
static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name,
u64 *data, int n)
{
- dt_prop(dt, name, (char *)data, sizeof(u64) * n);
+ dt_prop(dt, name, data, sizeof(u64) * n);
}
static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name,
u32 *data, int n)
{
- dt_prop(dt, name, (char *)data, sizeof(u32) * n);
+ dt_prop(dt, name, data, sizeof(u32) * n);
}
#ifdef notyet
@@ -595,6 +569,8 @@ static void __init dt_pci_devices(struct
static void dt_finish(struct iseries_flat_dt *dt)
{
dt_push_u32(dt, OF_DT_END);
+ dt->header.totalsize = (unsigned long)dt->data - (unsigned long)dt;
+ klimit = ALIGN((unsigned long)dt->data, 8);
}
void * __init build_flat_dt(unsigned long phys_mem_size)
--
1.3.1.ge923
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 12/14] powerpc: make iSeries flattened device tree dynamic
2006-05-19 6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
` (10 preceding siblings ...)
2006-05-19 7:04 ` [PATCH 13/14] powerpc: make iSeries flattened device tree dynamic - part 2 Stephen Rothwell
@ 2006-05-19 7:04 ` Stephen Rothwell
2006-05-19 7:06 ` [PATCH 14/14] powerpc: cleanup of iSeries flat device tree Stephen Rothwell
12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19 7:04 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
First we capture all the strings from dt.c statically by noting that gcc
puts them in a special section of their own. Idea from Michael Ellerman.
Then we move the flattened device tree to klimit.
Still to come, making the values blob grow as needed.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/kernel/vmlinux.lds.S | 5 ++
arch/powerpc/platforms/iseries/Makefile | 5 +-
arch/powerpc/platforms/iseries/dt.c | 96 ++++++++++++++++++-------------
3 files changed, 66 insertions(+), 40 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
0f75701d8ac409a5e5c9e1de1d414129a435b267
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index fe79c25..8b25953 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -93,6 +93,11 @@ #endif /* CONFIG_PPC32 */
__ptov_table_begin = .;
*(.ptov_fixup);
__ptov_table_end = .;
+#ifdef CONFIG_PPC_ISERIES
+ __dt_strings_start = .;
+ *(.dt_strings);
+ __dt_strings_end = .;
+#endif
}
. = ALIGN(16);
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
index 3230621..dee4eb4 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -1,8 +1,11 @@
EXTRA_CFLAGS += -mno-minimal-toc
-obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt.o mf.o lpevents.o \
+obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \
hvcall.o proc.o htab.o iommu.o misc.o irq.o
obj-$(CONFIG_PCI) += pci.o vpdinfo.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_VIOPATH) += viopath.o
obj-$(CONFIG_MODULES) += ksyms.o
+
+$(obj)/dt_mod.o: $(obj)/dt.o
+ @$(OBJCOPY) --rename-section .rodata.str1.8=.dt_strings $(obj)/dt.o $(obj)/dt_mod.o
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index 93d4233..0371329 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -30,6 +30,7 @@ #include <asm/lppaca.h>
#include <asm/page.h>
#include <asm/cputable.h>
#include <asm/abs_addr.h>
+#include <asm/system.h>
#include <asm/iseries/hv_types.h>
#include <asm/iseries/hv_lp_config.h>
#include <asm/iseries/hv_call_xm.h>
@@ -47,6 +48,9 @@ #else
#define DBG(fmt...)
#endif
+extern char __dt_strings_start[];
+extern char __dt_strings_end[];
+
struct blob {
unsigned char data[PAGE_SIZE * 2];
unsigned long next;
@@ -55,26 +59,34 @@ struct blob {
struct iseries_flat_dt {
struct boot_param_header header;
u64 reserve_map[2];
- struct blob dt;
- struct blob strings;
+ struct blob *dt;
};
-static struct iseries_flat_dt iseries_dt;
+static struct iseries_flat_dt *iseries_dt;
-static void __init dt_init(struct iseries_flat_dt *dt)
+static struct iseries_flat_dt * __init dt_init(void)
{
+ struct iseries_flat_dt *dt;
+ unsigned long str_len;
+
+ str_len = __dt_strings_end - __dt_strings_start;
+ dt = (struct iseries_flat_dt *)ALIGN(klimit, 8);
dt->header.off_mem_rsvmap =
offsetof(struct iseries_flat_dt, reserve_map);
- dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt);
- dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings);
- dt->header.totalsize = sizeof(struct iseries_flat_dt);
- dt->header.dt_strings_size = sizeof(struct blob);
+ dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8);
+ dt->header.off_dt_struct = dt->header.off_dt_strings
+ + ALIGN(str_len, 8);
+ dt->dt = (struct blob *)((unsigned long)dt + dt->header.off_dt_struct);
+ klimit = ALIGN((unsigned long)(dt->dt) + sizeof(struct blob), 8);
+ dt->header.totalsize = klimit - (unsigned long)dt;
+ dt->header.dt_strings_size = str_len;
/* There is no notion of hardware cpu id on iSeries */
dt->header.boot_cpuid_phys = smp_processor_id();
- dt->dt.next = (unsigned long)&dt->dt.data;
- dt->strings.next = (unsigned long)&dt->strings.data;
+ dt->dt->next = (unsigned long)&dt->dt->data;
+ memcpy((char *)dt + dt->header.off_dt_strings, __dt_strings_start,
+ str_len);
dt->header.magic = OF_DT_HEADER;
dt->header.version = 0x10;
@@ -82,6 +94,8 @@ static void __init dt_init(struct iserie
dt->reserve_map[0] = 0;
dt->reserve_map[1] = 0;
+
+ return dt;
}
static void __init dt_check_blob(struct blob *b)
@@ -94,19 +108,19 @@ static void __init dt_check_blob(struct
static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value)
{
- *((u32*)dt->dt.next) = value;
- dt->dt.next += sizeof(u32);
+ *((u32*)dt->dt->next) = value;
+ dt->dt->next += sizeof(u32);
- dt_check_blob(&dt->dt);
+ dt_check_blob(dt->dt);
}
#ifdef notyet
static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value)
{
- *((u64*)dt->dt.next) = value;
- dt->dt.next += sizeof(u64);
+ *((u64*)dt->dt->next) = value;
+ dt->dt->next += sizeof(u64);
- dt_check_blob(&dt->dt);
+ dt_check_blob(dt->dt);
}
#endif
@@ -125,7 +139,7 @@ static unsigned long __init dt_push_byte
static void __init dt_start_node(struct iseries_flat_dt *dt, char *name)
{
dt_push_u32(dt, OF_DT_BEGIN_NODE);
- dt_push_bytes(&dt->dt, name, strlen(name) + 1);
+ dt_push_bytes(dt->dt, name, strlen(name) + 1);
}
#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
@@ -140,14 +154,13 @@ static void __init dt_prop(struct iserie
/* Length of the data */
dt_push_u32(dt, len);
- /* Put the property name in the string blob. */
- offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1);
+ offset = name - __dt_strings_start;
/* The offset of the properties name in the string blob. */
dt_push_u32(dt, (u32)offset);
/* The actual data. */
- dt_push_bytes(&dt->dt, data, len);
+ dt_push_bytes(dt->dt, data, len);
}
static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name,
@@ -579,40 +592,45 @@ static void __init dt_pci_devices(struct
}
}
+static void dt_finish(struct iseries_flat_dt *dt)
+{
+ dt_push_u32(dt, OF_DT_END);
+}
+
void * __init build_flat_dt(unsigned long phys_mem_size)
{
u64 tmp[2];
- dt_init(&iseries_dt);
+ iseries_dt = dt_init();
- dt_start_node(&iseries_dt, "");
+ dt_start_node(iseries_dt, "");
- dt_prop_u32(&iseries_dt, "#address-cells", 2);
- dt_prop_u32(&iseries_dt, "#size-cells", 2);
- dt_model(&iseries_dt);
+ dt_prop_u32(iseries_dt, "#address-cells", 2);
+ dt_prop_u32(iseries_dt, "#size-cells", 2);
+ dt_model(iseries_dt);
/* /memory */
- dt_start_node(&iseries_dt, "memory@0");
- dt_prop_str(&iseries_dt, "name", "memory");
- dt_prop_str(&iseries_dt, "device_type", "memory");
+ dt_start_node(iseries_dt, "memory@0");
+ dt_prop_str(iseries_dt, "name", "memory");
+ dt_prop_str(iseries_dt, "device_type", "memory");
tmp[0] = 0;
tmp[1] = phys_mem_size;
- dt_prop_u64_list(&iseries_dt, "reg", tmp, 2);
- dt_end_node(&iseries_dt);
+ dt_prop_u64_list(iseries_dt, "reg", tmp, 2);
+ dt_end_node(iseries_dt);
/* /chosen */
- dt_start_node(&iseries_dt, "chosen");
- dt_prop_str(&iseries_dt, "bootargs", cmd_line);
- dt_end_node(&iseries_dt);
+ dt_start_node(iseries_dt, "chosen");
+ dt_prop_str(iseries_dt, "bootargs", cmd_line);
+ dt_end_node(iseries_dt);
- dt_cpus(&iseries_dt);
+ dt_cpus(iseries_dt);
- dt_vdevices(&iseries_dt);
- dt_pci_devices(&iseries_dt);
+ dt_vdevices(iseries_dt);
+ dt_pci_devices(iseries_dt);
- dt_end_node(&iseries_dt);
+ dt_end_node(iseries_dt);
- dt_push_u32(&iseries_dt, OF_DT_END);
+ dt_finish(iseries_dt);
- return &iseries_dt;
+ return iseries_dt;
}
--
1.3.1.ge923
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 14/14] powerpc: cleanup of iSeries flat device tree
2006-05-19 6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
` (11 preceding siblings ...)
2006-05-19 7:04 ` [PATCH 12/14] powerpc: make iSeries flattened device tree dynamic Stephen Rothwell
@ 2006-05-19 7:06 ` Stephen Rothwell
12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19 7:06 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
Consolidate the vio device node creation. Make some parameters const.
Make a few more things __initdata. Get the device_type strings out of
the device tree blob.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/platforms/iseries/dt.c | 199 ++++++++++++++++++-----------------
1 files changed, 101 insertions(+), 98 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
89435c92f9a6d37d8d47bf40acde012726780f7f
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index 2a51ec1..d3444aa 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -47,16 +47,34 @@ #else
#define DBG(fmt...)
#endif
+/*
+ * These are created by the linker script at the start and end
+ * of the section containing all the strings from this file.
+ */
extern char __dt_strings_start[];
extern char __dt_strings_end[];
struct iseries_flat_dt {
struct boot_param_header header;
u64 reserve_map[2];
- void *data;
};
-static struct iseries_flat_dt *iseries_dt;
+static void * __initdata dt_data;
+
+/*
+ * Putting these strings here keeps them out of the section
+ * that we rename to .dt_strings using objcopy and capture
+ * for the strings blob of the flattened device tree.
+ */
+static char __initdata device_type_cpu[] = "cpu";
+static char __initdata device_type_memory[] = "memory";
+static char __initdata device_type_serial[] = "serial";
+static char __initdata device_type_network[] = "network";
+static char __initdata device_type_block[] = "block";
+static char __initdata device_type_byte[] = "byte";
+static char __initdata device_type_pci[] = "pci";
+static char __initdata device_type_vdevice[] = "vdevice";
+static char __initdata device_type_vscsi[] = "vscsi";
static struct iseries_flat_dt * __init dt_init(void)
{
@@ -70,7 +88,7 @@ static struct iseries_flat_dt * __init d
dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8);
dt->header.off_dt_struct = dt->header.off_dt_strings
+ ALIGN(str_len, 8);
- dt->data = (void *)((unsigned long)dt + dt->header.off_dt_struct);
+ dt_data = (void *)((unsigned long)dt + dt->header.off_dt_struct);
dt->header.dt_strings_size = str_len;
/* There is no notion of hardware cpu id on iSeries */
@@ -91,26 +109,26 @@ static struct iseries_flat_dt * __init d
static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value)
{
- *((u32 *)dt->data) = value;
- dt->data += sizeof(u32);
+ *((u32 *)dt_data) = value;
+ dt_data += sizeof(u32);
}
#ifdef notyet
static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value)
{
- *((u64 *)dt->data) = value;
- dt->data += sizeof(u64);
+ *((u64 *)dt_data) = value;
+ dt_data += sizeof(u64);
}
#endif
-static void __init dt_push_bytes(struct iseries_flat_dt *dt, char *data,
+static void __init dt_push_bytes(struct iseries_flat_dt *dt, const char *data,
int len)
{
- memcpy(dt->data, data, len);
- dt->data += ALIGN(len, 4);
+ memcpy(dt_data, data, len);
+ dt_data += ALIGN(len, 4);
}
-static void __init dt_start_node(struct iseries_flat_dt *dt, char *name)
+static void __init dt_start_node(struct iseries_flat_dt *dt, const char *name)
{
dt_push_u32(dt, OF_DT_BEGIN_NODE);
dt_push_bytes(dt, name, strlen(name) + 1);
@@ -118,8 +136,8 @@ static void __init dt_start_node(struct
#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
-static void __init dt_prop(struct iseries_flat_dt *dt, char *name,
- void *data, int len)
+static void __init dt_prop(struct iseries_flat_dt *dt, const char *name,
+ const void *data, int len)
{
unsigned long offset;
@@ -137,36 +155,40 @@ static void __init dt_prop(struct iserie
dt_push_bytes(dt, data, len);
}
-static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name,
- char *data)
+static void __init dt_prop_str(struct iseries_flat_dt *dt, const char *name,
+ const char *data)
{
dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
}
-static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
+static void __init dt_prop_u32(struct iseries_flat_dt *dt, const char *name,
+ u32 data)
{
dt_prop(dt, name, &data, sizeof(u32));
}
-static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
+#ifdef notyet
+static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name,
+ u64 data)
{
dt_prop(dt, name, &data, sizeof(u64));
}
+#endif
-static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name,
- u64 *data, int n)
+static void __init dt_prop_u64_list(struct iseries_flat_dt *dt,
+ const char *name, u64 *data, int n)
{
dt_prop(dt, name, data, sizeof(u64) * n);
}
-static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name,
- u32 *data, int n)
+static void __init dt_prop_u32_list(struct iseries_flat_dt *dt,
+ const char *name, u32 *data, int n)
{
dt_prop(dt, name, data, sizeof(u32) * n);
}
#ifdef notyet
-static void __init dt_prop_empty(struct iseries_flat_dt *dt, char *name)
+static void __init dt_prop_empty(struct iseries_flat_dt *dt, const char *name)
{
dt_prop(dt, name, NULL, 0);
}
@@ -199,7 +221,7 @@ static void __init dt_cpus(struct iserie
snprintf(p, 32 - (p - buf), "@%d", i);
dt_start_node(dt, buf);
- dt_prop_str(dt, "device_type", "cpu");
+ dt_prop_str(dt, "device_type", device_type_cpu);
index = lppaca[i].dyn_hv_phys_proc_index;
d = &xIoHriProcessorVpd[index];
@@ -244,32 +266,41 @@ static void __init dt_model(struct iseri
dt_prop_str(dt, "compatible", "IBM,iSeries");
}
+static void __init dt_do_vdevice(struct iseries_flat_dt *dt,
+ const char *name, u32 reg, int unit,
+ const char *type, const char *compat, int end)
+{
+ char buf[32];
+
+ snprintf(buf, 32, "%s@%08x", name, reg + ((unit >= 0) ? unit : 0));
+ dt_start_node(dt, buf);
+ dt_prop_str(dt, "device_type", type);
+ if (compat)
+ dt_prop_str(dt, "compatible", compat);
+ dt_prop_u32(dt, "reg", reg + ((unit >= 0) ? unit : 0));
+ if (unit >= 0)
+ dt_prop_u32(dt, "linux,unit_address", unit);
+ if (end)
+ dt_end_node(dt);
+}
+
static void __init dt_vdevices(struct iseries_flat_dt *dt)
{
u32 reg = 0;
HvLpIndexMap vlan_map;
int i;
- char buf[32];
dt_start_node(dt, "vdevice");
- dt_prop_str(dt, "device_type", "vdevice");
+ dt_prop_str(dt, "device_type", device_type_vdevice);
dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice");
dt_prop_u32(dt, "#address-cells", 1);
dt_prop_u32(dt, "#size-cells", 0);
- snprintf(buf, sizeof(buf), "vty@%08x", reg);
- dt_start_node(dt, buf);
- dt_prop_str(dt, "device_type", "serial");
- dt_prop_u32(dt, "reg", reg);
- dt_end_node(dt);
+ dt_do_vdevice(dt, "vty", reg, -1, device_type_serial, NULL, 1);
reg++;
- snprintf(buf, sizeof(buf), "v-scsi@%08x", reg);
- dt_start_node(dt, buf);
- dt_prop_str(dt, "device_type", "vscsi");
- dt_prop_str(dt, "compatible", "IBM,v-scsi");
- dt_prop_u32(dt, "reg", reg);
- dt_end_node(dt);
+ dt_do_vdevice(dt, "v-scsi", reg, -1, device_type_vscsi,
+ "IBM,v-scsi", 1);
reg++;
vlan_map = HvLpConfig_getVirtualLanIndexMap();
@@ -278,13 +309,8 @@ static void __init dt_vdevices(struct is
if ((vlan_map & (0x8000 >> i)) == 0)
continue;
- snprintf(buf, 32, "l-lan@%08x", reg + i);
- dt_start_node(dt, buf);
- dt_prop_str(dt, "device_type", "network");
- dt_prop_str(dt, "compatible", "IBM,iSeries-l-lan");
- dt_prop_u32(dt, "reg", reg + i);
- dt_prop_u32(dt, "linux,unit_address", i);
-
+ dt_do_vdevice(dt, "l-lan", reg, i, device_type_network,
+ "IBM,iSeries-l-lan", 0);
mac_addr[0] = 0x02;
mac_addr[1] = 0x01;
mac_addr[2] = 0xff;
@@ -300,47 +326,31 @@ static void __init dt_vdevices(struct is
}
reg += HVMAXARCHITECTEDVIRTUALLANS;
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) {
- snprintf(buf, 32, "viodasd@%08x", reg + i);
- dt_start_node(dt, buf);
- dt_prop_str(dt, "device_type", "block");
- dt_prop_str(dt, "compatible", "IBM,iSeries-viodasd");
- dt_prop_u32(dt, "reg", reg + i);
- dt_prop_u32(dt, "linux,unit_address", i);
- dt_end_node(dt);
- }
+ for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
+ dt_do_vdevice(dt, "viodasd", reg, i, device_type_block,
+ "IBM,iSeries-viodasd", 1);
reg += HVMAXARCHITECTEDVIRTUALDISKS;
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) {
- snprintf(buf, 32, "viocd@%08x", reg + i);
- dt_start_node(dt, buf);
- dt_prop_str(dt, "device_type", "block");
- dt_prop_str(dt, "compatible", "IBM,iSeries-viocd");
- dt_prop_u32(dt, "reg", reg + i);
- dt_prop_u32(dt, "linux,unit_address", i);
- dt_end_node(dt);
- }
+
+ for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
+ dt_do_vdevice(dt, "viocd", reg, i, device_type_block,
+ "IBM,iSeries-viocd", 1);
reg += HVMAXARCHITECTEDVIRTUALCDROMS;
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) {
- snprintf(buf, 32, "viotape@%08x", reg + i);
- dt_start_node(dt, buf);
- dt_prop_str(dt, "device_type", "byte");
- dt_prop_str(dt, "compatible", "IBM,iSeries-viotape");
- dt_prop_u32(dt, "reg", reg + i);
- dt_prop_u32(dt, "linux,unit_address", i);
- dt_end_node(dt);
- }
+
+ for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
+ dt_do_vdevice(dt, "viotape", reg, i, device_type_byte,
+ "IBM,iSeries-viotape", 1);
dt_end_node(dt);
}
struct pci_class_name {
u16 code;
- char *name;
- char *type;
+ const char *name;
+ const char *type;
};
static struct pci_class_name __initdata pci_class_name[] = {
- { PCI_CLASS_NETWORK_ETHERNET, "ethernet", "network" },
+ { PCI_CLASS_NETWORK_ETHERNET, "ethernet", device_type_network },
};
static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code)
@@ -384,9 +394,7 @@ static void __init scan_bridge_slot(stru
agent_id, 0);
if (err) {
if (err != 0x302)
- printk(KERN_DEBUG
- "connectBusUnit(%x, %x, %x) "
- "== %x\n",
+ DBG("connectBusUnit(%x, %x, %x) %x\n",
bus, sub_bus, agent_id, err);
continue;
}
@@ -394,24 +402,21 @@ static void __init scan_bridge_slot(stru
err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
PCI_VENDOR_ID, &vendor_id);
if (err) {
- printk(KERN_DEBUG
- "ReadVendor(%x, %x, %x) == %x\n",
+ DBG("ReadVendor(%x, %x, %x) %x\n",
bus, sub_bus, agent_id, err);
continue;
}
err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
PCI_DEVICE_ID, &device_id);
if (err) {
- printk(KERN_DEBUG
- "ReadDevice(%x, %x, %x) == %x\n",
+ DBG("ReadDevice(%x, %x, %x) %x\n",
bus, sub_bus, agent_id, err);
continue;
}
err = HvCallPci_configLoad32(bus, sub_bus, agent_id,
PCI_CLASS_REVISION , &class_id);
if (err) {
- printk(KERN_DEBUG
- "ReadClass(%x, %x, %x) == %x\n",
+ DBG("ReadClass(%x, %x, %x) %x\n",
bus, sub_bus, agent_id, err);
continue;
}
@@ -470,19 +475,18 @@ static void __init scan_bridge(struct is
ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0);
if (ret != 0) {
if (ret != 0xb)
- printk(KERN_DEBUG "connectBusUnit(%x, %x, %x) "
- "== %x\n",
+ DBG("connectBusUnit(%x, %x, %x) %x\n",
bus, sub_bus, agent_id, ret);
continue;
}
- printk("found device at bus %d idsel %d func %d (AgentId %x)\n",
+ DBG("found device at bus %d idsel %d func %d (AgentId %x)\n",
bus, id_sel, function, agent_id);
ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id,
iseries_hv_addr(&bridge_info),
sizeof(struct HvCallPci_BridgeInfo));
if (ret != 0)
continue;
- printk("bridge info: type %x subbus %x "
+ DBG("bridge info: type %x subbus %x "
"maxAgents %x maxsubbus %x logslot %x\n",
bridge_info.busUnitInfo.deviceType,
bridge_info.subBusNumber,
@@ -493,7 +497,7 @@ static void __init scan_bridge(struct is
HvCallPci_BridgeDevice)
scan_bridge_slot(dt, bus, &bridge_info);
else
- printk("PCI: Invalid Bridge Configuration(0x%02X)",
+ DBG("PCI: Invalid Bridge Configuration(0x%02X)",
bridge_info.busUnitInfo.deviceType);
}
}
@@ -515,13 +519,12 @@ static void __init scan_phb(struct iseri
sizeof(struct HvCallPci_DeviceInfo));
if (err) {
if (err != 0x302)
- printk(KERN_DEBUG "getDeviceInfo(%x, %x, %x) "
- "== %x\n",
+ DBG("getDeviceInfo(%x, %x, %x) %x\n",
bus, sub_bus, id_sel, err);
continue;
}
if (dev_info.deviceType != HvCallPci_NodeDevice) {
- printk(KERN_DEBUG "PCI: Invalid System Configuration"
+ DBG("PCI: Invalid System Configuration"
"(0x%02X) for bus 0x%02x id 0x%02x.\n",
dev_info.deviceType, bus, id_sel);
continue;
@@ -547,14 +550,14 @@ static void __init dt_pci_devices(struct
* something has gone wrong.
*/
if (err != 0x0301)
- printk(KERN_ERR "Unexpected Return on Probe"
- "(0x%02X): 0x%04X", bus, err);
+ DBG("Unexpected Return on Probe(0x%02X) "
+ "0x%04X\n", bus, err);
continue;
}
- printk("bus %d appears to exist\n", bus);
+ DBG("bus %d appears to exist\n", bus);
snprintf(buf, 32, "pci@%d", phb_num);
dt_start_node(dt, buf);
- dt_prop_str(dt, "device_type", "pci");
+ dt_prop_str(dt, "device_type", device_type_pci);
dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB");
dt_prop_u32(dt, "#address-cells", 3);
dt_prop_u32(dt, "#size-cells", 2);
@@ -569,12 +572,13 @@ static void __init dt_pci_devices(struct
static void dt_finish(struct iseries_flat_dt *dt)
{
dt_push_u32(dt, OF_DT_END);
- dt->header.totalsize = (unsigned long)dt->data - (unsigned long)dt;
- klimit = ALIGN((unsigned long)dt->data, 8);
+ dt->header.totalsize = (unsigned long)dt_data - (unsigned long)dt;
+ klimit = ALIGN((unsigned long)dt_data, 8);
}
void * __init build_flat_dt(unsigned long phys_mem_size)
{
+ struct iseries_flat_dt *iseries_dt;
u64 tmp[2];
iseries_dt = dt_init();
@@ -587,8 +591,7 @@ void * __init build_flat_dt(unsigned lon
/* /memory */
dt_start_node(iseries_dt, "memory@0");
- dt_prop_str(iseries_dt, "name", "memory");
- dt_prop_str(iseries_dt, "device_type", "memory");
+ dt_prop_str(iseries_dt, "device_type", device_type_memory);
tmp[0] = 0;
tmp[1] = phys_mem_size;
dt_prop_u64_list(iseries_dt, "reg", tmp, 2);
--
1.3.1.ge923
^ permalink raw reply related [flat|nested] 14+ messages in thread