aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafal Jaworowski <raj@FreeBSD.org>2012-03-04 19:22:52 +0000
committerRafal Jaworowski <raj@FreeBSD.org>2012-03-04 19:22:52 +0000
commitaa15e881bb453670d9155ace6c4b1885b15056e1 (patch)
tree78b948ce6795b5c835b79387bde8f64f7f1b2827
parent1c7792950cb17570e4911cf341f4145861e0bc0c (diff)
downloadsrc-aa15e881bb453670d9155ace6c4b1885b15056e1.tar.gz
src-aa15e881bb453670d9155ace6c4b1885b15056e1.zip
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
Notes
Notes: svn path=/head/; revision=232518
-rw-r--r--sys/boot/fdt/dts/db78100.dts15
-rw-r--r--sys/dev/fdt/fdt_common.c45
-rw-r--r--sys/dev/fdt/fdt_common.h2
-rw-r--r--sys/dev/mge/if_mge.c21
-rw-r--r--sys/dev/mge/if_mgevar.h2
-rw-r--r--sys/dev/tsec/if_tsec.c28
-rw-r--r--sys/dev/tsec/if_tsec.h1
-rw-r--r--sys/dev/tsec/if_tsec_fdt.c9
8 files changed, 75 insertions, 48 deletions
diff --git a/sys/boot/fdt/dts/db78100.dts b/sys/boot/fdt/dts/db78100.dts
index 015768164826..caebaf18e8bf 100644
--- a/sys/boot/fdt/dts/db78100.dts
+++ b/sys/boot/fdt/dts/db78100.dts
@@ -221,6 +221,9 @@
phy0: ethernet-phy@0 {
reg = <0x8>;
};
+ phy1: ethernet-phy@1 {
+ reg = <0x9>;
+ };
};
};
@@ -234,17 +237,7 @@
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <45 46 47 44 70>;
interrupt-parent = <&PIC>;
- phy-handle = <&phy0>;
-
- mdio@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "mrvl,mdio";
-
- phy0: ethernet-phy@0 {
- reg = <0x9>;
- };
- };
+ phy-handle = <&phy1>;
};
serial0: serial@12000 {
diff --git a/sys/dev/fdt/fdt_common.c b/sys/dev/fdt/fdt_common.c
index 8702df284e82..bf18e3485838 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);
}
diff --git a/sys/dev/fdt/fdt_common.h b/sys/dev/fdt/fdt_common.h
index dc57dddde087..0bedb91916a1 100644
--- a/sys/dev/fdt/fdt_common.h
+++ b/sys/dev/fdt/fdt_common.h
@@ -89,7 +89,7 @@ int fdt_data_to_res(pcell_t *, int, int, u_long *, u_long *);
int fdt_data_verify(void *, int);
phandle_t fdt_find_compatible(phandle_t, const char *, int);
int fdt_get_mem_regions(struct mem_region *, int *, uint32_t *);
-int fdt_get_phyaddr(phandle_t node, int *);
+int fdt_get_phyaddr(phandle_t, device_t, int *, void **);
int fdt_immr_addr(vm_offset_t);
int fdt_regsize(phandle_t, u_long *, u_long *);
int fdt_intr_decode(phandle_t, pcell_t *, int *, int *, int *);
diff --git a/sys/dev/mge/if_mge.c b/sys/dev/mge/if_mge.c
index 824f8a21a615..5b7a78d2dc90 100644
--- a/sys/dev/mge/if_mge.c
+++ b/sys/dev/mge/if_mge.c
@@ -79,9 +79,6 @@ __FBSDID("$FreeBSD$");
#include "miibus_if.h"
-/* PHY registers are in the address space of the first mge unit */
-static struct mge_softc *sc_mge0 = NULL;
-
static int mge_probe(device_t dev);
static int mge_attach(device_t dev);
static int mge_detach(device_t dev);
@@ -635,14 +632,11 @@ mge_attach(device_t dev)
sc->dev = dev;
sc->node = ofw_bus_get_node(dev);
- if (device_get_unit(dev) == 0)
- sc_mge0 = sc;
-
/* Set chip version-dependent parameters */
mge_ver_params(sc);
- /* Get phy address from fdt */
- if (fdt_get_phyaddr(sc->node, &phy) != 0)
+ /* Get phy address and used softc from fdt */
+ if (fdt_get_phyaddr(sc->node, sc->dev, &phy, (void **)&sc->phy_sc) != 0)
return (ENXIO);
/* Initialize mutexes */
@@ -1294,17 +1288,18 @@ mge_miibus_readreg(device_t dev, int phy, int reg)
sc = device_get_softc(dev);
- MGE_WRITE(sc_mge0, MGE_REG_SMI, 0x1fffffff &
+ MGE_WRITE(sc->phy_sc, MGE_REG_SMI, 0x1fffffff &
(MGE_SMI_READ | (reg << 21) | (phy << 16)));
retries = MGE_SMI_READ_RETRIES;
- while (--retries && !(MGE_READ(sc_mge0, MGE_REG_SMI) & MGE_SMI_READVALID))
+ while (--retries &&
+ !(MGE_READ(sc->phy_sc, MGE_REG_SMI) & MGE_SMI_READVALID))
DELAY(MGE_SMI_READ_DELAY);
if (retries == 0)
device_printf(dev, "Timeout while reading from PHY\n");
- return (MGE_READ(sc_mge0, MGE_REG_SMI) & 0xffff);
+ return (MGE_READ(sc->phy_sc, MGE_REG_SMI) & 0xffff);
}
static int
@@ -1315,11 +1310,11 @@ mge_miibus_writereg(device_t dev, int phy, int reg, int value)
sc = device_get_softc(dev);
- MGE_WRITE(sc_mge0, MGE_REG_SMI, 0x1fffffff &
+ MGE_WRITE(sc->phy_sc, MGE_REG_SMI, 0x1fffffff &
(MGE_SMI_WRITE | (reg << 21) | (phy << 16) | (value & 0xffff)));
retries = MGE_SMI_WRITE_RETRIES;
- while (--retries && MGE_READ(sc_mge0, MGE_REG_SMI) & MGE_SMI_BUSY)
+ while (--retries && MGE_READ(sc->phy_sc, MGE_REG_SMI) & MGE_SMI_BUSY)
DELAY(MGE_SMI_WRITE_DELAY);
if (retries == 0)
diff --git a/sys/dev/mge/if_mgevar.h b/sys/dev/mge/if_mgevar.h
index 5f96fa760904..2ce6b6ffe71e 100644
--- a/sys/dev/mge/if_mgevar.h
+++ b/sys/dev/mge/if_mgevar.h
@@ -103,6 +103,8 @@ struct mge_softc {
uint32_t mge_tx_tok_cnt;
uint16_t mge_mtu;
int mge_ver;
+
+ struct mge_softc *phy_sc;
};
diff --git a/sys/dev/tsec/if_tsec.c b/sys/dev/tsec/if_tsec.c
index ce257ab3a6b1..2e54129e5754 100644
--- a/sys/dev/tsec/if_tsec.c
+++ b/sys/dev/tsec/if_tsec.c
@@ -106,8 +106,6 @@ static void tsec_offload_process_frame(struct tsec_softc *sc,
static void tsec_setup_multicast(struct tsec_softc *sc);
static int tsec_set_mtu(struct tsec_softc *sc, unsigned int mtu);
-struct tsec_softc *tsec0_sc = NULL; /* XXX ugly hack! */
-
devclass_t tsec_devclass;
DRIVER_MODULE(miibus, tsec, miibus_driver, miibus_devclass, 0, 0);
MODULE_DEPEND(tsec, ether, 1, 1, 1);
@@ -406,14 +404,14 @@ tsec_init_locked(struct tsec_softc *sc)
TSEC_WRITE(sc, TSEC_REG_TBIPA, 5);
/* Step 6: Reset the management interface */
- TSEC_WRITE(tsec0_sc, TSEC_REG_MIIMCFG, TSEC_MIIMCFG_RESETMGMT);
+ TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCFG, TSEC_MIIMCFG_RESETMGMT);
/* Step 7: Setup the MII Mgmt clock speed */
- TSEC_WRITE(tsec0_sc, TSEC_REG_MIIMCFG, TSEC_MIIMCFG_CLKDIV28);
+ TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCFG, TSEC_MIIMCFG_CLKDIV28);
/* Step 8: Read MII Mgmt indicator register and check for Busy = 0 */
timeout = TSEC_READ_RETRY;
- while (--timeout && (TSEC_READ(tsec0_sc, TSEC_REG_MIIMIND) &
+ while (--timeout && (TSEC_READ(sc->phy_sc, TSEC_REG_MIIMIND) &
TSEC_MIIMIND_BUSY))
DELAY(TSEC_READ_DELAY);
if (timeout == 0) {
@@ -1561,21 +1559,21 @@ tsec_miibus_readreg(device_t dev, int phy, int reg)
struct tsec_softc *sc;
uint32_t timeout;
- sc = tsec0_sc;
+ sc = device_get_softc(dev);
- TSEC_WRITE(sc, TSEC_REG_MIIMADD, (phy << 8) | reg);
- TSEC_WRITE(sc, TSEC_REG_MIIMCOM, 0);
- TSEC_WRITE(sc, TSEC_REG_MIIMCOM, TSEC_MIIMCOM_READCYCLE);
+ TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMADD, (phy << 8) | reg);
+ TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCOM, 0);
+ TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCOM, TSEC_MIIMCOM_READCYCLE);
timeout = TSEC_READ_RETRY;
- while (--timeout && TSEC_READ(sc, TSEC_REG_MIIMIND) &
+ while (--timeout && TSEC_READ(sc->phy_sc, TSEC_REG_MIIMIND) &
(TSEC_MIIMIND_NOTVALID | TSEC_MIIMIND_BUSY))
DELAY(TSEC_READ_DELAY);
if (timeout == 0)
device_printf(dev, "Timeout while reading from PHY!\n");
- return (TSEC_READ(sc, TSEC_REG_MIIMSTAT));
+ return (TSEC_READ(sc->phy_sc, TSEC_REG_MIIMSTAT));
}
int
@@ -1584,13 +1582,13 @@ tsec_miibus_writereg(device_t dev, int phy, int reg, int value)
struct tsec_softc *sc;
uint32_t timeout;
- sc = tsec0_sc;
+ sc = device_get_softc(dev);
- TSEC_WRITE(sc, TSEC_REG_MIIMADD, (phy << 8) | reg);
- TSEC_WRITE(sc, TSEC_REG_MIIMCON, value);
+ TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMADD, (phy << 8) | reg);
+ TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCON, value);
timeout = TSEC_READ_RETRY;
- while (--timeout && (TSEC_READ(sc, TSEC_REG_MIIMIND) &
+ while (--timeout && (TSEC_READ(sc->phy_sc, TSEC_REG_MIIMIND) &
TSEC_MIIMIND_BUSY))
DELAY(TSEC_READ_DELAY);
diff --git a/sys/dev/tsec/if_tsec.h b/sys/dev/tsec/if_tsec.h
index b98032202548..cfba3f6bcc3b 100644
--- a/sys/dev/tsec/if_tsec.h
+++ b/sys/dev/tsec/if_tsec.h
@@ -133,6 +133,7 @@ struct tsec_softc {
struct mbuf *frame;
int phyaddr;
+ struct tsec_softc *phy_sc;
};
/* interface to get/put generic objects */
diff --git a/sys/dev/tsec/if_tsec_fdt.c b/sys/dev/tsec/if_tsec_fdt.c
index 55132eb96811..7f6f414a35d8 100644
--- a/sys/dev/tsec/if_tsec_fdt.c
+++ b/sys/dev/tsec/if_tsec_fdt.c
@@ -68,8 +68,6 @@ __FBSDID("$FreeBSD$");
#define TSEC_RID_RXIRQ 1
#define TSEC_RID_ERRIRQ 2
-extern struct tsec_softc *tsec0_sc;
-
static int tsec_fdt_probe(device_t dev);
static int tsec_fdt_attach(device_t dev);
static int tsec_fdt_detach(device_t dev);
@@ -156,12 +154,9 @@ tsec_fdt_attach(device_t dev)
sc->dev = dev;
sc->node = ofw_bus_get_node(dev);
- /* XXX add comment on weird FSL's MII registers access design */
- if (device_get_unit(dev) == 0)
- tsec0_sc = sc;
-
/* Get phy address from fdt */
- if (fdt_get_phyaddr(sc->node, &sc->phyaddr) != 0)
+ if (fdt_get_phyaddr(sc->node, sc->dev, &sc->phyaddr,
+ (void **)&sc->phy_sc) != 0)
return (ENXIO);
/* Init timer */