]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/powerpc/kernel/prom_init.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86
[linux-2.6-omap-h63xx.git] / arch / powerpc / kernel / prom_init.c
index a1d582e38627492ace142363659cac979969640f..5ab4c8466cc94f56c645d5193eae9ffca00e0ad3 100644 (file)
@@ -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