]> err.no Git - linux-2.6/blobdiff - arch/powerpc/kernel/prom_init.c
[POWERPC] Add correct interrupt property for pegasos ide
[linux-2.6] / arch / powerpc / kernel / prom_init.c
index 520ef42f642ecca95c2f04ce3a4480fa3f913c33..e27d9d1b6e67232b75d9e99c50a70d051b282866 100644 (file)
@@ -2035,39 +2035,50 @@ static void __init fixup_device_tree_maple(void)
 #endif
 
 #ifdef CONFIG_PPC_CHRP
-/* Pegasos and BriQ lacks the "ranges" property in the isa node */
+/*
+ * Pegasos and BriQ lacks the "ranges" property in the isa node
+ * Pegasos needs decimal IRQ 14/15, not hexadecimal
+ */
 static void __init fixup_device_tree_chrp(void)
 {
-       phandle isa;
-       u32 isa_ranges[6];
+       phandle ph;
+       u32 prop[6];
        u32 rloc = 0x01006000; /* IO space; PCI device = 12 */
        char *name;
        int rc;
 
        name = "/pci@80000000/isa@c";
-       isa = call_prom("finddevice", 1, 1, ADDR(name));
-       if (!PHANDLE_VALID(isa)) {
+       ph = call_prom("finddevice", 1, 1, ADDR(name));
+       if (!PHANDLE_VALID(ph)) {
                name = "/pci@ff500000/isa@6";
-               isa = call_prom("finddevice", 1, 1, ADDR(name));
+               ph = call_prom("finddevice", 1, 1, ADDR(name));
                rloc = 0x01003000; /* IO space; PCI device = 6 */
        }
-       if (!PHANDLE_VALID(isa))
-               return;
-
-       rc = prom_getproplen(isa, "ranges");
-       if (rc != 0 && rc != PROM_ERROR)
-               return;
-
-       prom_printf("Fixing up missing ISA range on Pegasos...\n");
+       if (PHANDLE_VALID(ph)) {
+               rc = prom_getproplen(ph, "ranges");
+               if (rc == 0 || rc == PROM_ERROR) {
+                       prom_printf("Fixing up missing ISA range on Pegasos...\n");
+
+                       prop[0] = 0x1;
+                       prop[1] = 0x0;
+                       prop[2] = rloc;
+                       prop[3] = 0x0;
+                       prop[4] = 0x0;
+                       prop[5] = 0x00010000;
+                       prom_setprop(ph, name, "ranges", prop, sizeof(prop));
+               }
+       }
 
-       isa_ranges[0] = 0x1;
-       isa_ranges[1] = 0x0;
-       isa_ranges[2] = rloc;
-       isa_ranges[3] = 0x0;
-       isa_ranges[4] = 0x0;
-       isa_ranges[5] = 0x00010000;
-       prom_setprop(isa, name, "ranges",
-                       isa_ranges, sizeof(isa_ranges));
+       name = "/pci@80000000/ide@C,1";
+       ph = call_prom("finddevice", 1, 1, ADDR(name));
+       if (PHANDLE_VALID(ph)) {
+               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));
+       }
 }
 #else
 #define fixup_device_tree_chrp()
@@ -2117,11 +2128,92 @@ static void __init fixup_device_tree_pmac(void)
 #define fixup_device_tree_pmac()
 #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)
+{
+       /* 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",           "compatible",   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") },
+               {}
+       };
+       #undef prop_cstr
+
+       /* Vars */
+       u32 node;
+       char prop[64];
+       int rv, i;
+
+       /* Check if we're really running on a EFIKA */
+       node = call_prom("finddevice", 1, 1, ADDR("/"));
+       if (!PHANDLE_VALID(node))
+               return;
+
+       rv = prom_getprop(node, "model", prop, sizeof(prop));
+       if (rv == PROM_ERROR)
+               return;
+       if (strcmp(prop, "EFIKA5K2"))
+               return;
+
+       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;
+               }
+
+               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);
+       }
+}
+#else
+#define fixup_device_tree_efika()
+#endif
+
 static void __init fixup_device_tree(void)
 {
        fixup_device_tree_maple();
        fixup_device_tree_chrp();
        fixup_device_tree_pmac();
+       fixup_device_tree_efika();
 }
 
 static void __init prom_find_boot_cpu(void)