diff options
Diffstat (limited to 'arch/powerpc/kernel/prom_init.c')
-rw-r--r-- | arch/powerpc/kernel/prom_init.c | 152 |
1 files changed, 100 insertions, 52 deletions
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 1add6efdb315..5ab4c8466cc9 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -2142,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("/")); @@ -2199,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() |