aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64/kernel/prom_init.c
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-06-02 16:39:11 +0100
committerDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-06-02 16:39:11 +0100
commit1c3f45ab2f7f879ea482501c83899505c31f7539 (patch)
tree672465b3b9b3e2e26a8caf74ed64aa6885c52c13 /arch/ppc64/kernel/prom_init.c
parentAUDIT: Fix user pointer deref thinko in sys_socketcall(). (diff)
parentMerge of master.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6 (diff)
downloadlinux-dev-1c3f45ab2f7f879ea482501c83899505c31f7539.tar.xz
linux-dev-1c3f45ab2f7f879ea482501c83899505c31f7539.zip
Merge with master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Diffstat (limited to 'arch/ppc64/kernel/prom_init.c')
-rw-r--r--arch/ppc64/kernel/prom_init.c60
1 files changed, 58 insertions, 2 deletions
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
index 35ec42de962e..3de950de3671 100644
--- a/arch/ppc64/kernel/prom_init.c
+++ b/arch/ppc64/kernel/prom_init.c
@@ -1566,7 +1566,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
{
int l, align;
phandle child;
- char *namep, *prev_name, *sstart;
+ char *namep, *prev_name, *sstart, *p, *ep;
unsigned long soff;
unsigned char *valp;
unsigned long offset = reloc_offset();
@@ -1588,6 +1588,14 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
call_prom("package-to-path", 3, 1, node, namep, l);
}
namep[l] = '\0';
+ /* Fixup an Apple bug where they have bogus \0 chars in the
+ * middle of the path in some properties
+ */
+ for (p = namep, ep = namep + l; p < ep; p++)
+ if (*p == '\0') {
+ memmove(p, p+1, ep - p);
+ ep--; l--;
+ }
*mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4);
}
@@ -1750,7 +1758,44 @@ static void __init flatten_device_tree(void)
prom_printf("Device tree struct 0x%x -> 0x%x\n",
RELOC(dt_struct_start), RELOC(dt_struct_end));
- }
+}
+
+
+static void __init fixup_device_tree(void)
+{
+ unsigned long offset = reloc_offset();
+ phandle u3, i2c, mpic;
+ u32 u3_rev;
+ u32 interrupts[2];
+ u32 parent;
+
+ /* Some G5s have a missing interrupt definition, fix it up here */
+ u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
+ if ((long)u3 <= 0)
+ return;
+ i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
+ if ((long)i2c <= 0)
+ return;
+ mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
+ if ((long)mpic <= 0)
+ return;
+
+ /* check if proper rev of u3 */
+ if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) <= 0)
+ return;
+ if (u3_rev != 0x35)
+ return;
+ /* does it need fixup ? */
+ if (prom_getproplen(i2c, "interrupts") > 0)
+ return;
+ /* interrupt on this revision of u3 is number 0 and level */
+ interrupts[0] = 0;
+ interrupts[1] = 1;
+ prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts));
+ parent = (u32)mpic;
+ prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent));
+}
+
static void __init prom_find_boot_cpu(void)
{
@@ -1844,6 +1889,12 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long
&getprop_rval, sizeof(getprop_rval));
/*
+ * On pSeries, inform the firmware about our capabilities
+ */
+ if (RELOC(of_platform) & PLATFORM_PSERIES)
+ prom_send_capabilities();
+
+ /*
* On pSeries, copy the CPU hold code
*/
if (RELOC(of_platform) & PLATFORM_PSERIES)
@@ -1920,6 +1971,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long
}
/*
+ * Fixup any known bugs in the device-tree
+ */
+ fixup_device_tree();
+
+ /*
* Now finally create the flattened device-tree
*/
prom_printf("copying OF device tree ...\n");