* [PATCH 14/14] powerpc: cleanup of iSeries flat device tree
From: Stephen Rothwell @ 2006-05-19 7:06 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>
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
* [PATCH 12/14] powerpc: make iSeries flattened device tree dynamic
From: Stephen Rothwell @ 2006-05-19 7:04 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>
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
* [PATCH 13/14] powerpc: make iSeries flattened device tree dynamic - part 2
From: Stephen Rothwell @ 2006-05-19 7:04 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>
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
* [PATCH 11/14] powerpc: split device tree stuff out of iseries/setup.c
From: Stephen Rothwell @ 2006-05-19 7:00 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>
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
* [PATCH 10/14] powerpc: give iSeries device tree nodes better names
From: Stephen Rothwell @ 2006-05-19 6:58 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>
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
* [PATCH 09/14] powerpc: make iSeries flat device tree stuff static
From: Stephen Rothwell @ 2006-05-19 6:55 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>
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
* [PATCH 08/14] powerpc: clean up iSeries PCI probe
From: Stephen Rothwell @ 2006-05-19 6:54 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>
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
* [PATCH 07/14] powerpc: iSeries PCI devices can now have a devpsec attribute
From: Stephen Rothwell @ 2006-05-19 6:53 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>
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
* [PATCH 06/14] powerpc: remove LogicalSlot from pci_dn
From: Stephen Rothwell @ 2006-05-19 6:51 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>
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
* [PATCH 05/14] powerpc: remove Irq from pci_dn
From: Stephen Rothwell @ 2006-05-19 6:50 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>
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
* [PATCH 04/14] powerpc: remove iSeries_Global_Device_List
From: Stephen Rothwell @ 2006-05-19 6:48 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>
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
* [PATCH 03/14] powerpc: move iSeries PCI devices to the device tree
From: Stephen Rothwell @ 2006-05-19 6:46 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>
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
* [PATCH 02/14] powerpc: reintroduce HvCallPci_configLoad32
From: Stephen Rothwell @ 2006-05-19 6:43 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>
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
* [PATCH 01/14] powerpc: tidy up iseries/pci.c
From: Stephen Rothwell @ 2006-05-19 6:42 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev
Remove some unused counters.
No need to allocate iomm_table and iobar_table, which means that
iomm_table_initialize is not longer needed.
Use kzalloc where sensible.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/platforms/iseries/pci.c | 78 +++++-----------------------------
1 files changed, 11 insertions(+), 67 deletions(-)
This series of patches are intenede to put the iSeries PCI devices into
the flattened device tree. Built and run on an iSeries 270 with a single
PCI ethernet. Built for pSeries_defconfig.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
039fac4f522c6207625993cd79bb2164dc0b91f1
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 428ffb5..91a9474 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -57,15 +57,6 @@ LIST_HEAD(iSeries_Global_Device_List);
static int DeviceCount;
-/* Counters and control flags. */
-static long Pci_Io_Read_Count;
-static long Pci_Io_Write_Count;
-#if 0
-static long Pci_Cfg_Read_Count;
-static long Pci_Cfg_Write_Count;
-#endif
-static long Pci_Error_Count;
-
static int Pci_Retry_Max = 3; /* Only retry 3 times */
static int Pci_Error_Flag = 1; /* Set Retry Error on. */
@@ -79,41 +70,19 @@ #define IOMM_TABLE_MAX_ENTRIES 1024
#define IOMM_TABLE_ENTRY_SIZE 0x0000000000400000UL
#define BASE_IO_MEMORY 0xE000000000000000UL
-static unsigned long max_io_memory = 0xE000000000000000UL;
+static unsigned long max_io_memory = BASE_IO_MEMORY;
static long current_iomm_table_entry;
/*
* Lookup Tables.
*/
-static struct device_node **iomm_table;
-static u8 *iobar_table;
+static struct device_node *iomm_table[IOMM_TABLE_MAX_ENTRIES];
+static u8 iobar_table[IOMM_TABLE_MAX_ENTRIES];
-/*
- * Static and Global variables
- */
-static char *pci_io_text = "iSeries PCI I/O";
+static const char pci_io_text[] = "iSeries PCI I/O";
static DEFINE_SPINLOCK(iomm_table_lock);
/*
- * iomm_table_initialize
- *
- * Allocates and initalizes the Address Translation Table and Bar
- * Tables to get them ready for use. Must be called before any
- * I/O space is handed out to the device BARs.
- */
-static void iomm_table_initialize(void)
-{
- spin_lock(&iomm_table_lock);
- iomm_table = kmalloc(sizeof(*iomm_table) * IOMM_TABLE_MAX_ENTRIES,
- GFP_KERNEL);
- iobar_table = kmalloc(sizeof(*iobar_table) * IOMM_TABLE_MAX_ENTRIES,
- GFP_KERNEL);
- spin_unlock(&iomm_table_lock);
- if ((iomm_table == NULL) || (iobar_table == NULL))
- panic("PCI: I/O tables allocation failed.\n");
-}
-
-/*
* iomm_table_allocate_entry
*
* Adds pci_dev entry in address translation table
@@ -140,9 +109,8 @@ static void iomm_table_allocate_entry(st
*/
spin_lock(&iomm_table_lock);
bar_res->name = pci_io_text;
- bar_res->start =
+ bar_res->start = BASE_IO_MEMORY +
IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
- bar_res->start += BASE_IO_MEMORY;
bar_res->end = bar_res->start + bar_size - 1;
/*
* Allocate the number of table entries needed for BAR.
@@ -154,7 +122,7 @@ static void iomm_table_allocate_entry(st
++current_iomm_table_entry;
}
max_io_memory = BASE_IO_MEMORY +
- (IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry);
+ IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
spin_unlock(&iomm_table_lock);
}
@@ -171,13 +139,10 @@ static void iomm_table_allocate_entry(st
*/
static void allocate_device_bars(struct pci_dev *dev)
{
- struct resource *bar_res;
int bar_num;
- for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num) {
- bar_res = &dev->resource[bar_num];
+ for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num)
iomm_table_allocate_entry(dev, bar_num);
- }
}
/*
@@ -205,10 +170,9 @@ static struct device_node *build_device_
struct device_node *node;
struct pci_dn *pdn;
- node = kmalloc(sizeof(struct device_node), GFP_KERNEL);
+ node = kzalloc(sizeof(struct device_node), GFP_KERNEL);
if (node == NULL)
return NULL;
- memset(node, 0, sizeof(struct device_node));
pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
if (pdn == NULL) {
kfree(node);
@@ -224,7 +188,7 @@ static struct device_node *build_device_
}
/*
- * unsigned long __init find_and_init_phbs(void)
+ * iSeries_pcibios_init
*
* Description:
* This function checks for all possible system PCI host bridges that connect
@@ -232,7 +196,7 @@ static struct device_node *build_device_
* ownership status. A pci_controller is built for any bus which is partially
* owned or fully owned by this guest partition.
*/
-unsigned long __init find_and_init_phbs(void)
+void iSeries_pcibios_init(void)
{
struct pci_controller *phb;
HvBusNumber bus;
@@ -263,18 +227,6 @@ unsigned long __init find_and_init_phbs(
printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X",
bus, ret);
}
- return 0;
-}
-
-/*
- * iSeries_pcibios_init
- *
- * Chance to initialize and structures or variable before PCI Bus walk.
- */
-void iSeries_pcibios_init(void)
-{
- iomm_table_initialize();
- find_and_init_phbs();
}
/*
@@ -331,8 +283,7 @@ static void scan_PHB_slots(struct pci_co
int IdSel;
const int MaxAgents = 8;
- DevInfo = (struct HvCallPci_DeviceInfo*)
- kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL);
+ DevInfo = kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL);
if (DevInfo == NULL)
return;
@@ -622,7 +573,6 @@ static int CheckReturnCode(char *TextHdr
if (ret != 0) {
struct pci_dn *pdn = PCI_DN(DevNode);
- ++Pci_Error_Count;
(*retry)++;
printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n",
TextHdr, pdn->busno, pdn->devfn,
@@ -704,7 +654,6 @@ u8 iSeries_Read_Byte(const volatile void
return 0xff;
}
do {
- ++Pci_Io_Read_Count;
HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0);
} while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0);
@@ -734,7 +683,6 @@ u16 iSeries_Read_Word(const volatile voi
return 0xffff;
}
do {
- ++Pci_Io_Read_Count;
HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,
BarOffset, 0);
} while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0);
@@ -765,7 +713,6 @@ u32 iSeries_Read_Long(const volatile voi
return 0xffffffff;
}
do {
- ++Pci_Io_Read_Count;
HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa,
BarOffset, 0);
} while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0);
@@ -803,7 +750,6 @@ void iSeries_Write_Byte(u8 data, volatil
return;
}
do {
- ++Pci_Io_Write_Count;
rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0);
} while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0);
}
@@ -831,7 +777,6 @@ void iSeries_Write_Word(u16 data, volati
return;
}
do {
- ++Pci_Io_Write_Count;
rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0);
} while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0);
}
@@ -859,7 +804,6 @@ void iSeries_Write_Long(u32 data, volati
return;
}
do {
- ++Pci_Io_Write_Count;
rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0);
} while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0);
}
--
1.3.1.ge923
^ permalink raw reply related
* RE: [PATCH/2.6.17-rc4 0/10] powerpc: add mpc7448hpc2 (Taiga) bo ard support
From: Zang Roy-r61911 @ 2006-05-19 7:03 UTC (permalink / raw)
To: Kumar Gala
Cc: linuxppc-dev list, Yang Xin-Xin-r48390, Paul Mackerras,
Alexandre.Bounine
>
> On May 17, 2006, at 5:13 AM, Zang Roy-r61911 wrote:
>
> > Hi, Paul
> >
> > This series of patch adds mpc7448hpc2 (taiga) board support in
> > arch/powerpc.
> > Tsi108 chip of Tundra Semiconductor is also supported.
> >
> > Roy Zang
>
> Can you post your .dts for us to take a look at. I know Mark Greer
> is looking at support for the 105/6/7 family of bridges and the 10x
> family should have consistent flat device trees.
>
> - kumar
>
/*
* MPC7448HPC2 (Taiga) board Device Tree Source
*
* Copyright 2006 Freescale Semiconductor Inc.
* 2006 Roy Zang <Roy Zang at freescale.com>.
*
* 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.
*/
/ {
model = "mpc7448hpc2";
compatible = "mpc74xx";
#address-cells = <1>;
#size-cells = <1>;
linux,phandle = <100>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells =<0>;
linux,phandle = <200>;
PowerPC,7448@0 {
device_type = "cpu";
reg = <0>;
d-cache-line-size = <20>; // 32 bytes
i-cache-line-size = <20>; // 32 bytes
d-cache-size = <8000>; // L1, 32K bytes
i-cache-size = <8000>; // L1, 32K bytes
timebase-frequency = <0>; // 33 MHz, from uboot
clock-frequency = <0>; // From U-Boot
bus-frequency = <0>; // From U-Boot
32-bit;
linux,phandle = <201>;
linux,boot-cpu;
};
};
memory {
device_type = "memory";
linux,phandle = <300>;
reg = <00000000 20000000 // DDR2 512M at 0
>;
};
tsi108@c0000000 {
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
device_type = "tsi-bridge";
ranges = <00000000 c0000000 00010000>;
reg = <c0000000 00010000>;
bus-frequency = <0>;
i2c@7000 {
interrupt-parent = <7400>;
interrupts = <E 3>;
reg = <7000 400>;
device_type = "i2c";
compatible = "tsi-i2c";
};
mdio@6000 {
device_type = "mdio";
compatible = "tsi-ethernet";
ethernet-phy@6000 {
linux,phandle = <6000>;
interrupt-parent = <7400>;
interrupts = <2 1>;
reg = <6000 50>;
device_type = "ethernet-phy";
};
ethernet-phy@6400 {
linux,phandle = <6400>;
interrupt-parent = <7400>;
interrupts = <2 1>;
reg = <6400 50>;
device_type = "ethernet-phy";
};
};
ethernet@6200 {
#size-cells = <0>;
device_type = "network";
model = "TSI-ETH";
compatible = "tsi-ethernet";
reg = <6200 200>;
address = [ 00 06 D2 00 00 01 ];
interrupts = <10 3 10 3 10 3>;
interrupt-parent = <7400>;
phy-handle = <6000>;
};
ethernet@6600 {
#address-cells = <1>;
#size-cells = <0>;
device_type = "network";
model = "TSI-ETH";
compatible = "tsi-ethernet";
reg = <6600 200>;
address = [ 00 06 D2 00 00 02 ];
interrupts = <11 3 11 3 11 3>;
interrupt-parent = <7400>;
phy-handle = <6400>;
};
serial@7808 {
device_type = "serial";
compatible = "ns16550";
reg = <7808 200>;
clock-frequency = <3f6b5a00>;
interrupts = <c 3>;
interrupt-parent = <7400>;
};
serial@7c08 {
device_type = "serial";
compatible = "ns16550";
reg = <7c08 200>;
clock-frequency = <3f6b5a00>;
interrupts = <d 3>;
interrupt-parent = <7400>;
};
pic@7400 {
linux,phandle = <7400>;
clock-frequency = <0>;
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
reg = <7400 400>;
built-in;
compatible = "chrp,open-pic";
device_type = "open-pic";
big-endian;
};
pci@1000 {
compatible = "tsi10x";
device_type = "pci";
linux,phandle = <1000>;
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
reg = <1000 1000>;
bus-range = <0 0>;
ranges = <02000000 0 e0000000 e0000000 0 1A000000
01000000 0 00000000 fa000000 0 00010000>;
clock-frequency = <7f28154>;
interrupt-parent = <7400>;
interrupts = <8 0>;
interrupt-map-mask = <f800 0 0 7>;
interrupt-map = <
/* IDSEL 0x11 */
8800 0 0 1 7400 24 0
8800 0 0 2 7400 25 0
8800 0 0 3 7400 26 0
8800 0 0 4 7400 27 0
/* IDSEL 0x12 */
9000 0 0 1 7400 25 0
9000 0 0 2 7400 26 0
9000 0 0 3 7400 27 0
9000 0 0 4 7400 24 0
/* IDSEL 0x13 */
9800 0 0 1 7400 26 0
9800 0 0 2 7400 27 0
9800 0 0 3 7400 24 0
9800 0 0 4 7400 25 0
/* IDSEL 0x14 */
a000 0 0 1 7400 27 0
a000 0 0 2 7400 24 0
a000 0 0 3 7400 25 0
a000 0 0 4 7400 26 0
>;
};
};
};
^ permalink raw reply
* powerpc.git updated
From: Paul Mackerras @ 2006-05-19 6:07 UTC (permalink / raw)
To: linuxppc-dev
I just pushed a bunch of patches to the powerpc.git tree (master
branch) and pulled in Linus' current linux-2.6.git tree. The list
below shows which patches are in there but not in Linus' tree yet.
These will all go upstream after 2.6.17 is released. If you have a
patch that you want to go in that I haven't picked up yet, please
resend it.
Paul.
Andy Fleming:
Add 85xx CDS to arch/powerpc
Anton Blanchard:
powerpc: remove io_page_mask
Geoff Levand:
powerpc: remove do-nothing cpu setup routines
Haren Myneni:
powerpc: clear IPIs on kdump
Jeremy Kerr:
powerpc: cell: use kzalloc in alloc_spu_context()
powerpc: Add of_parse_dma_window()
powerpc: pseries: Use generic dma-window parsing function
Jimi Xenidis:
powerpc: Auto reserve of device tree blob
jimix@watson.ibm.com:
powerpc: udbg_printf() formatting attribute
Kumar Gala:
powerpc: provide ppc_md.panic() for both ppc32 & ppc64
Linas Vepstas:
powerpc/pseries: clear PCI failure counter if no new failures
powerpc/pseries: Increment fail counter in PCI recovery
Michael Ellerman:
powerpc: Disable and EOI interrupts in machine_crash_shutdown()
powerpc: Make early debugging options behave with oldconfig
powerpc: Make early xmon logic immune to location of early parsing
powerpc: Parse early parameters earlier
powerpc: Unify mem= handling
powerpc: Kdump header cleanup
powerpc: Move crashkernel= handling into the kernel.
Michael Neuling:
powerpc: whitespace cleanup in reg.h
mostrows@watson.ibm.com:
powerpc: Create /proc/rtas, /proc/ppc64/rtas if RTAS exists.
Olof Johansson:
powerpc: Quiet HVSI boot output
powerpc: Quiet time init output
powerpc: Quiet page order output
powerpc: Quiet VETH version printk
powerpc: Don't print chosen idle loop at every boot
powerpc: Less verbose mem configuration output
powerpc: Lack of ISA interrupts on XICS isn't dangerous
powerpc: Quiet PCI init printouts
powerpc: Quiet rtasd output at boot
powerpc: Quiet oprofile output at boot
powerpc: Remove stale iseries global
powerpc: kill union tce_entry
powerpc iommu: minor cleanup
Stephen Rothwell:
powerpc: add all the iSeries virtual devices to the device tree
powerpc: use the device tree for the iSeries vio bus probe
powerpc: use a common vio_match_device routine
powerpc: merge the rest of the vio code
powerpc: update iseries_veth device-tree information
powerpc: update iSeries viodasd device-tree entries
powerpc: update iSeries vdevice
powerpc: update iSeries viocd and viotape device-tree
powerpc: the iSeries vio lan driver changed device type
Will Schmidt:
nvram_print_partitions cosmetic fixup
^ permalink raw reply
* Re: [Cbe-oss-dev] Cell and new CPU feature bits
From: Andrew Pinski @ 2006-05-19 5:27 UTC (permalink / raw)
To: Olof Johansson; +Cc: cbe-oss-dev, Arnd Bergmann, linuxppc-dev list
In-Reply-To: <20060519051939.GJ8220@pb15.lixom.net>
On May 18, 2006, at 10:19 PM, Olof Johansson wrote:
>> - Lack of data stream instructions. Until now, it was assumed that
>> those were tied to the presence
>> of an Altivec (and they are documented in the Altivec manual).
>> Maybe
>> we should split that to a
>> new bit. I don't know if existing applications use them though, if
>> they do, there will be a
>> problem to get them updated as the new bit isn't present on older
>> kernels...
>
> I'm assuming you mean the instructions described under "AltiVec Memory
> Bandwidth Management" in secion 5.2 of the Altivec PEM -- dst, dstt,
> dstst, dss and dssall?
They are nops on the Cell though. They are also microcoded on the 970.
>
> If you're referring to the extended dcbt that includes streaming hints
> (as documented in the 64-bit PEM, but not in PPC book2 2.02), then a
> separate bit is likely needed -- obviously at least 970 seems to
> implement them.
Yes they are implemented on the 970.
Thanks,
Andrew Pinski
^ permalink raw reply
* pci-OF-bus-map deprecation
From: Benjamin Herrenschmidt @ 2006-05-19 5:24 UTC (permalink / raw)
To: linuxppc-dev list, Linux Kernel list
For 32 bits machines with Open Firmware, we used to create a
pci-OF-bus-map property in the device-tree that provided a mapping
between linux and Open Firmware PCI bus numbers (since on some platforms
like PowerMac, we still renumber PCI busses).
This property is no longer necessary as
- Nowadays, we have sysfs and the PCI devices in there do have a full
Open Firmware device path exposed as a "devspec" file in their sysfs
directories
- I don't think anybody ever used that property in userland :)
This mail is mostly to make sure of the later. I intend to get rid of it
in 2.6.18 (that's early, but as I said, I think nobody uses it anyway. I
intended to use it in some X stuff I never ended up actually
implementing...)
It only concerns 32 bits ppc machines with OF, and only the ones that
renumber busses, which means basically only PowerMacs.
Ben.
^ permalink raw reply
* Re: Cell and new CPU feature bits
From: Olof Johansson @ 2006-05-19 5:19 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: linuxppc-dev list, Paul Mackerras, cbe-oss-dev, Arnd Bergmann
In-Reply-To: <1148011621.13249.7.camel@localhost.localdomain>
On Fri, May 19, 2006 at 02:07:01PM +1000, Benjamin Herrenschmidt wrote:
> The Cell has a couple of "features" that should be exposed to userland
> in a way or another. That raises some questions however about how those
> should be done. Among others that come to mind:
Good questions, to make things scale when going from here on out
(including new products from various companies in the PPC arena), more
fine-grained features would certainly be useful.
> - The timebase errata (should we use a separate aux vector for "bugs"
> than for "features" ?
How are other userspace-exposed erratas normally handled? How are they
handled on other architectures? Adding it to the feature aux table
sounds like a bad idea.
> - Additional Altivec instructions (load/store right/left). A new
> feature bit for these ?
> - Lack of data stream instructions. Until now, it was assumed that
> those were tied to the presence
> of an Altivec (and they are documented in the Altivec manual). Maybe
> we should split that to a
> new bit. I don't know if existing applications use them though, if
> they do, there will be a
> problem to get them updated as the new bit isn't present on older
> kernels...
I'm assuming you mean the instructions described under "AltiVec Memory
Bandwidth Management" in secion 5.2 of the Altivec PEM -- dst, dstt,
dstst, dss and dssall?
Since they're explicitly part of the Altivec ISA, not the PPC ISA,
I don't see a need for a separate feature bit for them. They are not
marked as optional in the version I'm looking at right now (2.0).
> - Extended implementation of dcbt. (Another bit ? Or sould we just have
> a "CELL" bit ? In which
> case should it cover the altivec additions too or are those likely to
> exist in future non-Cell
> processors ?)
If you're referring to the extended dcbt that includes streaming hints
(as documented in the 64-bit PEM, but not in PPC book2 2.02), then a
separate bit is likely needed -- obviously at least 970 seems to
implement them.
> - Not strictly Cell specific but we currently don't expose the support
> for optional instructions
> fres and frsqte (which are supported by Cell)
>
> Part of the problem is that we only have 32 userland feature bits and
> for some reason decided to put the microarchitecture in there, thus we
> are running out fast...
From what I understood by Paul's choice of feature naming (see the
POWER6 patch discussions), PPC_ARCH_2_05 and similar will mean base
architecture version implemented and should not be used to assume
anything about optional features.
So, with that as a base, there will need to be a way to
indicate which optional features are available, plus what possible
extensions/implementation-specific features are there, at least if they
are common to more than one implementation/processor version. Bit arrays
seem to be the New Way of doing it between firmware and kernel, maybe
the same can/should be used for kernel->userspace? Can the aux vectors
be of arbitrary length?
-Olof
^ permalink raw reply
* Re: [PATCH] remove powerpc bitops infavor of existing generic bitops
From: Paul Mackerras @ 2006-05-19 5:00 UTC (permalink / raw)
To: Jon Mason; +Cc: linuxppc-dev
In-Reply-To: <20060515180108.GB17646@us.ibm.com>
Jon Mason writes:
> There already exists a big endian safe bitops implementation in
> lib/find_next_bit.c. The code in it is 90%+ common with the powerpc
> specific version, so the powerpc version is redundant. This patch
> makes the necessary changes to use the generic bitops in powerpc, and
> removes the powerpc specific version.
This patch breaks ARCH=ppc builds. Please resubmit with the necessary
changes to arch/ppc/Kconfig as well.
Paul.
^ permalink raw reply
* Recall: [PATCH/2.6.17-rc4 10/10] bugs fix for marvell SATA on po werp c pl atform
From: Zang Roy-r61911 @ 2006-05-19 4:12 UTC (permalink / raw)
To: Mark Lord, Jeff Garzik
Cc: Alexandre.Bounine, linux-ide, linux-kernel, linuxppc-dev list,
Paul Mackerras, Yang Xin-Xin-r48390
Zang Roy-r61911 would like to recall the message, "[PATCH/2.6.17-rc4 10/10] bugs fix for marvell SATA on powerp c pl atform".
^ permalink raw reply
* RE: [PATCH/2.6.17-rc4 10/10] bugs fix for marvell SATA on powerp c pl atform
From: Zang Roy-r61911 @ 2006-05-19 4:12 UTC (permalink / raw)
To: Mark Lord, Jeff Garzik
Cc: Alexandre.Bounine, linux-ide, linux-kernel, linuxppc-dev list,
Paul Mackerras, Yang Xin-Xin-r48390
> Jeff Garzik wrote:
> > Benjamin Herrenschmidt wrote:
> >> On Thu, 2006-05-18 at 12:03 +0800, Zang Roy-r61911 wrote:
> ..
> >>> @@ -1567,13 +1570,18 @@ static void mv5_read_preamp(struct mv_ho
> >>> static void mv5_enable_leds(struct mv_host_priv *hpriv,
> void __iomem
> >> *mmio)
> >>> {
> >>> u32 tmp;
> >>> -
> >>> +#ifndef CONFIG_PPC
> >>> writel(0, mmio + MV_GPIO_PORT_CTL);
> >>> +#endif
> >>
> >> You'll have to do better here too... I don't wee why when
> compiled on
> >> PPC, this driver should "magically" not clear those
> bits... At the very
> >> least, you should test the machine type if you want to do something
> >> specific to your platform, but first, you'll have to
> convince Jeff why
> >> this change has to be done in the first place and if there
> is a better
> >> way to handle it.
> >
> > Correct... it does seem some bugs were found, but #ifdef
> powerpc is
> > certainly out of the question. We want the driver to work without
> > ifdefs on all platforms.
>
> Yup. I have a powerpc platform here with PCI-X, and a PCI-X
> Marvell card
> to try in it. So I'll pick up these changes and try to
> integrate them a
> little more nicely in my internal updated driver, and then
> pass it on to Jeff.
>
> Cheers
>
The reason why I use "ifdef" is that I do not want to affect other platform. I do not
have other platform to verify. If you can verify my patch on your powerpc platform,
please help to integrate it into your driver.
^ permalink raw reply
* Cell and new CPU feature bits
From: Benjamin Herrenschmidt @ 2006-05-19 4:07 UTC (permalink / raw)
To: linuxppc-dev list, cbe-oss-dev; +Cc: Paul Mackerras, Arnd Bergmann
The Cell has a couple of "features" that should be exposed to userland
in a way or another. That raises some questions however about how those
should be done. Among others that come to mind:
- The timebase errata (should we use a separate aux vector for "bugs"
than for "features" ?
- Additional Altivec instructions (load/store right/left). A new
feature bit for these ?
- Lack of data stream instructions. Until now, it was assumed that
those were tied to the presence
of an Altivec (and they are documented in the Altivec manual). Maybe
we should split that to a
new bit. I don't know if existing applications use them though, if
they do, there will be a
problem to get them updated as the new bit isn't present on older
kernels...
- Extended implementation of dcbt. (Another bit ? Or sould we just have
a "CELL" bit ? In which
case should it cover the altivec additions too or are those likely to
exist in future non-Cell
processors ?)
- Not strictly Cell specific but we currently don't expose the support
for optional instructions
fres and frsqte (which are supported by Cell)
Part of the problem is that we only have 32 userland feature bits and
for some reason decided to put the microarchitecture in there, thus we
are running out fast...
Ben.
^ permalink raw reply
* RE: [PATCH/2.6.17-rc4 10/10] bugs fix for marvell SATA on powerp c pl atform
From: Zang Roy-r61911 @ 2006-05-19 4:06 UTC (permalink / raw)
To: Mark Lord, Jeff Garzik
Cc: Alexandre.Bounine, linux-ide, linux-kernel, linuxppc-dev list,
Paul Mackerras, Yang Xin-Xin-r48390
> Jeff Garzik wrote:
> > Benjamin Herrenschmidt wrote:
> >> On Thu, 2006-05-18 at 12:03 +0800, Zang Roy-r61911 wrote:
> ..
> >>> @@ -1567,13 +1570,18 @@ static void mv5_read_preamp(struct mv_ho
> >>> static void mv5_enable_leds(struct mv_host_priv *hpriv,
> void __iomem
> >> *mmio)
> >>> {
> >>> u32 tmp;
> >>> -
> >>> +#ifndef CONFIG_PPC
> >>> writel(0, mmio + MV_GPIO_PORT_CTL);
> >>> +#endif
> >>
> >> You'll have to do better here too... I don't wee why when
> compiled on
> >> PPC, this driver should "magically" not clear those
> bits... At the very
> >> least, you should test the machine type if you want to do something
> >> specific to your platform, but first, you'll have to
> convince Jeff why
> >> this change has to be done in the first place and if there
> is a better
> >> way to handle it.
> >
> > Correct... it does seem some bugs were found, but #ifdef
> powerpc is
> > certainly out of the question. We want the driver to work without
> > ifdefs on all platforms.
>
> Yup. I have a powerpc platform here with PCI-X, and a PCI-X
> Marvell card
> to try in it. So I'll pick up these changes and try to
> integrate them a
> little more nicely in my internal updated driver, and then
> pass it on to Jeff.
>
> Cheers
>
^ permalink raw reply
* Re: [PATCH/2.6.17-rc4 1/10] Powerpc: Add general support for mpc7 448h pc2 (Taiga) platform
From: Andy Fleming @ 2006-05-18 20:49 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Alexandre.Bounine, linuxppc-dev list, Paul Mackerras,
Yang Xin-Xin-r48390
In-Reply-To: <1147936929.17679.106.camel@localhost.localdomain>
On May 18, 2006, at 02:22, Benjamin Herrenschmidt wrote:
> On Thu, 2006-05-18 at 15:12 +0800, Zang Roy-r61911 wrote:
>>> I'm not repeating Kumar's comments about that CONFIG_7xxx
>>> thing and that
>>> 7xxx/ directory, it should all go.
>>>
>>
>> Should I move my code to embedded6xx?
>
> Probably for now yes.
>
>> I will get rid of those tables. I can see that in file
>> arch/powerpc/platforms/85xx/mpc85xx_ads.c (2.6.17-rc4), there is
>> a similar table. Should it be removed in future :)?
>
> Yes. And somebody beaten up for letting that stuff leak into
> arch/powerpc :)
>
>>> Yes, please do so, we will not accept a board that does the above :)
>>
>> I just do the same thing as 85xx :).
>
> Yes and I intend to LART Kumar seriously for that next time I meet
> him :)
So some of this needs to be moved into u-boot (look at my patches to
u-boot for the 85xx CDS support, and support in the current
powerpc.git tree). A lot of the PCI initialization is now there.
However, the interrupt maps, while properly setup in the current 85xx
u-boot oftree.dts files, is currently meaningless. I may be wrong,
but I thought support for getting the map from the flat-dev tree was
still pending....
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox