]> git.proxmox.com Git - mirror_ubuntu-disco-kernel.git/commitdiff
ppc/powerpc: workarounds for old Open Firmware versions
authorPaul Mackerras <paulus@samba.org>
Thu, 10 Nov 2005 01:00:55 +0000 (12:00 +1100)
committerPaul Mackerras <paulus@samba.org>
Thu, 10 Nov 2005 01:00:55 +0000 (12:00 +1100)
This adds code to work around some problems with old versions of
Open Firmware, such as on the early powermacs (7500 etc.) and the
"Longtrail" CHRP machine.  On these machines we have to claim
the physical and virtual address ranges explicitly when claiming
memory and then set up a V->P mapping.

The Longtrail has more problems: setprop doesn't work, and we have
to set an "allow-reclaim" variable to 0 in order to get claim on
physical memory ranges to fail if the memory is already claimed.

Signed-off-by: Paul Mackerras <paulus@samba.org>
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/platforms/chrp/setup.c
arch/ppc/boot/include/of1275.h
arch/ppc/boot/of1275/Makefile
arch/ppc/boot/of1275/call_prom.c [new file with mode: 0644]
arch/ppc/boot/of1275/claim.c
arch/ppc/boot/of1275/finddevice.c

index f645adb57534be04a39a2ed7718362b06359e812..5af39f866735b4e4915090a384a1a10de7d3a7b0 100644 (file)
@@ -1264,7 +1264,14 @@ static int __init early_init_dt_scan_memory(unsigned long node,
        unsigned long l;
 
        /* We are scanning "memory" nodes only */
-       if (type == NULL || strcmp(type, "memory") != 0)
+       if (type == NULL) {
+               /*
+                * The longtrail doesn't have a device_type on the
+                * /memory node, so look for the node called /memory@0.
+                */
+               if (depth != 1 || strcmp(uname, "memory@0") != 0)
+                       return 0;
+       } else if (strcmp(type, "memory") != 0)
                return 0;
 
        reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l);
index 58f0917bd6b624a0c021d8de43f08cfdd370eda5..09db1bb9ec912b2a63fbc89f2ff6de40dfabd59b 100644 (file)
@@ -94,11 +94,17 @@ extern const struct linux_logo logo_linux_clut224;
 #ifdef CONFIG_PPC64
 #define RELOC(x)        (*PTRRELOC(&(x)))
 #define ADDR(x)                (u32) add_reloc_offset((unsigned long)(x))
+#define OF_WORKAROUNDS 0
 #else
 #define RELOC(x)       (x)
 #define ADDR(x)                (u32) (x)
+#define OF_WORKAROUNDS of_workarounds
+int of_workarounds;
 #endif
 
+#define OF_WA_CLAIM    1       /* do phys/virt claim separately, then map */
+#define OF_WA_LONGTRAIL        2       /* work around longtrail bugs */
+
 #define PROM_BUG() do {                                                \
         prom_printf("kernel BUG at %s line 0x%x!\n",           \
                    RELOC(__FILE__), __LINE__);                 \
@@ -128,10 +134,11 @@ struct prom_args {
 
 struct prom_t {
        ihandle root;
-       ihandle chosen;
+       phandle chosen;
        int cpu;
        ihandle stdout;
        ihandle mmumap;
+       ihandle memory;
 };
 
 struct mem_map_entry {
@@ -360,16 +367,36 @@ static void __init prom_printf(const char *format, ...)
 static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
                                unsigned long align)
 {
-       int ret;
        struct prom_t *_prom = &RELOC(prom);
 
-       ret = call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
-                       (prom_arg_t)align);
-       if (ret != -1 && _prom->mmumap != 0)
-               /* old pmacs need us to map as well */
+       if (align == 0 && (OF_WORKAROUNDS & OF_WA_CLAIM)) {
+               /*
+                * Old OF requires we claim physical and virtual separately
+                * and then map explicitly (assuming virtual mode)
+                */
+               int ret;
+               prom_arg_t result;
+
+               ret = call_prom_ret("call-method", 5, 2, &result,
+                                   ADDR("claim"), _prom->memory,
+                                   align, size, virt);
+               if (ret != 0 || result == -1)
+                       return -1;
+               ret = call_prom_ret("call-method", 5, 2, &result,
+                                   ADDR("claim"), _prom->mmumap,
+                                   align, size, virt);
+               if (ret != 0) {
+                       call_prom("call-method", 4, 1, ADDR("release"),
+                                 _prom->memory, size, virt);
+                       return -1;
+               }
+               /* the 0x12 is M (coherence) + PP == read/write */
                call_prom("call-method", 6, 1,
-                         ADDR("map"), _prom->mmumap, 0, size, virt, virt);
-       return ret;
+                         ADDR("map"), _prom->mmumap, 0x12, size, virt, virt);
+               return virt;
+       }
+       return call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
+                        (prom_arg_t)align);
 }
 
 static void __init __attribute__((noreturn)) prom_panic(const char *reason)
