Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 4 Mar 2012 19:22:53 +0000 (UTC)
From:      Rafal Jaworowski <raj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r232518 - in head/sys: boot/fdt/dts dev/fdt dev/mge dev/tsec
Message-ID:  <201203041922.q24JMria049221@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: raj
Date: Sun Mar  4 19:22:52 2012
New Revision: 232518
URL: http://svn.freebsd.org/changeset/base/232518

Log:
  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

Modified:
  head/sys/boot/fdt/dts/db78100.dts
  head/sys/dev/fdt/fdt_common.c
  head/sys/dev/fdt/fdt_common.h
  head/sys/dev/mge/if_mge.c
  head/sys/dev/mge/if_mgevar.h
  head/sys/dev/tsec/if_tsec.c
  head/sys/dev/tsec/if_tsec.h
  head/sys/dev/tsec/if_tsec_fdt.c

Modified: head/sys/boot/fdt/dts/db78100.dts
==============================================================================
--- head/sys/boot/fdt/dts/db78100.dts	Sun Mar  4 18:59:38 2012	(r232517)
+++ head/sys/boot/fdt/dts/db78100.dts	Sun Mar  4 19:22:52 2012	(r232518)
@@ -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 {

Modified: head/sys/dev/fdt/fdt_common.c
==============================================================================
--- head/sys/dev/fdt/fdt_common.c	Sun Mar  4 18:59:38 2012	(r232517)
+++ head/sys/dev/fdt/fdt_common.c	Sun Mar  4 19:22:52 2012	(r232518)
@@ -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
 		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);
 }
 

Modified: head/sys/dev/fdt/fdt_common.h
==============================================================================
--- head/sys/dev/fdt/fdt_common.h	Sun Mar  4 18:59:38 2012	(r232517)
+++ head/sys/dev/fdt/fdt_common.h	Sun Mar  4 19:22:52 2012	(r232518)
@@ -89,7 +89,7 @@ int fdt_data_to_res(pcell_t *, int, int,
 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 *);

Modified: head/sys/dev/mge/if_mge.c
==============================================================================
--- head/sys/dev/mge/if_mge.c	Sun Mar  4 18:59:38 2012	(r232517)
+++ head/sys/dev/mge/if_mge.c	Sun Mar  4 19:22:52 2012	(r232518)
@@ -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
 
 	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 ph
 
 	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)

Modified: head/sys/dev/mge/if_mgevar.h
==============================================================================
--- head/sys/dev/mge/if_mgevar.h	Sun Mar  4 18:59:38 2012	(r232517)
+++ head/sys/dev/mge/if_mgevar.h	Sun Mar  4 19:22:52 2012	(r232518)
@@ -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;
 };
 
 

Modified: head/sys/dev/tsec/if_tsec.c
==============================================================================
--- head/sys/dev/tsec/if_tsec.c	Sun Mar  4 18:59:38 2012	(r232517)
+++ head/sys/dev/tsec/if_tsec.c	Sun Mar  4 19:22:52 2012	(r232518)
@@ -106,8 +106,6 @@ static void	tsec_offload_process_frame(s
 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 ph
 	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 p
 	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);
 

Modified: head/sys/dev/tsec/if_tsec.h
==============================================================================
--- head/sys/dev/tsec/if_tsec.h	Sun Mar  4 18:59:38 2012	(r232517)
+++ head/sys/dev/tsec/if_tsec.h	Sun Mar  4 19:22:52 2012	(r232518)
@@ -133,6 +133,7 @@ struct tsec_softc {
 	struct mbuf	*frame;
 
 	int		phyaddr;
+	struct tsec_softc *phy_sc;
 };
 
 /* interface to get/put generic objects */

Modified: head/sys/dev/tsec/if_tsec_fdt.c
==============================================================================
--- head/sys/dev/tsec/if_tsec_fdt.c	Sun Mar  4 18:59:38 2012	(r232517)
+++ head/sys/dev/tsec/if_tsec_fdt.c	Sun Mar  4 19:22:52 2012	(r232518)
@@ -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 */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203041922.q24JMria049221>