Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 11 Nov 2013 15:43:22 +0000 (UTC)
From:      Nathan Whitehorn <nwhitehorn@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r257993 - in head/sys: conf dev/tsec powerpc/ofw
Message-ID:  <201311111543.rABFhM1K009850@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: nwhitehorn
Date: Mon Nov 11 15:43:21 2013
New Revision: 257993
URL: http://svnweb.freebsd.org/changeset/base/257993

Log:
  Make tsec work with the device tree present on the RB800. The previous code
  assumed that the MDIO bus was a direct child of the Ethernet interface. It
  may not be and indeed on many device trees is not. While here, add proper
  locking for MII transactions, which may be on a bus shared by several MACs.
  
  Hardware donated by:	Benjamin Perrault

Modified:
  head/sys/conf/files.powerpc
  head/sys/dev/tsec/if_tsec.c
  head/sys/dev/tsec/if_tsec.h
  head/sys/dev/tsec/if_tsec_fdt.c
  head/sys/dev/tsec/if_tsecreg.h
  head/sys/powerpc/ofw/ofw_machdep.c

Modified: head/sys/conf/files.powerpc
==============================================================================
--- head/sys/conf/files.powerpc	Mon Nov 11 15:23:35 2013	(r257992)
+++ head/sys/conf/files.powerpc	Mon Nov 11 15:43:21 2013	(r257993)
@@ -134,7 +134,7 @@ powerpc/mpc85xx/lbc.c		optional	mpc85xx
 powerpc/mpc85xx/mpc85xx.c	optional	mpc85xx
 powerpc/mpc85xx/pci_mpc85xx.c	optional	pci mpc85xx
 powerpc/ofw/ofw_cpu.c		optional	aim
-powerpc/ofw/ofw_machdep.c	optional	aim
+powerpc/ofw/ofw_machdep.c	standard
 powerpc/ofw/ofw_pci.c		optional	pci
 powerpc/ofw/ofw_pcibus.c	optional	pci
 powerpc/ofw/ofw_pcib_pci.c	optional	pci