@@ -415,11 +442,52 @@ static int inline prom_getproplen(phandle node, const char *pname)
        return call_prom("getproplen", 2, 1, node, ADDR(pname));
 }
 
-static int inline prom_setprop(phandle node, const char *pname,
-                              void *value, size_t valuelen)
+static void add_string(char **str, const char *q)
 {
-       return call_prom("setprop", 4, 1, node, ADDR(pname),
-                        (u32)(unsigned long) value, (u32) valuelen);
+       char *p = *str;
+
+       while (*q)
+               *p++ = *q++;
+       *p++ = ' ';
+       *str = p;
+}
+
+static char *tohex(unsigned int x)
+{
+       static char digits[] = "0123456789abcdef";
+       static char result[9];
+       int i;
+
+       result[8] = 0;
+       i = 8;
+       do {
+               --i;
+               result[i] = digits[x & 0xf];
+               x >>= 4;
+       } while (x != 0 && i > 0);
+       return &result[i];
+}
+
+static int __init prom_setprop(phandle node, const char *nodename,
+                              const char *pname, void *value, size_t valuelen)
+{
+       char cmd[256], *p;
+
+       if (!(OF_WORKAROUNDS & OF_WA_LONGTRAIL))
+               return call_prom("setprop", 4, 1, node, ADDR(pname),
+                                (u32)(unsigned long) value, (u32) valuelen);
+
+       /* gah... setprop doesn't work on longtrail, have to use interpret */
+       p = cmd;
+       add_string(&p, "dev");
+       add_string(&p, nodename);
+       add_string(&p, tohex((u32)(unsigned long) value));
+       add_string(&p, tohex(valuelen));
+       add_string(&p, tohex(ADDR(pname)));
+       add_string(&p, tohex(strlen(RELOC(pname))));
+       add_string(&p, "property");
+       *p = 0;
+       return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd);
 }
 
 /* We can't use the standard versions because of RELOC headaches. */
@@ -980,7 +1048,7 @@ static void __init prom_instantiate_rtas(void)
 
        rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
        if (!IHANDLE_VALID(rtas_inst)) {
-               prom_printf("opening rtas package failed");
+               prom_printf("opening rtas package failed (%x)\n", rtas_inst);
                return;
        }
 
@@ -988,7 +1056,7 @@ static void __init prom_instantiate_rtas(void)
 
        if (call_prom_ret("call-method", 3, 2, &entry,
                          ADDR("instantiate-rtas"),
-                         rtas_inst, base) == PROM_ERROR
+                         rtas_inst, base) != 0
            || entry == 0) {
                prom_printf(" failed\n");
                return;
@@ -997,8 +1065,10 @@ static void __init prom_instantiate_rtas(void)
 
        reserve_mem(base, size);
 
-       prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base));
-       prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry));
+       prom_setprop(rtas_node, "/rtas", "linux,rtas-base",
+                    &base, sizeof(base));
+       prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
+                    &entry, sizeof(entry));
 
        prom_debug("rtas base     = 0x%x\n", base);
        prom_debug("rtas entry    = 0x%x\n", entry);
@@ -1089,10 +1159,6 @@ static void __init prom_initialize_tce_table(void)
                if (base < local_alloc_bottom)
                        local_alloc_bottom = base;
 
-               /* Save away the TCE table attributes for later use. */
-               prom_setprop(node, "linux,tce-base", &base, sizeof(base));
-               prom_setprop(node, "linux,tce-size", &minsize, sizeof(minsize));
-
                /* It seems OF doesn't null-terminate the path :-( */
                memset(path, 0, sizeof(path));
                /* Call OF to setup the TCE hardware */
@@ -1101,6 +1167,10 @@ static void __init prom_initialize_tce_table(void)
                        prom_printf("package-to-path failed\n");
                }
 
+               /* Save away the TCE table attributes for later use. */
+               prom_setprop(node, path, "linux,tce-base", &base, sizeof(base));
+               prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize));
+
                prom_debug("TCE table: %s\n", path);
                prom_debug("\tnode = 0x%x\n", node);
                prom_debug("\tbase = 0x%x\n", base);
