[SPARC64]: Convert sparc64 PCI layer to in-kernel device tree.

One thing this change pointed out was that we really should
pull the "get 'local-mac-address' property" logic into a helper
function all the network drivers can call.

Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c
index c69504a..3125a5b 100644
--- a/arch/sparc64/kernel/ebus.c
+++ b/arch/sparc64/kernel/ebus.c
@@ -553,7 +553,7 @@
 	}
 
 	cookie = pdev->sysdata;
-	ebusnd = cookie->prom_node;
+	ebusnd = cookie->prom_node->node;
 
 	ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus));
 	ebus->next = NULL;
@@ -578,7 +578,7 @@
 			}
 			ebus->is_rio = is_rio;
 			cookie = pdev->sysdata;
-			ebusnd = cookie->prom_node;
+			ebusnd = cookie->prom_node->node;
 			continue;
 		}
 		printk("ebus%d:", num_ebus);
@@ -622,7 +622,7 @@
 			break;
 
 		cookie = pdev->sysdata;
-		ebusnd = cookie->prom_node;
+		ebusnd = cookie->prom_node->node;
 
 		ebus->next = ebus_alloc(sizeof(struct linux_ebus));
 		ebus = ebus->next;
diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c
index 30862ab..ae02c38 100644
--- a/arch/sparc64/kernel/isa.c
+++ b/arch/sparc64/kernel/isa.c
@@ -291,8 +291,8 @@
 		isa_br->parent = pbm;
 		isa_br->self = pdev;
 		isa_br->index = index++;
-		isa_br->prom_node = pdev_cookie->prom_node;
-		strncpy(isa_br->prom_name, pdev_cookie->prom_name,
+		isa_br->prom_node = pdev_cookie->prom_node->node;
+		strncpy(isa_br->prom_name, pdev_cookie->prom_node->name,
 			sizeof(isa_br->prom_name));
 
 		prop_len = prom_getproperty(isa_br->prom_node,
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
index 2319d73..b06a295 100644
--- a/arch/sparc64/kernel/pci_common.c
+++ b/arch/sparc64/kernel/pci_common.c
@@ -9,6 +9,9 @@
 #include <linux/init.h>
 
 #include <asm/pbm.h>
+#include <asm/prom.h>
+
+#include "pci_impl.h"
 
 /* Pass "pci=irq_verbose" on the kernel command line to enable this.  */
 int pci_irq_verbose;
@@ -31,16 +34,14 @@
 	prom_halt();
 }
 
-/* Find the OBP PROM device tree node for a PCI device.
- * Return zero if not found.
- */
-static int __init find_device_prom_node(struct pci_pbm_info *pbm,
-					struct pci_dev *pdev,
-					int bus_prom_node,
-					struct linux_prom_pci_registers *pregs,
-					int *nregs)
+/* Find the OBP PROM device tree node for a PCI device.  */
+static struct device_node * __init
+find_device_prom_node(struct pci_pbm_info *pbm, struct pci_dev *pdev,
+		      struct device_node *bus_node,
+		      struct linux_prom_pci_registers **pregs,
+		      int *nregs)
 {
-	int node;
+	struct device_node *dp;
 
 	*nregs = 0;
 
@@ -57,24 +58,30 @@
 	     pdev->device == PCI_DEVICE_ID_SUN_TOMATILLO ||
 	     pdev->device == PCI_DEVICE_ID_SUN_SABRE ||
 	     pdev->device == PCI_DEVICE_ID_SUN_HUMMINGBIRD))
-		return bus_prom_node;
+		return bus_node;
 
