summaryrefslogtreecommitdiffstats
path: root/sys/dev/mii
diff options
context:
space:
mode:
authorgonzo <gonzo@FreeBSD.org>2012-08-15 04:03:55 +0000
committergonzo <gonzo@FreeBSD.org>2012-08-15 04:03:55 +0000
commitc4f4444c7b39a4fd773a9887605e8c216763d00d (patch)
tree69536b58d6be811d83efc392c09c14037a1cd95b /sys/dev/mii
parenta86619e32d43f67acebfca6f18e523a14bce37c8 (diff)
downloadFreeBSD-src-c4f4444c7b39a4fd773a9887605e8c216763d00d.zip
FreeBSD-src-c4f4444c7b39a4fd773a9887605e8c216763d00d.tar.gz
Merging of projects/armv6, part 5
- Driver for SMSC LAN95XX and LAN8710A ethernet controllers - Driver for LAN8710A PHY Submitted by: Ben Gray, Damjan Marion, Tim Kientzle
Diffstat (limited to 'sys/dev/mii')
-rw-r--r--sys/dev/mii/miidevs4
-rw-r--r--sys/dev/mii/smcphy.c3
-rw-r--r--sys/dev/mii/smscphy.c237
3 files changed, 243 insertions, 1 deletions
diff --git a/sys/dev/mii/miidevs b/sys/dev/mii/miidevs
index 5544614..3ccaf37 100644
--- a/sys/dev/mii/miidevs
+++ b/sys/dev/mii/miidevs
@@ -69,6 +69,7 @@ oui RDC 0x00d02d RDC Semiconductor
oui REALTEK 0x00e04c RealTek Semicondctor
oui SEEQ 0x00a07d Seeq Technology
oui SIS 0x00e006 Silicon Integrated Systems
+oui SMC 0x00800f SMC
oui TI 0x080028 Texas Instruments
oui TSC 0x00c039 TDK Semiconductor
oui VITESSE 0x0001c1 Vitesse Semiconductor
@@ -325,3 +326,6 @@ model xxVITESSE VSC8641 0x0003 Vitesse VSC8641 10/100/1000TX PHY
/* XaQti Corp. PHYs */
model xxXAQTI XMACII 0x0000 XaQti Corp. XMAC II gigabit interface
+
+/* SMC */
+model SMC LAN8710A 0x000F SMC LAN8710A 10/100 interface
diff --git a/sys/dev/mii/smcphy.c b/sys/dev/mii/smcphy.c
index 1dd418d..e968053 100644
--- a/sys/dev/mii/smcphy.c
+++ b/sys/dev/mii/smcphy.c
@@ -26,7 +26,8 @@
__FBSDID("$FreeBSD$");
/*
- * Driver for the internal PHY on the SMSC LAN91C111.
+ * Driver for the SEEQ 80220 and 84220.
+ * (Originally developed for the internal PHY on the SMSC LAN91C111.)
*/
#include <sys/param.h>
diff --git a/sys/dev/mii/smscphy.c b/sys/dev/mii/smscphy.c
new file mode 100644
index 0000000..005e868
--- /dev/null
+++ b/sys/dev/mii/smscphy.c
@@ -0,0 +1,237 @@
+/*-
+ * Copyright (c) 2006 Benno Rice. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Driver for the SMSC LAN8710A
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include "miidevs.h"
+
+#include "miibus_if.h"
+
+static int smscphy_probe(device_t);
+static int smscphy_attach(device_t);
+
+static int smscphy_service(struct mii_softc *, struct mii_data *, int);
+static void smscphy_auto(struct mii_softc *, int);
+static void smscphy_status(struct mii_softc *);
+
+static device_method_t smscphy_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, smscphy_probe),
+ DEVMETHOD(device_attach, smscphy_attach),
+ DEVMETHOD(device_detach, mii_phy_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD_END
+};
+
+static devclass_t smscphy_devclass;
+
+static driver_t smscphy_driver = {
+ "smscphy",
+ smscphy_methods,
+ sizeof(struct mii_softc)
+};
+
+DRIVER_MODULE(smscphy, miibus, smscphy_driver, smscphy_devclass, 0, 0);
+
+static const struct mii_phydesc smscphys[] = {
+ MII_PHY_DESC(SMC, LAN8710A),
+ MII_PHY_END
+};
+
+static const struct mii_phy_funcs smscphy_funcs = {
+ smscphy_service,
+ smscphy_status,
+ mii_phy_reset
+};
+
+static int
+smscphy_probe(device_t dev)
+{
+
+ return (mii_phy_dev_probe(dev, smscphys, BUS_PROBE_DEFAULT));
+}
+
+static int
+smscphy_attach(device_t dev)
+{
+ struct mii_softc *sc;
+ struct mii_attach_args *ma;
+ const struct mii_phy_funcs *mpf;
+
+ sc = device_get_softc(dev);
+ ma = device_get_ivars(dev);
+ mpf = &smscphy_funcs;
+ mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, mpf, 1);
+ mii_phy_setmedia(sc);
+
+ return (0);
+}
+
+static int
+smscphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
+{
+ struct ifmedia_entry *ife;
+ int reg;
+
+ ife = mii->mii_media.ifm_cur;
+
+ switch (cmd) {
+ case MII_POLLSTAT:
+ break;
+
+ case MII_MEDIACHG:
+ /*
+ * If the interface is not up, don't do anything.
+ */
+ if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
+ break;
+
+ switch (IFM_SUBTYPE(ife->ifm_media)) {
+ case IFM_AUTO:
+ smscphy_auto(sc, ife->ifm_media);
+ break;
+
+ default:
+ mii_phy_setmedia(sc);
+ break;
+ }
+
+ break;
+
+ case MII_TICK:
+ if ((mii->mii_ifp->if_flags & IFF_UP) == 0) {
+ return (0);
+ }
+
+ if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
+ break;
+ }
+
+ /* I have no idea why BMCR_ISO gets set. */
+ reg = PHY_READ(sc, MII_BMCR);
+ if (reg & BMCR_ISO) {
+ PHY_WRITE(sc, MII_BMCR, reg & ~BMCR_ISO);
+ }
+
+ reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
+ if (reg & BMSR_LINK) {
+ sc->mii_ticks = 0;
+ break;
+ }
+
+ if (++sc->mii_ticks <= MII_ANEGTICKS) {
+ break;
+ }
+
+ sc->mii_ticks = 0;
+ PHY_RESET(sc);
+ smscphy_auto(sc, ife->ifm_media);
+ break;
+ }
+
+ /* Update the media status. */
+ PHY_STATUS(sc);
+
+ /* Callback if something changed. */
+ mii_phy_update(sc, cmd);
+ return (0);
+}
+
+static void
+smscphy_auto(struct mii_softc *sc, int media)
+{
+ uint16_t anar;
+
+ anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
+ if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
+ anar |= ANAR_FC;
+ PHY_WRITE(sc, MII_ANAR, anar);
+ /* Apparently this helps. */
+ anar = PHY_READ(sc, MII_ANAR);
+ PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
+}
+
+static void
+smscphy_status(struct mii_softc *sc)
+{
+ struct mii_data *mii;
+ uint32_t bmcr, bmsr, status;
+
+ mii = sc->mii_pdata;
+ mii->mii_media_status = IFM_AVALID;
+ mii->mii_media_active = IFM_ETHER;
+
+ bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
+ if ((bmsr & BMSR_LINK) != 0)
+ mii->mii_media_status |= IFM_ACTIVE;
+
+ bmcr = PHY_READ(sc, MII_BMCR);
+ if ((bmcr & BMCR_ISO) != 0) {
+ mii->mii_media_active |= IFM_NONE;
+ mii->mii_media_status = 0;
+ return;
+ }
+
+ if ((bmcr & BMCR_LOOP) != 0)
+ mii->mii_media_active |= IFM_LOOP;
+
+ if ((bmcr & BMCR_AUTOEN) != 0) {
+ if ((bmsr & BMSR_ACOMP) == 0) {
+ /* Erg, still trying, I guess... */
+ mii->mii_media_active |= IFM_NONE;
+ return;
+ }
+ }
+
+ status = PHY_READ(sc, 0x1F);
+ if (status & 0x0008)
+ mii->mii_media_active |= IFM_100_TX;
+ else
+ mii->mii_media_active |= IFM_10_T;
+ if (status & 0x0010)
+ mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc);
+ else
+ mii->mii_media_active |= IFM_HDX;
+}
OpenPOWER on IntegriCloud