@@ -1342,6 +1412,7 @@ static void __init prom_init_client_services(unsigned long pp)
 /*
  * For really old powermacs, we need to map things we claim.
  * For that, we need the ihandle of the mmu.
+ * Also, on the longtrail, we need to work around other bugs.
  */
 static void __init prom_find_mmu(void)
 {
@@ -1355,12 +1426,19 @@ static void __init prom_find_mmu(void)
        if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
                return;
        version[sizeof(version) - 1] = 0;
-       prom_printf("OF version is '%s'\n", version);
        /* XXX might need to add other versions here */
-       if (strcmp(version, "Open Firmware, 1.0.5") != 0)
+       if (strcmp(version, "Open Firmware, 1.0.5") == 0)
+               of_workarounds = OF_WA_CLAIM;
+       else if (strncmp(version, "FirmWorks,3.", 12) == 0) {
+               of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL;
+               call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim");
+       } else
                return;
+       _prom->memory = call_prom("open", 1, 1, ADDR("/memory"));
        prom_getprop(_prom->chosen, "mmu", &_prom->mmumap,
                     sizeof(_prom->mmumap));
+       if (!IHANDLE_VALID(_prom->memory) || !IHANDLE_VALID(_prom->mmumap))
+               of_workarounds &= ~OF_WA_CLAIM;         /* hmmm */
 }
 #else
 #define prom_find_mmu()
@@ -1382,16 +1460,17 @@ static void __init prom_init_stdout(void)
        memset(path, 0, 256);
        call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255);
        val = call_prom("instance-to-package", 1, 1, _prom->stdout);
-       prom_setprop(_prom->chosen, "linux,stdout-package", &val, sizeof(val));
+       prom_setprop(_prom->chosen, "/chosen", "linux,stdout-package",
+                    &val, sizeof(val));
        prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device));
-       prom_setprop(_prom->chosen, "linux,stdout-path",
-                    RELOC(of_stdout_device), strlen(RELOC(of_stdout_device))+1);
+       prom_setprop(_prom->chosen, "/chosen", "linux,stdout-path",
+                    path, strlen(path) + 1);
 
        /* If it's a display, note it */
        memset(type, 0, sizeof(type));
        prom_getprop(val, "device_type", type, sizeof(type));
        if (strcmp(type, RELOC("display")) == 0)
-               prom_setprop(val, "linux,boot-display", NULL, 0);
+               prom_setprop(val, path, "linux,boot-display", NULL, 0);
 }
 
 static void __init prom_close_stdin(void)
@@ -1514,7 +1593,7 @@ static void __init prom_check_displays(void)
 
                /* Success */
                prom_printf("done\n");
-               prom_setprop(node, "linux,opened", NULL, 0);
+               prom_setprop(node, path, "linux,opened", NULL, 0);
 
                /* Setup a usable color table when the appropriate
                 * method is available. Should update this to set-colors */
@@ -1884,9 +1963,11 @@ static void __init fixup_device_tree(void)
        /* interrupt on this revision of u3 is number 0 and level */
        interrupts[0] = 0;
        interrupts[1] = 1;
-       prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts));
+       prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts",
+                    &interrupts, sizeof(interrupts));
        parent = (u32)mpic;
-       prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent));
+       prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
+                    &parent, sizeof(parent));
 #endif
 }
 
@@ -1922,11 +2003,11 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
                RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4;
 
                val = RELOC(prom_initrd_start);
-               prom_setprop(_prom->chosen, "linux,initrd-start", &val,
-                            sizeof(val));
+               prom_setprop(_prom->chosen, "/chosen", "linux,initrd-start",
+                            &val, sizeof(val));
                val = RELOC(prom_initrd_end);
-               prom_setprop(_prom->chosen, "linux,initrd-end", &val,
-                            sizeof(val));
+               prom_setprop(_prom->chosen, "/chosen", "linux,initrd-end",
+                            &val, sizeof(val));
 
                reserve_mem(RELOC(prom_initrd_start),
                            RELOC(prom_initrd_end) - RELOC(prom_initrd_start));
@@ -1969,14 +2050,15 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
        prom_init_client_services(pp);
 
        /*
-        * Init prom stdout device
+        * See if this OF is old enough that we need to do explicit maps
+        * and other workarounds
         */
-       prom_init_stdout();
+       prom_find_mmu();
 
        /*
-        * See if this OF is old enough that we need to do explicit maps
+        * Init prom stdout device
         */
-       prom_find_mmu();
+       prom_init_stdout();
 
        /*
         * Check for an initrd
@@ -1989,7 +2071,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
         */
        RELOC(of_platform) = prom_find_machine_type();
        getprop_rval = RELOC(of_platform);
