xref: /freebsd/sys/dev/mii/acphy.c (revision 685dc743)
19526a692SSemen Ustimenko /*-
2b61a5730SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni  *
49526a692SSemen Ustimenko  * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
59526a692SSemen Ustimenko  * All rights reserved.
69526a692SSemen Ustimenko  *
79526a692SSemen Ustimenko  * This code is derived from software contributed to The NetBSD Foundation
89526a692SSemen Ustimenko  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
99526a692SSemen Ustimenko  * NASA Ames Research Center.
109526a692SSemen Ustimenko  *
119526a692SSemen Ustimenko  * Redistribution and use in source and binary forms, with or without
129526a692SSemen Ustimenko  * modification, are permitted provided that the following conditions
139526a692SSemen Ustimenko  * are met:
149526a692SSemen Ustimenko  * 1. Redistributions of source code must retain the above copyright
159526a692SSemen Ustimenko  *    notice, this list of conditions and the following disclaimer.
169526a692SSemen Ustimenko  * 2. Redistributions in binary form must reproduce the above copyright
179526a692SSemen Ustimenko  *    notice, this list of conditions and the following disclaimer in the
189526a692SSemen Ustimenko  *    documentation and/or other materials provided with the distribution.
199526a692SSemen Ustimenko  *
209526a692SSemen Ustimenko  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
219526a692SSemen Ustimenko  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
229526a692SSemen Ustimenko  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
239526a692SSemen Ustimenko  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
249526a692SSemen Ustimenko  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
259526a692SSemen Ustimenko  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
269526a692SSemen Ustimenko  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
279526a692SSemen Ustimenko  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
289526a692SSemen Ustimenko  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
299526a692SSemen Ustimenko  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
309526a692SSemen Ustimenko  * POSSIBILITY OF SUCH DAMAGE.
319526a692SSemen Ustimenko  */
32aad970f1SDavid E. O'Brien 
33098ca2bdSWarner Losh /*-
349526a692SSemen Ustimenko  * Copyright (c) 1997 Manuel Bouyer.  All rights reserved.
359526a692SSemen Ustimenko  *
369526a692SSemen Ustimenko  * Redistribution and use in source and binary forms, with or without
379526a692SSemen Ustimenko  * modification, are permitted provided that the following conditions
389526a692SSemen Ustimenko  * are met:
399526a692SSemen Ustimenko  * 1. Redistributions of source code must retain the above copyright
409526a692SSemen Ustimenko  *    notice, this list of conditions and the following disclaimer.
419526a692SSemen Ustimenko  * 2. Redistributions in binary form must reproduce the above copyright
429526a692SSemen Ustimenko  *    notice, this list of conditions and the following disclaimer in the
439526a692SSemen Ustimenko  *    documentation and/or other materials provided with the distribution.
449526a692SSemen Ustimenko  *
459526a692SSemen Ustimenko  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
469526a692SSemen Ustimenko  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
479526a692SSemen Ustimenko  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
489526a692SSemen Ustimenko  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
499526a692SSemen Ustimenko  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
509526a692SSemen Ustimenko  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
519526a692SSemen Ustimenko  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
529526a692SSemen Ustimenko  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
539526a692SSemen Ustimenko  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
549526a692SSemen Ustimenko  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
559526a692SSemen Ustimenko  */
569526a692SSemen Ustimenko 
5750aa1061SMarius Strobl #include <sys/cdefs.h>
589526a692SSemen Ustimenko /*
599526a692SSemen Ustimenko  * Driver for Altima AC101 10/100 PHY
609526a692SSemen Ustimenko  */
619526a692SSemen Ustimenko 
629526a692SSemen Ustimenko #include <sys/param.h>
639526a692SSemen Ustimenko #include <sys/systm.h>
649526a692SSemen Ustimenko #include <sys/kernel.h>
659526a692SSemen Ustimenko #include <sys/socket.h>
669526a692SSemen Ustimenko #include <sys/errno.h>
679526a692SSemen Ustimenko #include <sys/module.h>
689526a692SSemen Ustimenko #include <sys/bus.h>
699526a692SSemen Ustimenko 
709526a692SSemen Ustimenko #include <net/if.h>
719526a692SSemen Ustimenko #include <net/if_media.h>
729526a692SSemen Ustimenko 
739526a692SSemen Ustimenko #include <dev/mii/mii.h>
749526a692SSemen Ustimenko #include <dev/mii/miivar.h>
752d3ce713SDavid E. O'Brien #include "miidevs.h"
769526a692SSemen Ustimenko 
779526a692SSemen Ustimenko #include <dev/mii/acphyreg.h>
789526a692SSemen Ustimenko 
799526a692SSemen Ustimenko #include "miibus_if.h"
809526a692SSemen Ustimenko 
81e51a25f8SAlfred Perlstein static int acphy_probe(device_t);
82e51a25f8SAlfred Perlstein static int acphy_attach(device_t);
839526a692SSemen Ustimenko 
849526a692SSemen Ustimenko static device_method_t acphy_methods[] = {
859526a692SSemen Ustimenko 	/* device interface */
869526a692SSemen Ustimenko 	DEVMETHOD(device_probe,		acphy_probe),
879526a692SSemen Ustimenko 	DEVMETHOD(device_attach,	acphy_attach),
88279fe8d1SPoul-Henning Kamp 	DEVMETHOD(device_detach,	mii_phy_detach),
899526a692SSemen Ustimenko 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
90604f5f1fSMarius Strobl 	DEVMETHOD_END
919526a692SSemen Ustimenko };
929526a692SSemen Ustimenko 
939526a692SSemen Ustimenko static driver_t acphy_driver = {
949526a692SSemen Ustimenko 	"acphy",
959526a692SSemen Ustimenko 	acphy_methods,
969526a692SSemen Ustimenko 	sizeof(struct mii_softc)
979526a692SSemen Ustimenko };
989526a692SSemen Ustimenko 
99f438c2ffSJohn Baldwin DRIVER_MODULE(acphy, miibus, acphy_driver, 0, 0);
1009526a692SSemen Ustimenko 
101e51a25f8SAlfred Perlstein static int	acphy_service(struct mii_softc *, struct mii_data *, int);
102e51a25f8SAlfred Perlstein static void	acphy_reset(struct mii_softc *);
103e51a25f8SAlfred Perlstein static void	acphy_status(struct mii_softc *);
1049526a692SSemen Ustimenko 
105a35b9333SMarius Strobl static const struct mii_phydesc acphys[] = {
1063fcb7a53SMarius Strobl 	MII_PHY_DESC(ALTIMA, AC101),
1073fcb7a53SMarius Strobl 	MII_PHY_DESC(ALTIMA, AC101L),
10865169ee9SMarius Strobl 	/* XXX This is reported to work, but it's not from any data sheet. */
1093fcb7a53SMarius Strobl 	MII_PHY_DESC(ALTIMA, ACXXX),
110a35b9333SMarius Strobl 	MII_PHY_END
111a35b9333SMarius Strobl };
112a35b9333SMarius Strobl 
1133fcb7a53SMarius Strobl static const struct mii_phy_funcs acphy_funcs = {
1143fcb7a53SMarius Strobl 	acphy_service,
1153fcb7a53SMarius Strobl 	acphy_status,
1163fcb7a53SMarius Strobl 	acphy_reset
1173fcb7a53SMarius Strobl };
1183fcb7a53SMarius Strobl 
1199c1c2e99SAlfred Perlstein static int
acphy_probe(device_t dev)1207d830ac9SWarner Losh acphy_probe(device_t dev)
1219526a692SSemen Ustimenko {
1229526a692SSemen Ustimenko 
123a35b9333SMarius Strobl 	return (mii_phy_dev_probe(dev, acphys, BUS_PROBE_DEFAULT));
1249526a692SSemen Ustimenko }
1259526a692SSemen Ustimenko 
1269c1c2e99SAlfred Perlstein static int
acphy_attach(device_t dev)1277d830ac9SWarner Losh acphy_attach(device_t dev)
1289526a692SSemen Ustimenko {
1299526a692SSemen Ustimenko 	struct mii_softc *sc;
1309526a692SSemen Ustimenko 
1319526a692SSemen Ustimenko 	sc = device_get_softc(dev);
1329526a692SSemen Ustimenko 
1333fcb7a53SMarius Strobl 	mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &acphy_funcs, 0);
1349526a692SSemen Ustimenko 
1353fcb7a53SMarius Strobl 	PHY_RESET(sc);
13665169ee9SMarius Strobl 
1373fcb7a53SMarius Strobl 	sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & sc->mii_capmask;
1389526a692SSemen Ustimenko 	device_printf(dev, " ");
139a9ddce98SMarius Strobl 
14027e1f92dSGleb Smirnoff #define	ADD(m)	ifmedia_add(&sc->mii_pdata->mii_media, (m), 0, NULL)
141a9ddce98SMarius Strobl 	if ((PHY_READ(sc, MII_ACPHY_MCTL) & AC_MCTL_FX_SEL) != 0) {
142a9ddce98SMarius Strobl 		sc->mii_flags |= MIIF_HAVEFIBER;
14327e1f92dSGleb Smirnoff 		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, 0, sc->mii_inst));
144a9ddce98SMarius Strobl 		printf("100baseFX, ");
14527e1f92dSGleb Smirnoff 		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, IFM_FDX, sc->mii_inst));
146a9ddce98SMarius Strobl 		printf("100baseFX-FDX, ");
147a9ddce98SMarius Strobl 	}
148a9ddce98SMarius Strobl #undef ADD
149a9ddce98SMarius Strobl 
15065169ee9SMarius Strobl 	mii_phy_add_media(sc);
1519526a692SSemen Ustimenko 	printf("\n");
1529526a692SSemen Ustimenko 
1539526a692SSemen Ustimenko 	MIIBUS_MEDIAINIT(sc->mii_dev);
1549526a692SSemen Ustimenko 	return (0);
1559526a692SSemen Ustimenko }
1569526a692SSemen Ustimenko 
157d9730b8bSJonathan Lemon static int
acphy_service(struct mii_softc * sc,struct mii_data * mii,int cmd)1587d830ac9SWarner Losh acphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
1599526a692SSemen Ustimenko {
1609526a692SSemen Ustimenko 	int reg;
1619526a692SSemen Ustimenko 
1624592db46SSemen Ustimenko 	switch (cmd) {
1634592db46SSemen Ustimenko 	case MII_POLLSTAT:
1644592db46SSemen Ustimenko 		break;
1654592db46SSemen Ustimenko 
1664592db46SSemen Ustimenko 	case MII_MEDIACHG:
1674592db46SSemen Ustimenko 		/* Wake & deisolate up if necessary */
1689526a692SSemen Ustimenko 		reg = PHY_READ(sc, MII_BMCR);
1699526a692SSemen Ustimenko 		if (reg & (BMCR_ISO | BMCR_PDOWN))
1709526a692SSemen Ustimenko 			PHY_WRITE(sc, MII_BMCR, reg & ~(BMCR_ISO | BMCR_PDOWN));
1719526a692SSemen Ustimenko 
17265169ee9SMarius Strobl 		mii_phy_setmedia(sc);
1739526a692SSemen Ustimenko 		break;
1749526a692SSemen Ustimenko 
1759526a692SSemen Ustimenko 	case MII_TICK:
1769526a692SSemen Ustimenko 		/*
1774592db46SSemen Ustimenko 		 * This PHY's autonegotiation doesn't need to be kicked.
178d9730b8bSJonathan Lemon 		 */
1799526a692SSemen Ustimenko 		break;
1809526a692SSemen Ustimenko 	}
1819526a692SSemen Ustimenko 
1829526a692SSemen Ustimenko 	/* Update the media status. */
1833fcb7a53SMarius Strobl 	PHY_STATUS(sc);
1849526a692SSemen Ustimenko 
1859526a692SSemen Ustimenko 	/* Callback if something changed. */
186d9730b8bSJonathan Lemon 	mii_phy_update(sc, cmd);
1879526a692SSemen Ustimenko 	return (0);
1889526a692SSemen Ustimenko }
1899526a692SSemen Ustimenko 
190d9730b8bSJonathan Lemon static void
acphy_status(struct mii_softc * sc)1917d830ac9SWarner Losh acphy_status(struct mii_softc *sc)
1929526a692SSemen Ustimenko {
1939526a692SSemen Ustimenko 	struct mii_data *mii = sc->mii_pdata;
1949526a692SSemen Ustimenko 	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
1959526a692SSemen Ustimenko 	int bmsr, bmcr, diag;
1969526a692SSemen Ustimenko 
1979526a692SSemen Ustimenko 	mii->mii_media_status = IFM_AVALID;
1989526a692SSemen Ustimenko 	mii->mii_media_active = IFM_ETHER;
1999526a692SSemen Ustimenko 
2009526a692SSemen Ustimenko 	bmsr = PHY_READ(sc, MII_BMSR) |
2019526a692SSemen Ustimenko 	    PHY_READ(sc, MII_BMSR);
2029526a692SSemen Ustimenko 	if (bmsr & BMSR_LINK)
2039526a692SSemen Ustimenko 		mii->mii_media_status |= IFM_ACTIVE;
2049526a692SSemen Ustimenko 
2059526a692SSemen Ustimenko 	bmcr = PHY_READ(sc, MII_BMCR);
2069526a692SSemen Ustimenko 	if (bmcr & BMCR_ISO) {
2079526a692SSemen Ustimenko 		mii->mii_media_active |= IFM_NONE;
2089526a692SSemen Ustimenko 		mii->mii_media_status = 0;
2099526a692SSemen Ustimenko 		return;
2109526a692SSemen Ustimenko 	}
2119526a692SSemen Ustimenko 
2129526a692SSemen Ustimenko 	if (bmcr & BMCR_LOOP)
2139526a692SSemen Ustimenko 		mii->mii_media_active |= IFM_LOOP;
2149526a692SSemen Ustimenko 
2159526a692SSemen Ustimenko 	if (bmcr & BMCR_AUTOEN) {
2169526a692SSemen Ustimenko 		if ((bmsr & BMSR_ACOMP) == 0) {
2179526a692SSemen Ustimenko 			/* Erg, still trying, I guess... */
2189526a692SSemen Ustimenko 			mii->mii_media_active |= IFM_NONE;
2199526a692SSemen Ustimenko 			return;
2209526a692SSemen Ustimenko 		}
2214592db46SSemen Ustimenko 		diag = PHY_READ(sc, MII_ACPHY_DIAG);
2229526a692SSemen Ustimenko 		if (diag & AC_DIAG_SPEED)
2239526a692SSemen Ustimenko 			mii->mii_media_active |= IFM_100_TX;
2249526a692SSemen Ustimenko 		else
2259526a692SSemen Ustimenko 			mii->mii_media_active |= IFM_10_T;
2269526a692SSemen Ustimenko 
2279526a692SSemen Ustimenko 		if (diag & AC_DIAG_DUPLEX)
2283fcb7a53SMarius Strobl 			mii->mii_media_active |=
2293fcb7a53SMarius Strobl 			    IFM_FDX | mii_phy_flowstatus(sc);
230d7a9ad56SMarius Strobl 		else
231d7a9ad56SMarius Strobl 			mii->mii_media_active |= IFM_HDX;
2329526a692SSemen Ustimenko 	} else
2339526a692SSemen Ustimenko 		mii->mii_media_active = ife->ifm_media;
2349526a692SSemen Ustimenko }
2359526a692SSemen Ustimenko 
236d9730b8bSJonathan Lemon static void
acphy_reset(struct mii_softc * sc)2377d830ac9SWarner Losh acphy_reset(struct mii_softc *sc)
2389526a692SSemen Ustimenko {
2399526a692SSemen Ustimenko 
2409526a692SSemen Ustimenko 	mii_phy_reset(sc);
2419526a692SSemen Ustimenko 	PHY_WRITE(sc, MII_ACPHY_INT, 0);
2429526a692SSemen Ustimenko }
243