-	node = prom_getchild(bus_prom_node);
-	while (node != 0) {
-		int err = prom_getproperty(node, "reg",
-					   (char *)pregs,
-					   sizeof(*pregs) * PROMREG_MAX);
-		if (err == 0 || err == -1)
+	dp = bus_node->child;
+	while (dp) {
+		struct linux_prom_pci_registers *regs;
+		struct property *prop;
+		int len;
+
+		prop = of_find_property(dp, "reg", &len);
+		if (!prop)
 			goto do_next_sibling;
-		if (((pregs[0].phys_hi >> 8) & 0xff) == pdev->devfn) {
-			*nregs = err / sizeof(*pregs);
-			return node;
+
+		regs = prop->value;
+		if (((regs[0].phys_hi >> 8) & 0xff) == pdev->devfn) {
+			*pregs = regs;
+			*nregs = len / sizeof(struct linux_prom_pci_registers);
+			return dp;
 		}
 
 	do_next_sibling:
-		node = prom_getsibling(node);
+		dp = dp->sibling;
 	}
-	return 0;
+
+	return NULL;
 }
 
 /* Older versions of OBP on PCI systems encode 64-bit MEM
@@ -131,15 +138,17 @@
  */
 static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm,
 				      struct pci_dev *pdev,
-				      int bus_prom_node)
+				      struct device_node *bus_node)
 {
-	struct linux_prom_pci_registers pregs[PROMREG_MAX];
+	struct linux_prom_pci_registers *pregs = NULL;
 	struct pcidev_cookie *pcp;
-	int device_prom_node, nregs, err;
+	struct device_node *dp;
+	struct property *prop;
+	int nregs, len;
 
-	device_prom_node = find_device_prom_node(pbm, pdev, bus_prom_node,
-						 pregs, &nregs);
-	if (device_prom_node == 0) {
+	dp = find_device_prom_node(pbm, pdev, bus_node,
+				   &pregs, &nregs);
+	if (!dp) {
 		/* If it is not in the OBP device tree then
 		 * there must be a damn good reason for it.
 		 *
@@ -153,45 +162,43 @@
 		return;
 	}
 
-	pcp = kmalloc(sizeof(*pcp), GFP_ATOMIC);
+	pcp = kzalloc(sizeof(*pcp), GFP_ATOMIC);
 	if (pcp == NULL) {
 		prom_printf("PCI_COOKIE: Fatal malloc error, aborting...\n");
 		prom_halt();
 	}
 	pcp->pbm = pbm;
-	pcp->prom_node = device_prom_node;
-	memcpy(pcp->prom_regs, pregs, sizeof(pcp->prom_regs));
+	pcp->prom_node = dp;
+	memcpy(pcp->prom_regs, pregs,
+	       nregs * sizeof(struct linux_prom_pci_registers));
 	pcp->num_prom_regs = nregs;
-	err = prom_getproperty(device_prom_node, "name",
-			       pcp->prom_name, sizeof(pcp->prom_name));
-	if (err > 0)
-		pcp->prom_name[err] = 0;
-	else
-		pcp->prom_name[0] = 0;
 
-	err = prom_getproperty(device_prom_node,
-			       "assigned-addresses",
-			       (char *)pcp->prom_assignments,
-			       sizeof(pcp->prom_assignments));
-	if (err == 0 || err == -1)
+	/* We can't have the pcidev_cookie assignments be just
+	 * direct pointers into the property value, since they
+	 * are potentially modified by the probing process.
+	 */
+	prop = of_find_property(dp, "assigned-addresses", &len);
+	if (!prop) {
 		pcp->num_prom_assignments = 0;
-	else
+	} else {
+		memcpy(pcp->prom_assignments, prop->value, len);
 		pcp->num_prom_assignments =
-			(err / sizeof(pcp->prom_assignments[0]));
+			(len / sizeof(pcp->prom_assignments[0]));
+	}
 
-	if (strcmp(pcp->prom_name, "ebus") == 0) {
-		struct linux_prom_ebus_ranges erng[PROM_PCIRNG_MAX];
+	if (strcmp(dp->name, "ebus") == 0) {
+		struct linux_prom_ebus_ranges *erng;
 		int iter;
 
 		/* EBUS is special... */
-		err = prom_getproperty(device_prom_node, "ranges",
-				       (char *)&erng[0], sizeof(erng));
-		if (err == 0 || err == -1) {
+		prop = of_find_property(dp, "ranges", &len);
+		if (!prop) {
 			prom_printf("EBUS: Fatal error, no range property\n");
 			prom_halt();
 		}
-		err = (err / sizeof(erng[0]));
-		for(iter = 0; iter < err; iter++) {
+		erng = prop->value;
+		len = (len / sizeof(erng[0]));
+		for (iter = 0; iter < len; iter++) {
 			struct linux_prom_ebus_ranges *ep = &erng[iter];
 			struct linux_prom_pci_registers *ap;
 
@@ -203,7 +210,7 @@
 			ap->size_hi = 0;
 			ap->size_lo = ep->size;
 		}
-		pcp->num_prom_assignments = err;
+		pcp->num_prom_assignments = len;
 	}
 
 	fixup_obp_assignments(pdev, pcp);
@@ -213,7 +220,7 @@
 
 void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus,
 				    struct pci_pbm_info *pbm,
-				    int prom_node)
+				    struct device_node *dp)
 {
 	struct pci_dev *pdev, *pdev_next;
 	struct pci_bus *this_pbus, *pbus_next;
@@ -221,7 +228,7 @@
 	/* This must be _safe because the cookie fillin
 	   routine can delete devices from the tree.  */
 	list_for_each_entry_safe(pdev, pdev_next, &pbus->devices, bus_list)
-		pdev_cookie_fillin(pbm, pdev, prom_node);
+		pdev_cookie_fillin(pbm, pdev, dp);
 
 	list_for_each_entry_safe(this_pbus, pbus_next, &pbus->children, node) {
 		struct pcidev_cookie *pcp = this_pbus->self->sysdata;
@@ -244,7 +251,6 @@
 	if (res)
 		prom_printf("PCI: RES[%016lx-->%016lx:(%lx)]\n",
 			    res->start, res->end, res->flags);
-	prom_printf("Please email this information to davem@redhat.com\n");
 	if (do_prom_halt)
 		prom_halt();
 }
@@ -276,8 +282,7 @@
 		return &pbm->mem_space;
 
 	default:
-		printk("PCI: What is resource space %x? "
-		       "Tell davem@redhat.com about it!\n", space);
+		printk("PCI: What is resource space %x?\n", space);
 		return NULL;
 	};
 }
@@ -572,50 +577,51 @@
 					    struct pci_dev *pbus,
 					    struct pci_dev *pdev,
 					    unsigned int interrupt,
-					    unsigned int *cnode)
+					    struct device_node **cnode)
 {
-	struct linux_prom_pci_intmap imap[PROM_PCIIMAP_MAX];
-	struct linux_prom_pci_intmask imask;
+	struct linux_prom_pci_intmap *imap;
+	struct linux_prom_pci_intmask *imask;
 	struct pcidev_cookie *pbus_pcp = pbus->sysdata;
 	struct pcidev_cookie *pdev_pcp = pdev->sysdata;
 	struct linux_prom_pci_registers *pregs = pdev_pcp->prom_regs;
+	struct property *prop;
 	int plen, num_imap, i;
 	unsigned int hi, mid, lo, irq, orig_interrupt;
 
 	*cnode = pbus_pcp->prom_node;
 
-	plen = prom_getproperty(pbus_pcp->prom_node, "interrupt-map",
-				(char *) &imap[0], sizeof(imap));
-	if (plen <= 0 ||
+	prop = of_find_property(pbus_pcp->prom_node, "interrupt-map", &plen);
+	if (!prop ||
 	    (plen % sizeof(struct linux_prom_pci_intmap)) != 0) {
 		printk("%s: Device %s interrupt-map has bad len %d\n",
 		       pbm->name, pci_name(pbus), plen);
 		goto no_intmap;
 	}
+	imap = prop->value;
 	num_imap = plen / sizeof(struct linux_prom_pci_intmap);
 
-	plen = prom_getproperty(pbus_pcp->prom_node, "interrupt-map-mask",
-				(char *) &imask, sizeof(imask));
-	if (plen <= 0 ||
+	prop = of_find_property(pbus_pcp->prom_node, "interrupt-map-mask", &plen);
+	if (!prop ||
 	    (plen % sizeof(struct linux_prom_pci_intmask)) != 0) {
 		printk("%s: Device %s interrupt-map-mask has bad len %d\n",
 		       pbm->name, pci_name(pbus), plen);
 		goto no_intmap;
 	}
+	imask = prop->value;
 
 	orig_interrupt = interrupt;
 
-	hi   = pregs->phys_hi & imask.phys_hi;
-	mid  = pregs->phys_mid & imask.phys_mid;
-	lo   = pregs->phys_lo & imask.phys_lo;
-	irq  = interrupt & imask.interrupt;
+	hi   = pregs->phys_hi & imask->phys_hi;
+	mid  = pregs->phys_mid & imask->phys_mid;
+	lo   = pregs->phys_lo & imask->phys_lo;
+	irq  = interrupt & imask->interrupt;
 
 	for (i = 0; i < num_imap; i++) {
 		if (imap[i].phys_hi  == hi   &&
 		    imap[i].phys_mid == mid  &&
 		    imap[i].phys_lo  == lo   &&
 		    imap[i].interrupt == irq) {
-			*cnode = imap[i].cnode;
+			*cnode = of_find_node_by_phandle(imap[i].cnode);
 			interrupt = imap[i].cinterrupt;
 		}
 	}
@@ -638,21 +644,22 @@
  * all interrupt translations are complete, else we should use that node's
  * "reg" property to apply the PBM's "interrupt-{map,mask}" to the interrupt.
  */
-static unsigned int __init pci_intmap_match_to_root(struct pci_pbm_info *pbm,
-						    struct pci_dev *pdev,
-						    unsigned int *interrupt)
+static struct device_node * __init
+pci_intmap_match_to_root(struct pci_pbm_info *pbm,
+			 struct pci_dev *pdev,
+			 unsigned int *interrupt)
 {
 	struct pci_dev *toplevel_pdev = pdev;
 	struct pcidev_cookie *toplevel_pcp = toplevel_pdev->sysdata;
-	unsigned int cnode = toplevel_pcp->prom_node;
+	struct device_node *cnode = toplevel_pcp->prom_node;
 
 	while (pdev->bus->number != pbm->pci_first_busno) {
 		struct pci_dev *pbus = pdev->bus->self;
 		struct pcidev_cookie *pcp = pbus->sysdata;
-		int plen;
+		struct property *prop;
 
-		plen = prom_getproplen(pcp->prom_node, "interrupt-map");
-		if (plen <= 0) {
+		prop = of_find_property(pcp->prom_node, "interrupt-map", NULL);
+		if (!prop) {
 			*interrupt = pci_slot_swivel(pbm, toplevel_pdev,
 						     pdev, *interrupt);
 			cnode = pcp->prom_node;
@@ -669,7 +676,7 @@
 		}
 		pdev = pbus;
 
-		if (cnode == pbm->prom_node->node)
+		if (cnode == pbm->prom_node)
 			break;
 	}
 
@@ -680,21 +687,24 @@
 {
 	struct pcidev_cookie *dev_pcp = pdev->sysdata;
 	struct pci_pbm_info *pbm = dev_pcp->pbm;
-	struct linux_prom_pci_registers reg[PROMREG_MAX];
+	struct linux_prom_pci_registers *reg;
+	struct device_node *cnode;
+	struct property *prop;
 	unsigned int hi, mid, lo, irq;
-	int i, cnode, plen;
+	int i, plen;
 
 	cnode = pci_intmap_match_to_root(pbm, pdev, interrupt);
-	if (cnode == pbm->prom_node->node)
+	if (cnode == pbm->prom_node)
 		goto success;
 
-	plen = prom_getproperty(cnode, "reg", (char *) reg, sizeof(reg));
-	if (plen <= 0 ||
+	prop = of_find_property(cnode, "reg", &plen);
+	if (!prop ||
 	    (plen % sizeof(struct linux_prom_pci_registers)) != 0) {
-		printk("%s: OBP node %x reg property has bad len %d\n",
-		       pbm->name, cnode, plen);
+		printk("%s: OBP node %s reg property has bad len %d\n",
+		       pbm->name, cnode->full_name, plen);
 		goto fail;
 	}
+	reg = prop->value;
 
 	hi   = reg[0].phys_hi & pbm->pbm_intmask->phys_hi;
 	mid  = reg[0].phys_mid & pbm->pbm_intmask->phys_mid;
@@ -734,8 +744,8 @@
 	struct pci_controller_info *p = pbm->parent;
 	unsigned int portid = pbm->portid;
 	unsigned int prom_irq;
-	int prom_node = pcp->prom_node;
-	int err;
+	struct device_node *dp = pcp->prom_node;
+	struct property *prop;
 
 	/* If this is an empty EBUS device, sometimes OBP fails to
 	 * give it a valid fully specified interrupts property.
@@ -746,17 +756,17 @@
 	 */
 	if (pdev->vendor == PCI_VENDOR_ID_SUN &&
 	    pdev->device == PCI_DEVICE_ID_SUN_EBUS &&
-	    !prom_getchild(prom_node)) {
+	    !dp->child) {
 		pdev->irq = 0;
 		return;
 	}
 
-	err = prom_getproperty(prom_node, "interrupts",
-			       (char *)&prom_irq, sizeof(prom_irq));
-	if (err == 0 || err == -1) {
+	prop = of_find_property(dp, "interrupts", NULL);
+	if (!prop) {
 		pdev->irq = 0;
 		return;
 	}
+	prom_irq = *(unsigned int *) prop->value;
 
 	if (tlb_type != hypervisor) {
 		/* Fully specified already? */
diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h
index 6c32059..971e2be 100644
--- a/arch/sparc64/kernel/pci_impl.h
+++ b/arch/sparc64/kernel/pci_impl.h
@@ -10,6 +10,7 @@
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <asm/io.h>
+#include <asm/prom.h>
 
 extern struct pci_controller_info *pci_controller_root;
 
@@ -19,7 +20,7 @@
 extern void pci_fixup_host_bridge_self(struct pci_bus *pbus);
 extern void pci_fill_in_pbm_cookies(struct pci_bus *pbus,
 				    struct pci_pbm_info *pbm,
-				    int prom_node);
+				    struct device_node *prom_node);
 extern void pci_record_assignments(struct pci_pbm_info *pbm,
 				   struct pci_bus *pbus);
 extern void pci_assign_unassigned(struct pci_pbm_info *pbm,
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index 40c2b68..5b2261e 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -1104,7 +1104,7 @@
 	pci_fixup_host_bridge_self(pbm->pci_bus);
 	pbm->pci_bus->self->sysdata = cookie;
 
-	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node->node);
+	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
 	pci_record_assignments(pbm, pbm->pci_bus);
 	pci_assign_unassigned(pbm, pbm->pci_bus);
 	pci_fixup_irq(pbm, pbm->pci_bus);
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index 4ce7b46..26f194c 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -1161,7 +1161,7 @@
 
 		pbus->sysdata = pbm;
 		pbm->pci_bus = pbus;
-		pci_fill_in_pbm_cookies(pbus, pbm, pbm->prom_node->node);
+		pci_fill_in_pbm_cookies(pbus, pbm, pbm->prom_node);
 		pci_record_assignments(pbm, pbus);
 		pci_assign_unassigned(pbm, pbus);
 		pci_fixup_irq(pbm, pbus);
@@ -1174,7 +1174,7 @@
 		pbm = &p->pbm_A;
 		sabre_bus->sysdata = pbm;
 		pbm->pci_bus = sabre_bus;
-		pci_fill_in_pbm_cookies(sabre_bus, pbm, pbm->prom_node->node);
+		pci_fill_in_pbm_cookies(sabre_bus, pbm, pbm->prom_node);
 		pci_record_assignments(pbm, sabre_bus);
 		pci_assign_unassigned(pbm, sabre_bus);
 		pci_fixup_irq(pbm, sabre_bus);
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
index d268200..f16449c 100644
--- a/arch/sparc64/kernel/pci_schizo.c
+++ b/arch/sparc64/kernel/pci_schizo.c
@@ -1438,7 +1438,7 @@
 	pci_fixup_host_bridge_self(pbm->pci_bus);
 	pbm->pci_bus->self->sysdata = cookie;
 
-	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node->node);
+	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
 	pci_record_assignments(pbm, pbm->pci_bus);
 	pci_assign_unassigned(pbm, pbm->pci_bus);
 	pci_fixup_irq(pbm, pbm->pci_bus);
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index b275c7d..b69e227 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -814,8 +814,7 @@
 	pci_fixup_host_bridge_self(pbm->pci_bus);
 	pbm->pci_bus->self->sysdata = cookie;
 #endif
-	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm,
-				pbm->prom_node->node);
+	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
 	pci_record_assignments(pbm, pbm->pci_bus);
 	pci_assign_unassigned(pbm, pbm->pci_bus);
 	pci_fixup_irq(pbm, pbm->pci_bus);
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
index 0a32b10..fb112c3 100644
--- a/arch/sparc64/kernel/prom.c
+++ b/arch/sparc64/kernel/prom.c
@@ -20,6 +20,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
+#include <linux/module.h>
 
 #include <asm/prom.h>
 #include <asm/oplib.h>
@@ -63,6 +64,17 @@
 	return np;
 }
 
+struct device_node *of_find_node_by_phandle(phandle handle)
+{
+	struct device_node *np;
+
+	for (np = allnodes; np != 0; np = np->allnext)
+		if (np->node == handle)
+			break;
+
+	return np;
+}
+
 struct device_node *of_find_node_by_name(struct device_node *from,
 	const char *name)
 {
@@ -103,6 +115,18 @@
 	}
 	return pp;
 }
+EXPORT_SYMBOL(of_find_property);
+
+/*
+ * Find a property with a given name for a given node
+ * and return the value.
+ */
+void *of_get_property(struct device_node *np, const char *name, int *lenp)
+{
+	struct property *pp = of_find_property(np,name,lenp);
+	return pp ? pp->value : NULL;
+}
+EXPORT_SYMBOL(of_get_property);
 
 int of_getintprop_default(struct device_node *np, const char *name, int def)
 {
@@ -115,6 +139,7 @@
 
 	return *(int *) prop->value;
 }
+EXPORT_SYMBOL(of_getintprop_default);
 
 static unsigned int prom_early_allocated;
 
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 38cd30c..5248670 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -2880,17 +2880,20 @@
 #if defined(__sparc__)
 	struct pci_dev *pdev = gp->pdev;
 	struct pcidev_cookie *pcp = pdev->sysdata;
-	int node = -1;
+	int use_idprom = 1;
 
 	if (pcp != NULL) {
-		node = pcp->prom_node;
-		if (prom_getproplen(node, "local-mac-address") == 6)
-			prom_getproperty(node, "local-mac-address",
-					 dev->dev_addr, 6);
-		else
-			node = -1;
+		unsigned char *addr;
+		int len;
+
+		addr = of_get_property(pcp->prom_node, "local-mac-address",
+				       &len);
+		if (addr && len == 6) {
+			use_idprom = 0;
+			memcpy(dev->dev_addr, addr, 6);
+		}
 	}
-	if (node == -1)
+	if (use_idprom)
 		memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
 #elif defined(CONFIG_PPC_PMAC)
 	unsigned char *addr;
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index bd5d266..b0d4527 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -3013,7 +3013,6 @@
 	struct quattro *qp = NULL;
 #ifdef __sparc__
 	struct pcidev_cookie *pcp;
-	int node;
 #endif
 	struct happy_meal *hp;
 	struct net_device *dev;
@@ -3026,13 +3025,12 @@
 	/* Now make sure pci_dev cookie is there. */
 #ifdef __sparc__
 	pcp = pdev->sysdata;
-	if (pcp == NULL || pcp->prom_node == -1) {
+	if (pcp == NULL) {
 		printk(KERN_ERR "happymeal(PCI): Some PCI device info missing\n");
 		return -ENODEV;
 	}
-	node = pcp->prom_node;
 	
-	prom_getstring(node, "name", prom_name, sizeof(prom_name));
+	strcpy(prom_name, pcp->prom_node->name);
 #else
 	if (is_quattro_p(pdev))
 		strcpy(prom_name, "SUNW,qfe");
@@ -3104,10 +3102,14 @@
 		macaddr[5]++;
 	} else {
 #ifdef __sparc__
+		unsigned char *addr;
+		int len;
+
 		if (qfe_slot != -1 &&
-		    prom_getproplen(node, "local-mac-address") == 6) {
-			prom_getproperty(node, "local-mac-address",
-					 dev->dev_addr, 6);
+		    (addr = of_get_property(pcp->prom_node,
+					    "local-mac-address", &len)) != NULL
+		    && len == 6) {
+			memcpy(dev->dev_addr, addr, 6);
 		} else {
 			memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
 		}
@@ -3124,7 +3126,7 @@
 	hp->tcvregs    = (hpreg_base + 0x7000UL);
 
 #ifdef __sparc__
-	hp->hm_revision = prom_getintdefault(node, "hm-rev", 0xff);
+	hp->hm_revision = of_getintprop_default(pcp->prom_node, "hm-rev", 0xff);
 	if (hp->hm_revision == 0xff) {
 		unsigned char prev;
 
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index e3e380f..35f9316 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -10549,11 +10549,13 @@
 	struct pcidev_cookie *pcp = pdev->sysdata;
 
 	if (pcp != NULL) {
-		int node = pcp->prom_node;
+		unsigned char *addr;
+		int len;
 
-		if (prom_getproplen(node, "local-mac-address") == 6) {
-			prom_getproperty(node, "local-mac-address",
-					 dev->dev_addr, 6);
+		addr = of_get_property(pcp->prom_node, "local-mac-address",
+					&len);
+		if (addr && len == 6) {
+			memcpy(dev->dev_addr, addr, 6);
 			memcpy(dev->perm_addr, dev->dev_addr, 6);
 			return 0;
 		}
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index cabdf89..e0de667 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1550,10 +1550,14 @@
 			dev->dev_addr[i] = last_phys_addr[i];
 		dev->dev_addr[i] = last_phys_addr[i] + 1;
 #if defined(__sparc__)
-		if ((pcp != NULL) && prom_getproplen(pcp->prom_node,
-			"local-mac-address") == 6) {
-			prom_getproperty(pcp->prom_node, "local-mac-address",
-			    dev->dev_addr, 6);
+		if (pcp) {
+			unsigned char *addr;
+			int len;
+		  
+			addr = of_get_property(pcp->prom_node,
+					       "local-mac-address", &len);
+			if (addr && len == 6)
+				memcpy(dev->dev_addr, addr, 6);
 		}
 #endif
 #if defined(__i386__) || defined(__x86_64__)	/* Patch up x86 BIOS bug. */
diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c
index 239e108..cf5b476 100644
--- a/drivers/sbus/char/openprom.c
+++ b/drivers/sbus/char/openprom.c
@@ -243,8 +243,8 @@
 					      ((int *) opp->oprom_array)[1]);
 
 			pcp = pdev->sysdata;
-			if (pcp != NULL && pcp->prom_node != -1 && pcp->prom_node) {
-				node = pcp->prom_node;
+			if (pcp != NULL) {
+				node = pcp->prom_node->node;
 				data->current_node = node;
 				*((int *)opp->oprom_array) = node;
 				opp->oprom_size = sizeof(int);
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index eb6aa42..c054bb2 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -2966,7 +2966,7 @@
 	}
 
 	pcp = pdev->sysdata;
-	if (node == pcp->prom_node) {
+	if (node == pcp->prom_node->node) {
 		struct fb_var_screeninfo *var = &default_var;
 		unsigned int N, P, Q, M, T, R;
 		u32 v_total, h_total;
diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h
index 142cc40..cebe80b 100644
--- a/include/asm-sparc64/pbm.h
+++ b/include/asm-sparc64/pbm.h
@@ -227,8 +227,7 @@
  */
 struct pcidev_cookie {
 	struct pci_pbm_info		*pbm;
-	char				prom_name[64];
-	int				prom_node;
+	struct device_node		*prom_node;
 	struct linux_prom_pci_registers	prom_regs[PROMREG_MAX];
 	int num_prom_regs;
 	struct linux_prom_pci_registers prom_assignments[PROMREG_MAX];
diff --git a/include/asm-sparc64/prom.h b/include/asm-sparc64/prom.h
index d0187b3..062ae6e 100644
--- a/include/asm-sparc64/prom.h
+++ b/include/asm-sparc64/prom.h
@@ -76,12 +76,15 @@
 	for (dn = of_find_node_by_type(NULL, type); dn; \
 	     dn = of_find_node_by_type(dn, type))
 extern struct device_node *of_find_node_by_path(const char *path);
+extern struct device_node *of_find_node_by_phandle(phandle handle);
 extern struct device_node *of_get_parent(const struct device_node *node);
 extern struct device_node *of_get_next_child(const struct device_node *node,
 					     struct device_node *prev);
 extern struct property *of_find_property(struct device_node *np,
 					 const char *name,
 					 int *lenp);
+extern void *of_get_property(struct device_node *node, const char *name,
+			     int *lenp);
 extern int of_getintprop_default(struct device_node *np,
 				 const char *name,
 				 int def);