X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=arch%2Fpowerpc%2Fkernel%2Fprom_init.c;h=5ab4c8466cc94f56c645d5193eae9ffca00e0ad3;hb=d2fc0bacd5c438cb459fdf531eff00ab18422a00;hp=a1d582e38627492ace142363659cac979969640f;hpb=e8b495fe09bc793ae26774e7b2667f7f658d56e2;p=linux-2.6-omap-h63xx.git diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index a1d582e3862..5ab4c8466cc 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -1199,7 +1199,7 @@ static void __init prom_initialize_tce_table(void) if ((type[0] == 0) || (strstr(type, RELOC("pci")) == NULL)) continue; - /* Keep the old logic in tack to avoid regression. */ + /* Keep the old logic intact to avoid regression. */ if (compatible[0] != 0) { if ((strstr(compatible, RELOC("python")) == NULL) && (strstr(compatible, RELOC("Speedwagon")) == NULL) && @@ -1244,7 +1244,7 @@ static void __init prom_initialize_tce_table(void) local_alloc_bottom = base; /* It seems OF doesn't null-terminate the path :-( */ - memset(path, 0, sizeof(path)); + memset(path, 0, PROM_SCRATCH_SIZE); /* Call OF to setup the TCE hardware */ if (call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1) == PROM_ERROR) { @@ -2046,6 +2046,7 @@ static void __init fixup_device_tree_maple(void) /* * Pegasos and BriQ lacks the "ranges" property in the isa node * Pegasos needs decimal IRQ 14/15, not hexadecimal + * Pegasos has the IDE configured in legacy mode, but advertised as native */ static void __init fixup_device_tree_chrp(void) { @@ -2083,9 +2084,13 @@ static void __init fixup_device_tree_chrp(void) prom_printf("Fixing up IDE interrupt on Pegasos...\n"); prop[0] = 14; prop[1] = 0x0; - prop[2] = 15; - prop[3] = 0x0; - prom_setprop(ph, name, "interrupts", prop, 4*sizeof(u32)); + prom_setprop(ph, name, "interrupts", prop, 2*sizeof(u32)); + prom_printf("Fixing up IDE class-code on Pegasos...\n"); + rc = prom_getprop(ph, "class-code", prop, sizeof(u32)); + if (rc == sizeof(u32)) { + prop[0] &= ~0x5; + prom_setprop(ph, name, "class-code", prop, sizeof(u32)); + } } } #else @@ -2137,49 +2142,84 @@ static void __init fixup_device_tree_pmac(void) #endif #ifdef CONFIG_PPC_EFIKA -/* The current fw of the Efika has a device tree needs quite a few - * fixups to be compliant with the mpc52xx bindings. It's currently - * unknown if it will ever be compliant (come on bPlan ...) so we do fixups. - * NOTE that we (barely) tolerate it because the EFIKA was out before - * the bindings were finished, for any new boards -> RTFM ! */ - -struct subst_entry { - char *path; - char *property; - void *value; - int value_len; -}; - -static void __init fixup_device_tree_efika(void) +/* + * The MPC5200 FEC driver requires an phy-handle property to tell it how + * to talk to the phy. If the phy-handle property is missing, then this + * function is called to add the appropriate nodes and link it to the + * ethernet node. + */ +static void __init fixup_device_tree_efika_add_phy(void) { - /* Substitution table */ - #define prop_cstr(x) x, sizeof(x) - int prop_sound_irq[3] = { 2, 2, 0 }; - int prop_bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0, - 3,4,0, 3,5,0, 3,6,0, 3,7,0, - 3,8,0, 3,9,0, 3,10,0, 3,11,0, - 3,12,0, 3,13,0, 3,14,0, 3,15,0 }; - struct subst_entry efika_subst_table[] = { - { "/", "device_type", prop_cstr("efika") }, - { "/builtin", "device_type", prop_cstr("soc") }, - { "/builtin/ata", "compatible", prop_cstr("mpc5200b-ata\0mpc5200-ata"), }, - { "/builtin/bestcomm", "compatible", prop_cstr("mpc5200b-bestcomm\0mpc5200-bestcomm") }, - { "/builtin/bestcomm", "interrupts", prop_bcomm_irq, sizeof(prop_bcomm_irq) }, - { "/builtin/ethernet", "compatible", prop_cstr("mpc5200b-fec\0mpc5200-fec") }, - { "/builtin/pic", "compatible", prop_cstr("mpc5200b-pic\0mpc5200-pic") }, - { "/builtin/serial", "compatible", prop_cstr("mpc5200b-psc-uart\0mpc5200-psc-uart") }, - { "/builtin/sound", "compatible", prop_cstr("mpc5200b-psc-ac97\0mpc5200-psc-ac97") }, - { "/builtin/sound", "interrupts", prop_sound_irq, sizeof(prop_sound_irq) }, - { "/builtin/sram", "compatible", prop_cstr("mpc5200b-sram\0mpc5200-sram") }, - { "/builtin/sram", "device_type", prop_cstr("sram") }, - {} + u32 node; + char prop[64]; + int rv; + + /* Check if /builtin/ethernet exists - bail if it doesn't */ + node = call_prom("finddevice", 1, 1, ADDR("/builtin/ethernet")); + if (!PHANDLE_VALID(node)) + return; + + /* Check if the phy-handle property exists - bail if it does */ + rv = prom_getprop(node, "phy-handle", prop, sizeof(prop)); + if (!rv) + return; + + /* + * At this point the ethernet device doesn't have a phy described. + * Now we need to add the missing phy node and linkage + */ + + /* Check for an MDIO bus node - if missing then create one */ + node = call_prom("finddevice", 1, 1, ADDR("/builtin/mdio")); + if (!PHANDLE_VALID(node)) { + prom_printf("Adding Ethernet MDIO node\n"); + call_prom("interpret", 1, 1, + " s\" /builtin\" find-device" + " new-device" + " 1 encode-int s\" #address-cells\" property" + " 0 encode-int s\" #size-cells\" property" + " s\" mdio\" device-name" + " s\" fsl,mpc5200b-mdio\" encode-string" + " s\" compatible\" property" + " 0xf0003000 0x400 reg" + " 0x2 encode-int" + " 0x5 encode-int encode+" + " 0x3 encode-int encode+" + " s\" interrupts\" property" + " finish-device"); }; - #undef prop_cstr - /* Vars */ + /* Check for a PHY device node - if missing then create one and + * give it's phandle to the ethernet node */ + node = call_prom("finddevice", 1, 1, + ADDR("/builtin/mdio/ethernet-phy")); + if (!PHANDLE_VALID(node)) { + prom_printf("Adding Ethernet PHY node\n"); + call_prom("interpret", 1, 1, + " s\" /builtin/mdio\" find-device" + " new-device" + " s\" ethernet-phy\" device-name" + " 0x10 encode-int s\" reg\" property" + " my-self" + " ihandle>phandle" + " finish-device" + " s\" /builtin/ethernet\" find-device" + " encode-int" + " s\" phy-handle\" property" + " device-end"); + } +} + +static void __init fixup_device_tree_efika(void) +{ + int sound_irq[3] = { 2, 2, 0 }; + int bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0, + 3,4,0, 3,5,0, 3,6,0, 3,7,0, + 3,8,0, 3,9,0, 3,10,0, 3,11,0, + 3,12,0, 3,13,0, 3,14,0, 3,15,0 }; u32 node; char prop[64]; - int rv, i; + int rv, len; /* Check if we're really running on a EFIKA */ node = call_prom("finddevice", 1, 1, ADDR("/")); @@ -2194,23 +2234,36 @@ static void __init fixup_device_tree_efika(void) prom_printf("Applying EFIKA device tree fixups\n"); - /* Process substitution table */ - for (i=0; efika_subst_table[i].path; i++) { - struct subst_entry *se = &efika_subst_table[i]; - - node = call_prom("finddevice", 1, 1, ADDR(se->path)); - if (!PHANDLE_VALID(node)) { - prom_printf("fixup_device_tree_efika: ", - "skipped entry %x - not found\n", i); - continue; + /* Claiming to be 'chrp' is death */ + node = call_prom("finddevice", 1, 1, ADDR("/")); + rv = prom_getprop(node, "device_type", prop, sizeof(prop)); + if (rv != PROM_ERROR && (strcmp(prop, "chrp") == 0)) + prom_setprop(node, "/", "device_type", "efika", sizeof("efika")); + + /* Fixup bestcomm interrupts property */ + node = call_prom("finddevice", 1, 1, ADDR("/builtin/bestcomm")); + if (PHANDLE_VALID(node)) { + len = prom_getproplen(node, "interrupts"); + if (len == 12) { + prom_printf("Fixing bestcomm interrupts property\n"); + prom_setprop(node, "/builtin/bestcom", "interrupts", + bcomm_irq, sizeof(bcomm_irq)); } + } - rv = prom_setprop(node, se->path, se->property, - se->value, se->value_len ); - if (rv == PROM_ERROR) - prom_printf("fixup_device_tree_efika: ", - "skipped entry %x - setprop error\n", i); + /* Fixup sound interrupts property */ + node = call_prom("finddevice", 1, 1, ADDR("/builtin/sound")); + if (PHANDLE_VALID(node)) { + rv = prom_getprop(node, "interrupts", prop, sizeof(prop)); + if (rv == PROM_ERROR) { + prom_printf("Adding sound interrupts property\n"); + prom_setprop(node, "/builtin/sound", "interrupts", + sound_irq, sizeof(sound_irq)); + } } + + /* Make sure ethernet phy-handle property exists */ + fixup_device_tree_efika_add_phy(); } #else #define fixup_device_tree_efika() @@ -2226,7 +2279,7 @@ static void __init fixup_device_tree(void) static void __init prom_find_boot_cpu(void) { - struct prom_t *_prom = &RELOC(prom); + struct prom_t *_prom = &RELOC(prom); u32 getprop_rval; ihandle prom_cpu; phandle cpu_pkg; @@ -2246,7 +2299,7 @@ static void __init prom_find_boot_cpu(void) static void __init prom_check_initrd(unsigned long r3, unsigned long r4) { #ifdef CONFIG_BLK_DEV_INITRD - struct prom_t *_prom = &RELOC(prom); + struct prom_t *_prom = &RELOC(prom); if (r3 && r4 && r4 != 0xdeadbeef) { unsigned long val; @@ -2279,7 +2332,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long pp, unsigned long r6, unsigned long r7) { - struct prom_t *_prom; + struct prom_t *_prom; unsigned long hdr; unsigned long offset = reloc_offset(); @@ -2338,8 +2391,8 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, /* * Copy the CPU hold code */ - if (RELOC(of_platform) != PLATFORM_POWERMAC) - copy_and_flush(0, KERNELBASE + offset, 0x100, 0); + if (RELOC(of_platform) != PLATFORM_POWERMAC) + copy_and_flush(0, KERNELBASE + offset, 0x100, 0); /* * Do early parsing of command line