summaryrefslogtreecommitdiffstats
path: root/sys/dev/fdt/fdt_common.c
diff options
context:
space:
mode:
authorraj <raj@FreeBSD.org>2012-03-04 19:22:52 +0000
committerraj <raj@FreeBSD.org>2012-03-04 19:22:52 +0000
commite1d4e01ec9ff06eadf96ecaa2e282942720e90fa (patch)
tree78b948ce6795b5c835b79387bde8f64f7f1b2827 /sys/dev/fdt/fdt_common.c
parent4d1957ce4f39f16b06c0ec758cb0d09cf2e2bc1c (diff)
downloadFreeBSD-src-e1d4e01ec9ff06eadf96ecaa2e282942720e90fa.zip
FreeBSD-src-e1d4e01ec9ff06eadf96ecaa2e282942720e90fa.tar.gz
Respect phy-handle property in Ethernet nodes of the device tree.
This lets specify whereabouts of the parent PHY for a given MAC node (and get rid of ugly kludges in mge(4) and tsec(4)). Obtained from: Semihalf MFC after: 1 week
Diffstat (limited to 'sys/dev/fdt/fdt_common.c')
-rw-r--r--sys/dev/fdt/fdt_common.c45
1 files changed, 44 insertions, 1 deletions
diff --git a/sys/dev/fdt/fdt_common.c b/sys/dev/fdt/fdt_common.c
index 8702df2..bf18e34 100644
--- a/sys/dev/fdt/fdt_common.c
+++ b/sys/dev/fdt/fdt_common.c
@@ -542,11 +542,13 @@ out:
}
int
-fdt_get_phyaddr(phandle_t node, int *phy_addr)
+fdt_get_phyaddr(phandle_t node, device_t dev, int *phy_addr, void **phy_sc)
{
phandle_t phy_node;
ihandle_t phy_ihandle;
pcell_t phy_handle, phy_reg;
+ uint32_t i;
+ device_t parent, child;
if (OF_getprop(node, "phy-handle", (void *)&phy_handle,
sizeof(phy_handle)) <= 0)
@@ -561,6 +563,47 @@ fdt_get_phyaddr(phandle_t node, int *phy_addr)
return (ENXIO);
*phy_addr = fdt32_to_cpu(phy_reg);
+
+ /*
+ * Search for softc used to communicate with phy.
+ */
+
+ /*
+ * Step 1: Search for ancestor of the phy-node with a "phy-handle"
+ * property set.
+ */
+ phy_node = OF_parent(phy_node);
+ while (phy_node != 0) {
+ if (OF_getprop(phy_node, "phy-handle", (void *)&phy_handle,
+ sizeof(phy_handle)) > 0)
+ break;
+ phy_node = OF_parent(phy_node);
+ }
+ if (phy_node == 0)
+ return (ENXIO);
+
+ /*
+ * Step 2: For each device with the same parent and name as ours
+ * compare its node with the one found in step 1, ancestor of phy
+ * node (stored in phy_node).
+ */
+ parent = device_get_parent(dev);
+ i = 0;
+ child = device_find_child(parent, device_get_name(dev), i);
+ while (child != NULL) {
+ if (ofw_bus_get_node(child) == phy_node)
+ break;
+ i++;
+ child = device_find_child(parent, device_get_name(dev), i);
+ }
+ if (child == NULL)
+ return (ENXIO);
+
+ /*
+ * Use softc of the device found.
+ */
+ *phy_sc = (void *)device_get_softc(child);
+
return (0);
}
OpenPOWER on IntegriCloud