#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>
#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/hv_lp_event.h>
#include <asm/iseries/lpar_map.h>
#include <asm/udbg.h>
+#include <asm/irq.h>
#include "naca.h"
#include "setup.h"
static void iSeries_pci_final_fixup(void) { }
#endif
-/* Global Variables */
-int piranha_simulator;
-
extern int rd_size; /* Defined in drivers/block/rd.c */
extern unsigned long embedded_sysmap_start;
extern unsigned long embedded_sysmap_end;
#ifdef CONFIG_SMP
smp_init_iSeries();
#endif
- if (itLpNaca.xPirEnvironMode == 0)
- piranha_simulator = 1;
/* Associate Lp Event Queue 0 with processor 0 */
HvCallEvent_setLpEventQueueInterruptProc(0, 0);
{
if (get_lppaca()->shared_proc) {
ppc_md.idle_loop = iseries_shared_idle;
- printk(KERN_INFO "Using shared processor idle loop\n");
+ printk(KERN_DEBUG "Using shared processor idle loop\n");
} else {
ppc_md.idle_loop = iseries_dedicated_idle;
- printk(KERN_INFO "Using dedicated idle loop\n");
+ printk(KERN_DEBUG "Using dedicated idle loop\n");
}
/* Setup the Lp Event Queue */
void __init iSeries_init_IRQ(void) { }
#endif
-static int __init iseries_probe(int platform)
+static int __init iseries_probe(void)
{
- if (PLATFORM_ISERIES_LPAR != platform)
+ unsigned long root = of_get_flat_dt_root();
+ if (!of_flat_dt_is_compatible(root, "IBM,iSeries"))
return 0;
powerpc_firmware_features |= FW_FEATURE_ISERIES;
powerpc_firmware_features |= FW_FEATURE_LPAR;
+ /*
+ * The Hypervisor only allows us up to 256 interrupt
+ * sources (the irq number is passed in a u8).
+ */
+ virt_irq_max = 255;
+
return 1;
}
-struct machdep_calls __initdata iseries_md = {
+define_machine(iseries) {
+ .name = "iSeries",
.setup_arch = iSeries_setup_arch,
.show_cpuinfo = iSeries_show_cpuinfo,
.init_IRQ = iSeries_init_IRQ,
};
struct blob {
- unsigned char data[PAGE_SIZE];
+ unsigned char data[PAGE_SIZE * 2];
unsigned long next;
};
dt_prop_str(dt, "compatible", "IBM,iSeries");
}
+void 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_u32(dt, "#address-cells", 1);
+ dt_prop_u32(dt, "#size-cells", 0);
+
+ snprintf(buf, sizeof(buf), "viocons@%08x", reg);
+ dt_start_node(dt, buf);
+ dt_prop_str(dt, "device_type", "serial");
+ dt_prop_str(dt, "compatible", "");
+ 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, "vlan@%08x", reg + i);
+ dt_start_node(dt, buf);
+ dt_prop_str(dt, "device_type", "vlan");
+ dt_prop_str(dt, "compatible", "");
+ 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_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", "viodasd");
+ dt_prop_str(dt, "compatible", "");
+ 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", "viocd");
+ dt_prop_str(dt, "compatible", "");
+ 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", "viotape");
+ dt_prop_str(dt, "compatible", "");
+ dt_prop_u32(dt, "reg", reg + i);
+ dt_prop_u32(dt, "linux,unit_address", i);
+ dt_end_node(dt);
+ }
+
+ dt_end_node(dt);
+}
+
void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
{
u64 tmp[2];
/* /chosen */
dt_start_node(dt, "chosen");
- dt_prop_u32(dt, "linux,platform", PLATFORM_ISERIES_LPAR);
dt_prop_str(dt, "bootargs", cmd_line);
if (cmd_mem_limit)
dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit);
dt_cpus(dt);
+ dt_vdevices(dt);
+
dt_end_node(dt);
dt_push_u32(dt, OF_DT_END);