Modified: head/sys/dev/tsec/if_tsec.c
==============================================================================
--- head/sys/dev/tsec/if_tsec.c	Mon Nov 11 15:23:35 2013	(r257992)
+++ head/sys/dev/tsec/if_tsec.c	Mon Nov 11 15:43:21 2013	(r257993)
@@ -112,6 +112,8 @@ DRIVER_MODULE(miibus, tsec, miibus_drive
 MODULE_DEPEND(tsec, ether, 1, 1, 1);
 MODULE_DEPEND(tsec, miibus, 1, 1, 1);
 
+struct mtx tsec_phy_mtx;
+
 int
 tsec_attach(struct tsec_softc *sc)
 {
@@ -122,6 +124,10 @@ tsec_attach(struct tsec_softc *sc)
 	int error = 0;
 	int i;
 
+	/* Initialize global (because potentially shared) MII lock */
+	if (!mtx_initialized(&tsec_phy_mtx))
+		mtx_init(&tsec_phy_mtx, "tsec mii", NULL, MTX_DEF);
+
 	/* Reset all TSEC counters */
 	TSEC_TX_RX_COUNTERS_INIT(sc);
 
@@ -407,21 +413,24 @@ tsec_init_locked(struct tsec_softc *sc)
 	 */
 	TSEC_WRITE(sc, TSEC_REG_TBIPA, 5);
 
+	TSEC_PHY_LOCK(sc);
+
 	/* Step 6: Reset the management interface */
-	TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCFG, TSEC_MIIMCFG_RESETMGMT);
+	TSEC_PHY_WRITE(sc, TSEC_REG_MIIMCFG, TSEC_MIIMCFG_RESETMGMT);
 
 	/* Step 7: Setup the MII Mgmt clock speed */
-	TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCFG, TSEC_MIIMCFG_CLKDIV28);
+	TSEC_PHY_WRITE(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(sc->phy_sc, TSEC_REG_MIIMIND) &
+	while (--timeout && (TSEC_PHY_READ(sc, TSEC_REG_MIIMIND) &
 	    TSEC_MIIMIND_BUSY))
 		DELAY(TSEC_READ_DELAY);
 	if (timeout == 0) {
 		if_printf(ifp, "tsec_init_locked(): Mgmt busy timeout\n");
 		return;
 	}
+	TSEC_PHY_UNLOCK(sc);
 
 	/* Step 9: Setup the MII Mgmt */
 	mii_mediachg(sc->tsec_mii);
@@ -1562,22 +1571,27 @@ tsec_miibus_readreg(device_t dev, int ph
 {
 	struct tsec_softc *sc;
 	uint32_t timeout;
+	int rv;
 
 	sc = device_get_softc(dev);
 
-	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);
+	TSEC_PHY_LOCK();
+	TSEC_PHY_WRITE(sc, TSEC_REG_MIIMADD, (phy << 8) | reg);
+	TSEC_PHY_WRITE(sc, TSEC_REG_MIIMCOM, 0);
+	TSEC_PHY_WRITE(sc, TSEC_REG_MIIMCOM, TSEC_MIIMCOM_READCYCLE);
 
 	timeout = TSEC_READ_RETRY;
-	while (--timeout && TSEC_READ(sc->phy_sc, TSEC_REG_MIIMIND) &
+	while (--timeout && TSEC_PHY_READ(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->phy_sc, TSEC_REG_MIIMSTAT));
+	rv = TSEC_PHY_READ(sc, TSEC_REG_MIIMSTAT);
+	TSEC_PHY_UNLOCK();
+
+	return (rv);
 }
 
 int
@@ -1588,13 +1602,15 @@ tsec_miibus_writereg(device_t dev, int p
 
 	sc = device_get_softc(dev);
 
-	TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMADD, (phy << 8) | reg);
-	TSEC_WRITE(sc->phy_sc, TSEC_REG_MIIMCON, value);
+	TSEC_PHY_LOCK();
+	TSEC_PHY_WRITE(sc, TSEC_REG_MIIMADD, (phy << 8) | reg);
+	TSEC_PHY_WRITE(sc, TSEC_REG_MIIMCON, value);
 
 	timeout = TSEC_READ_RETRY;
-	while (--timeout && (TSEC_READ(sc->phy_sc, TSEC_REG_MIIMIND) &
+	while (--timeout && (TSEC_READ(sc, TSEC_REG_MIIMIND) &
 	    TSEC_MIIMIND_BUSY))
 		DELAY(TSEC_READ_DELAY);
+	TSEC_PHY_UNLOCK();
 
 	if (timeout == 0)
 		device_printf(dev, "Timeout while writing to PHY!\n");

Modified: head/sys/dev/tsec/if_tsec.h
==============================================================================
--- head/sys/dev/tsec/if_tsec.h	Mon Nov 11 15:23:35 2013	(r257992)
+++ head/sys/dev/tsec/if_tsec.h	Mon Nov 11 15:43:21 2013	(r257993)
@@ -133,7 +133,8 @@ struct tsec_softc {
 	struct mbuf	*frame;
 
 	int		phyaddr;
-	struct tsec_softc *phy_sc;
+	bus_space_tag_t phy_bst;
+	bus_space_handle_t phy_bsh;
 };
 
 /* interface to get/put generic objects */
@@ -253,6 +254,14 @@ struct tsec_softc {
 #define TSEC_WRITE(sc, reg, val)	\
 		bus_space_write_4((sc)->sc_bas.bst, (sc)->sc_bas.bsh, (reg), (val))
 
+extern struct mtx tsec_phy_mtx;
+#define TSEC_PHY_LOCK(sc)	mtx_lock(&tsec_phy_mtx)
+#define TSEC_PHY_UNLOCK(sc)	mtx_unlock(&tsec_phy_mtx)
+#define TSEC_PHY_READ(sc, reg)		\
+		bus_space_read_4((sc)->phy_bst, (sc)->phy_bsh, (reg))
+#define TSEC_PHY_WRITE(sc, reg, val)	\
+		bus_space_write_4((sc)->phy_bst, (sc)->phy_bsh, (reg), (val))
+
 /* Lock for transmitter */
 #define TSEC_TRANSMIT_LOCK(sc) do {					\
 		mtx_assert(&(sc)->receive_lock, MA_NOTOWNED);		\

Modified: head/sys/dev/tsec/if_tsec_fdt.c
==============================================================================
--- head/sys/dev/tsec/if_tsec_fdt.c	Mon Nov 11 15:23:35 2013	(r257992)
+++ head/sys/dev/tsec/if_tsec_fdt.c	Mon Nov 11 15:43:21 2013	(r257993)
@@ -110,6 +110,10 @@ tsec_fdt_probe(device_t dev)
 	struct tsec_softc *sc;
 	uint32_t id;
 
+	if (ofw_bus_get_type(dev) == NULL ||
+	    strcmp(ofw_bus_get_type(dev), "network") != 0)
+		return (ENXIO);
+
 	if (!ofw_bus_is_compatible(dev, "gianfar"))
 		return (ENXIO);
 
@@ -148,6 +152,7 @@ static int
 tsec_fdt_attach(device_t dev)
 {
 	struct tsec_softc *sc;
+	phandle_t phy;
 	int error = 0;
 
 	sc = device_get_softc(dev);
@@ -155,9 +160,14 @@ tsec_fdt_attach(device_t dev)
 	sc->node = ofw_bus_get_node(dev);
 
 	/* Get phy address from fdt */
-	if (fdt_get_phyaddr(sc->node, sc->dev, &sc->phyaddr,
-	    (void **)&sc->phy_sc) != 0)
+	if (OF_getencprop(sc->node, "phy-handle", &phy, sizeof(phy)) <= 0) {
+		device_printf(dev, "PHY not found in device tree");
 		return (ENXIO);
+	}
+
+	phy = OF_xref_phandle(phy);
+	OF_decode_addr(OF_parent(phy), 0, &sc->phy_bst, &sc->phy_bsh);
+	OF_getencprop(phy, "reg", &sc->phyaddr, sizeof(sc->phyaddr));
 
 	/* Init timer */
 	callout_init(&sc->tsec_callout, 1);
@@ -324,6 +334,13 @@ tsec_get_hwaddr(struct tsec_softc *sc, u
 		return;
 	}
 
+	/* Also try the mac-address property, which is second-best */
+	i = OF_getprop(sc->node, "mac-address", (void *)hw.addr, 6);
+	if (i == 6 && (hw.reg[0] != 0 || hw.reg[1] != 0)) {
+		bcopy(hw.addr, addr, 6);
+		return;
+	}
+
 	/*
 	 * Fall back -- use the currently programmed address in the hope that
 	 * it was set be firmware...

Modified: head/sys/dev/tsec/if_tsecreg.h
==============================================================================
--- head/sys/dev/tsec/if_tsecreg.h	Mon Nov 11 15:23:35 2013	(r257992)
+++ head/sys/dev/tsec/if_tsecreg.h	Mon Nov 11 15:43:21 2013	(r257993)
@@ -77,12 +77,13 @@
 				       * register */
 #define TSEC_REG_HAFDUP		0x50c /* Half-duplex register */
 #define TSEC_REG_MAXFRM		0x510 /* Maximum frame length register */
-#define TSEC_REG_MIIMCFG	0x520 /* MII Management configuration register */
-#define TSEC_REG_MIIMCOM	0x524 /* MII Management command register */
-#define TSEC_REG_MIIMADD	0x528 /* MII Management address register */
-#define TSEC_REG_MIIMCON	0x52c /* MII Management control register */
-#define TSEC_REG_MIIMSTAT	0x530 /* MII Management status register */
-#define TSEC_REG_MIIMIND	0x534 /* MII Management indicator register */
+#define TSEC_REG_MIIBASE	0x520 /* MII Management base, rest offsets */
+#define TSEC_REG_MIIMCFG	0x0   /* MII Management configuration register */
+#define TSEC_REG_MIIMCOM	0x4   /* MII Management command register */
+#define TSEC_REG_MIIMADD	0x8   /* MII Management address register */
+#define TSEC_REG_MIIMCON	0xc   /* MII Management control register */
+#define TSEC_REG_MIIMSTAT	0x10  /* MII Management status register */
+#define TSEC_REG_MIIMIND	0x14  /* MII Management indicator register */
 #define TSEC_REG_IFSTAT		0x53c /* Interface status register */
 #define TSEC_REG_MACSTNADDR1	0x540 /* Station address register, part 1 */
 #define TSEC_REG_MACSTNADDR2	0x544 /* Station address register, part 2 */

Modified: head/sys/powerpc/ofw/ofw_machdep.c
==============================================================================
--- head/sys/powerpc/ofw/ofw_machdep.c	Mon Nov 11 15:23:35 2013	(r257992)
+++ head/sys/powerpc/ofw/ofw_machdep.c	Mon Nov 11 15:43:21 2013	(r257993)
@@ -63,11 +63,13 @@ __FBSDID("$FreeBSD$");
 static struct mem_region OFmem[PHYS_AVAIL_SZ], OFavail[PHYS_AVAIL_SZ];
 static struct mem_region OFfree[PHYS_AVAIL_SZ];
 
+static int	apple_hacks;
+
+#ifdef AIM
 extern register_t ofmsr[5];
 extern void	*openfirmware_entry;
 static void	*fdt;
 int		ofw_real_mode;
-static int	apple_hacks;
 
 int		ofwcall(void *);
 static int	openfirmware(void *args);
@@ -114,6 +116,7 @@ ofw_sprg_restore(void)
 	 */
 	__asm __volatile("mtsprg0 %0" :: "r"(ofw_sprg0_save));
 }
+#endif
 
 /*
  * Memory region utilities: determine if two regions overlap,
@@ -436,6 +439,7 @@ ofw_mem_regions(struct mem_region **memp
 	*availsz = fsz;
 }
 
+#ifdef AIM
 void
 OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *))
 {
@@ -607,6 +611,8 @@ OF_reboot()
 	for (;;);	/* just in case */
 }
 
+#endif /* AIM */
+
 void
 OF_getetheraddr(device_t dev, u_char *addr)
 {



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