-       prom_setprop(_prom->chosen, "linux,platform",
+       prom_setprop(_prom->chosen, "/chosen", "linux,platform",
                     &getprop_rval, sizeof(getprop_rval));
 
 #ifdef CONFIG_PPC_PSERIES
@@ -2050,21 +2132,23 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
         * Fill in some infos for use by the kernel later on
         */
        if (RELOC(prom_memory_limit))
-               prom_setprop(_prom->chosen, "linux,memory-limit",
+               prom_setprop(_prom->chosen, "/chosen", "linux,memory-limit",
                             &RELOC(prom_memory_limit),
                             sizeof(prom_memory_limit));
 #ifdef CONFIG_PPC64
        if (RELOC(ppc64_iommu_off))
-               prom_setprop(_prom->chosen, "linux,iommu-off", NULL, 0);
+               prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off",
+                            NULL, 0);
 
        if (RELOC(iommu_force_on))
-               prom_setprop(_prom->chosen, "linux,iommu-force-on", NULL, 0);
+               prom_setprop(_prom->chosen, "/chosen", "linux,iommu-force-on",
+                            NULL, 0);
 
        if (RELOC(prom_tce_alloc_start)) {
-               prom_setprop(_prom->chosen, "linux,tce-alloc-start",
+               prom_setprop(_prom->chosen, "/chosen", "linux,tce-alloc-start",
                             &RELOC(prom_tce_alloc_start),
                             sizeof(prom_tce_alloc_start));
-               prom_setprop(_prom->chosen, "linux,tce-alloc-end",
+               prom_setprop(_prom->chosen, "/chosen", "linux,tce-alloc-end",
                             &RELOC(prom_tce_alloc_end),
                             sizeof(prom_tce_alloc_end));
        }
index ecd32d5d85f487e775fc3dcb455d2c409ca793af..4099ddab9205ce6b32ed61f47e950a047c5e76b9 100644 (file)
@@ -361,7 +361,9 @@ static void __init chrp_find_openpic(void)
        printk(KERN_INFO "OpenPIC at %lx\n", opaddr);
 
        irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */
-       prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS - 4);
+       prom_get_irq_senses(init_senses, NUM_ISA_INTERRUPTS, NR_IRQS - 4);
+       /* i8259 cascade is always positive level */
+       init_senses[0] = IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE;
 
        iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len);
        if (iranges == NULL)
index 69173df76db0c06b8cb65de84c0a5f8859a8345a..4ed88acfa73a20f956f2287ba9f226491387201e 100644 (file)
@@ -19,6 +19,9 @@ extern prom_entry of_prom_entry;
 
 /* function declarations */
 
+int    call_prom(const char *service, int nargs, int nret, ...);
+int    call_prom_ret(const char *service, int nargs, int nret,
+                     unsigned int *rets, ...);
 void * claim(unsigned int virt, unsigned int size, unsigned int align);
 int    map(unsigned int phys, unsigned int virt, unsigned int size);
 void   enter(void);
index 02e6f235d7cb3bc6e32fb79b9a964e2ebc0b2144..0b979c0049729351a75931e38eb85a93d126bb9a 100644 (file)
@@ -3,4 +3,4 @@
 #
 
 lib-y := claim.o enter.o exit.o finddevice.o getprop.o ofinit.o        \
-        ofstdio.o read.o release.o write.o map.o
+        ofstdio.o read.o release.o write.o map.o call_prom.o
diff --git a/arch/ppc/boot/of1275/call_prom.c b/arch/ppc/boot/of1275/call_prom.c
new file mode 100644 (file)
index 0000000..9479a3a
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "of1275.h"
+#include <stdarg.h>
+
+int call_prom(const char *service, int nargs, int nret, ...)
+{
+       int i;
+       struct prom_args {
+               const char *service;
+               int nargs;
+               int nret;
+               unsigned int args[12];
+       } args;
+       va_list list;
+
+       args.service = service;
+       args.nargs = nargs;
+       args.nret = nret;
+
+       va_start(list, nret);
+       for (i = 0; i < nargs; i++)
+               args.args[i] = va_arg(list, unsigned int);
+       va_end(list);
+
+       for (i = 0; i < nret; i++)
+               args.args[nargs+i] = 0;
+
+       if (of_prom_entry(&args) < 0)
+               return -1;
+
+       return (nret > 0)? args.args[nargs]: 0;
+}
+
+int call_prom_ret(const char *service, int nargs, int nret,
+                 unsigned int *rets, ...)
+{
+       int i;
+       struct prom_args {
+               const char *service;
+               int nargs;
+               int nret;
+               unsigned int args[12];
+       } args;
+       va_list list;
+
+       args.service = service;
+       args.nargs = nargs;
+       args.nret = nret;
+
+       va_start(list, rets);
+       for (i = 0; i < nargs; i++)
+               args.args[i] = va_arg(list, unsigned int);
+       va_end(list);
+
+       for (i = 0; i < nret; i++)
+               args.args[nargs+i] = 0;
+
+       if (of_prom_entry(&args) < 0)
+               return -1;
+
+       if (rets != (void *) 0)
+               for (i = 1; i < nret; ++i)
+                       rets[i-1] = args.args[nargs+i];
+
+       return (nret > 0)? args.args[nargs]: 0;
+}
index 13169a5c4339d862128b660da5d8c149858b5871..1ed3aeeff8ae469d00ae21afa7a3575810b92aeb 100644 (file)
@@ -9,27 +9,84 @@
  */
 
 #include "of1275.h"
+#include "nonstdio.h"
 
-void *
-claim(unsigned int virt, unsigned int size, unsigned int align)
+/*
+ * Older OF's require that when claiming a specific range of addresses,
+ * we claim the physical space in the /memory node and the virtual
+ * space in the chosen mmu node, and then do a map operation to
+ * map virtual to physical.
+ */
+static int need_map = -1;
+static ihandle chosen_mmu;
+static phandle memory;
+
+/* returns true if s2 is a prefix of s1 */
+static int string_match(const char *s1, const char *s2)
+{
+       for (; *s2; ++s2)
+               if (*s1++ != *s2)
+                       return 0;
+       return 1;
+}
+
+static int check_of_version(void)
+{
+       phandle oprom, chosen;
+       char version[64];
+
+       oprom = finddevice("/openprom");
+       if (oprom == OF_INVALID_HANDLE)
+               return 0;
+       if (getprop(oprom, "model", version, sizeof(version)) <= 0)
+               return 0;
+       version[sizeof(version)-1] = 0;
+       printf("OF version = '%s'\n", version);
+       if (!string_match(version, "Open Firmware, 1.")
+           && !string_match(version, "FirmWorks,3."))
+               return 0;
+       chosen = finddevice("/chosen");
+       if (chosen == OF_INVALID_HANDLE) {
+               chosen = finddevice("/chosen@0");
+               if (chosen == OF_INVALID_HANDLE) {
+                       printf("no chosen\n");
+                       return 0;
+               }
+       }
+       if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
+               printf("no mmu\n");
+               return 0;
+       }
+       memory = (ihandle) call_prom("open", 1, 1, "/memory");
+       if (memory == OF_INVALID_HANDLE) {
+               memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
+               if (memory == OF_INVALID_HANDLE) {
+                       printf("no memory node\n");
+                       return 0;
+               }
+       }
+       printf("old OF detected\n");
+       return 1;
+}
+
+void *claim(unsigned int virt, unsigned int size, unsigned int align)
 {
-    struct prom_args {
-       char *service;
-       int nargs;
-       int nret;
-       unsigned int virt;
-       unsigned int size;
-       unsigned int align;
-       void *ret;
-    } args;
+       int ret;
+       unsigned int result;
 
-    args.service = "claim";
-    args.nargs = 3;
-    args.nret = 1;
-    args.virt = virt;
-    args.size = size;
-    args.align = align;
-    args.ret = (void *) 0;
-    (*of_prom_entry)(&args);
-    return args.ret;
+       if (need_map < 0)
+               need_map = check_of_version();
+       if (align || !need_map)
+               return (void *) call_prom("claim", 3, 1, virt, size, align);
+       
+       ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
+                           align, size, virt);
+       if (ret != 0 || result == -1)
+               return (void *) -1;
+       ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
+                           align, size, virt);
+       /* 0x12 == coherent + read/write */
+       ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
+                       0x12, size, virt, virt);
+       return virt;
 }
index 2c0f7cbb793e20b750b0eb913767abe20d44579e..0dcb1201b7722f7811370a51debb28b2e0361115 100644 (file)
 
 #include "of1275.h"
 
-phandle
-finddevice(const char *name)
+phandle finddevice(const char *name)
 {
-    struct prom_args {
-       char *service;
-       int nargs;
-       int nret;
-       const char *devspec;
-       phandle device;
-    } args;
-
-    args.service = "finddevice";
-    args.nargs = 1;
-    args.nret = 1;
-    args.devspec = name;
-    args.device = OF_INVALID_HANDLE;
-    (*of_prom_entry)(&args);
-    return args.device;
+       return (phandle) call_prom("finddevice", 1, 1, name);
 }