xref: /netbsd-src/sys/dev/mii/glxtphy.c (revision 7a9a30c5e763bb556f73924ae04973e33cc385da)
1*7a9a30c5Sthorpej /*	$NetBSD: glxtphy.c,v 1.32 2020/03/15 23:04:50 thorpej Exp $	*/
241a68e94Sthorpej 
341a68e94Sthorpej /*-
441a68e94Sthorpej  * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
541a68e94Sthorpej  * All rights reserved.
641a68e94Sthorpej  *
741a68e94Sthorpej  * This code is derived from software contributed to The NetBSD Foundation
841a68e94Sthorpej  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
941a68e94Sthorpej  * NASA Ames Research Center.
1041a68e94Sthorpej  *
1141a68e94Sthorpej  * Redistribution and use in source and binary forms, with or without
1241a68e94Sthorpej  * modification, are permitted provided that the following conditions
1341a68e94Sthorpej  * are met:
1441a68e94Sthorpej  * 1. Redistributions of source code must retain the above copyright
1541a68e94Sthorpej  *    notice, this list of conditions and the following disclaimer.
1641a68e94Sthorpej  * 2. Redistributions in binary form must reproduce the above copyright
1741a68e94Sthorpej  *    notice, this list of conditions and the following disclaimer in the
1841a68e94Sthorpej  *    documentation and/or other materials provided with the distribution.
1941a68e94Sthorpej  *
2041a68e94Sthorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2141a68e94Sthorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2241a68e94Sthorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2341a68e94Sthorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2441a68e94Sthorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2541a68e94Sthorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2641a68e94Sthorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2741a68e94Sthorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2841a68e94Sthorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2941a68e94Sthorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3041a68e94Sthorpej  * POSSIBILITY OF SUCH DAMAGE.
3141a68e94Sthorpej  */
3241a68e94Sthorpej 
3341a68e94Sthorpej /*
3441a68e94Sthorpej  * Copyright (c) 1997 Manuel Bouyer.  All rights reserved.
3541a68e94Sthorpej  *
3641a68e94Sthorpej  * Redistribution and use in source and binary forms, with or without
3741a68e94Sthorpej  * modification, are permitted provided that the following conditions
3841a68e94Sthorpej  * are met:
3941a68e94Sthorpej  * 1. Redistributions of source code must retain the above copyright
4041a68e94Sthorpej  *    notice, this list of conditions and the following disclaimer.
4141a68e94Sthorpej  * 2. Redistributions in binary form must reproduce the above copyright
4241a68e94Sthorpej  *    notice, this list of conditions and the following disclaimer in the
4341a68e94Sthorpej  *    documentation and/or other materials provided with the distribution.
4441a68e94Sthorpej  *
4541a68e94Sthorpej  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
4641a68e94Sthorpej  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
4741a68e94Sthorpej  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
4841a68e94Sthorpej  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
4941a68e94Sthorpej  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
5041a68e94Sthorpej  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
5141a68e94Sthorpej  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
5241a68e94Sthorpej  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5341a68e94Sthorpej  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
5441a68e94Sthorpej  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5541a68e94Sthorpej  */
5641a68e94Sthorpej 
5741a68e94Sthorpej /*
5841a68e94Sthorpej  * Driver for the Level One LXT-1000 10/100/1000 PHY.
5941a68e94Sthorpej  */
6041a68e94Sthorpej 
618b7bb912Slukem #include <sys/cdefs.h>
62*7a9a30c5Sthorpej __KERNEL_RCSID(0, "$NetBSD: glxtphy.c,v 1.32 2020/03/15 23:04:50 thorpej Exp $");
638b7bb912Slukem 
6441a68e94Sthorpej #include <sys/param.h>
6541a68e94Sthorpej #include <sys/systm.h>
6641a68e94Sthorpej #include <sys/kernel.h>
6741a68e94Sthorpej #include <sys/device.h>
6841a68e94Sthorpej #include <sys/socket.h>
6941a68e94Sthorpej #include <sys/errno.h>
7041a68e94Sthorpej 
7141a68e94Sthorpej #include <net/if.h>
7241a68e94Sthorpej #include <net/if_media.h>
7341a68e94Sthorpej 
7441a68e94Sthorpej #include <dev/mii/mii.h>
7541a68e94Sthorpej #include <dev/mii/miivar.h>
7641a68e94Sthorpej #include <dev/mii/miidevs.h>
7741a68e94Sthorpej 
7841a68e94Sthorpej #include <dev/mii/glxtphyreg.h>
7941a68e94Sthorpej 
807db0e577Sxtraeme static int	glxtphymatch(device_t, cfdata_t, void *);
817db0e577Sxtraeme static void	glxtphyattach(device_t, device_t, void *);
8241a68e94Sthorpej 
837db0e577Sxtraeme CFATTACH_DECL_NEW(glxtphy, sizeof(struct mii_softc),
84c9b3657cSthorpej     glxtphymatch, glxtphyattach, mii_phy_detach, mii_phy_activate);
8541a68e94Sthorpej 
861efb3da0Sthorpej static int	glxtphy_service(struct mii_softc *, struct mii_data *, int);
871efb3da0Sthorpej static void	glxtphy_status(struct mii_softc *);
8841a68e94Sthorpej 
891efb3da0Sthorpej static const struct mii_phy_funcs glxtphy_funcs = {
9041a68e94Sthorpej 	glxtphy_service, glxtphy_status, mii_phy_reset,
9141a68e94Sthorpej };
9241a68e94Sthorpej 
931efb3da0Sthorpej static const struct mii_phydesc glxtphys[] = {
947b43da1bSchristos 	MII_PHY_DESC(LEVEL1, LXT1000_OLD),
957b43da1bSchristos 	MII_PHY_DESC(LEVEL1, LXT1000),
967b43da1bSchristos 	MII_PHY_END,
9741a68e94Sthorpej };
9841a68e94Sthorpej 
991efb3da0Sthorpej static int
glxtphymatch(device_t parent,cfdata_t match,void * aux)10002341723Smsaitoh glxtphymatch(device_t parent, cfdata_t match, void *aux)
10141a68e94Sthorpej {
10241a68e94Sthorpej 	struct mii_attach_args *ma = aux;
10341a68e94Sthorpej 
10441a68e94Sthorpej 	if (mii_phy_match(ma, glxtphys) != NULL)
10502341723Smsaitoh 		return 10;
10641a68e94Sthorpej 
10702341723Smsaitoh 	return 0;
10841a68e94Sthorpej }
10941a68e94Sthorpej 
1101efb3da0Sthorpej static void
glxtphyattach(device_t parent,device_t self,void * aux)1117db0e577Sxtraeme glxtphyattach(device_t parent, device_t self, void *aux)
11241a68e94Sthorpej {
113838ee1e0Sthorpej 	struct mii_softc *sc = device_private(self);
11441a68e94Sthorpej 	struct mii_attach_args *ma = aux;
11541a68e94Sthorpej 	struct mii_data *mii = ma->mii_data;
11641a68e94Sthorpej 	const struct mii_phydesc *mpd;
11741a68e94Sthorpej 
11841a68e94Sthorpej 	mpd = mii_phy_match(ma, glxtphys);
119c31f87a5Sthorpej 	aprint_naive(": Media interface\n");
120c31f87a5Sthorpej 	aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
12141a68e94Sthorpej 
1227db0e577Sxtraeme 	sc->mii_dev = self;
12341a68e94Sthorpej 	sc->mii_inst = mii->mii_instance;
12441a68e94Sthorpej 	sc->mii_phy = ma->mii_phyno;
12541a68e94Sthorpej 	sc->mii_funcs = &glxtphy_funcs;
12641a68e94Sthorpej 	sc->mii_pdata = mii;
127b0178985Sthorpej 	sc->mii_flags = ma->mii_flags;
12841a68e94Sthorpej 
129*7a9a30c5Sthorpej 	mii_lock(mii);
130*7a9a30c5Sthorpej 
13141a68e94Sthorpej 	PHY_RESET(sc);
13241a68e94Sthorpej 
133a5cdd4b4Smsaitoh 	PHY_READ(sc, MII_BMSR, &sc->mii_capabilities);
134a5cdd4b4Smsaitoh 	sc->mii_capabilities &= ma->mii_capmask;
13541a68e94Sthorpej 	if (sc->mii_capabilities & BMSR_EXTSTAT)
136a5cdd4b4Smsaitoh 		PHY_READ(sc, MII_EXTSR, &sc->mii_extcapabilities);
13741a68e94Sthorpej 
138*7a9a30c5Sthorpej 	mii_unlock(mii);
139*7a9a30c5Sthorpej 
14041a68e94Sthorpej 	mii_phy_add_media(sc);
14141a68e94Sthorpej }
14241a68e94Sthorpej 
1431efb3da0Sthorpej static int
glxtphy_service(struct mii_softc * sc,struct mii_data * mii,int cmd)14489893e42Sthorpej glxtphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
14541a68e94Sthorpej {
14641a68e94Sthorpej 	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
147a5cdd4b4Smsaitoh 	uint16_t reg;
14841a68e94Sthorpej 
149*7a9a30c5Sthorpej 	KASSERT(mii_locked(mii));
150*7a9a30c5Sthorpej 
15141a68e94Sthorpej 	switch (cmd) {
15241a68e94Sthorpej 	case MII_POLLSTAT:
15302341723Smsaitoh 		/* If we're not polling our PHY instance, just return. */
15441a68e94Sthorpej 		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
15502341723Smsaitoh 			return 0;
15641a68e94Sthorpej 		break;
15741a68e94Sthorpej 
15841a68e94Sthorpej 	case MII_MEDIACHG:
15941a68e94Sthorpej 		/*
16041a68e94Sthorpej 		 * If the media indicates a different PHY instance,
16141a68e94Sthorpej 		 * isolate ourselves.
16241a68e94Sthorpej 		 */
16341a68e94Sthorpej 		if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
164a5cdd4b4Smsaitoh 			PHY_READ(sc, MII_BMCR, &reg);
16541a68e94Sthorpej 			PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
16602341723Smsaitoh 			return 0;
16741a68e94Sthorpej 		}
16841a68e94Sthorpej 
16902341723Smsaitoh 		/* If the interface is not up, don't do anything. */
17041a68e94Sthorpej 		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
17141a68e94Sthorpej 			break;
17241a68e94Sthorpej 
17341a68e94Sthorpej 		mii_phy_setmedia(sc);
17441a68e94Sthorpej 		break;
17541a68e94Sthorpej 
17641a68e94Sthorpej 	case MII_TICK:
17702341723Smsaitoh 		/* If we're not currently selected, just return. */
17841a68e94Sthorpej 		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
17902341723Smsaitoh 			return 0;
18041a68e94Sthorpej 
18141a68e94Sthorpej 		if (mii_phy_tick(sc) == EJUSTRETURN)
18202341723Smsaitoh 			return 0;
18341a68e94Sthorpej 		break;
18441a68e94Sthorpej 
18541a68e94Sthorpej 	case MII_DOWN:
18641a68e94Sthorpej 		mii_phy_down(sc);
18702341723Smsaitoh 		return 0;
18841a68e94Sthorpej 	}
18941a68e94Sthorpej 
19041a68e94Sthorpej 	/* Update the media status. */
19141a68e94Sthorpej 	mii_phy_status(sc);
19241a68e94Sthorpej 
19341a68e94Sthorpej 	/* Callback if something changed. */
19441a68e94Sthorpej 	mii_phy_update(sc, cmd);
19502341723Smsaitoh 	return 0;
19641a68e94Sthorpej }
19741a68e94Sthorpej 
1981efb3da0Sthorpej static void
glxtphy_status(struct mii_softc * sc)19989893e42Sthorpej glxtphy_status(struct mii_softc *sc)
20041a68e94Sthorpej {
20141a68e94Sthorpej 	struct mii_data *mii = sc->mii_pdata;
20241a68e94Sthorpej 	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
203a5cdd4b4Smsaitoh 	uint16_t bmcr, qsr, gtsr;
20441a68e94Sthorpej 
205*7a9a30c5Sthorpej 	KASSERT(mii_locked(mii));
206*7a9a30c5Sthorpej 
20741a68e94Sthorpej 	mii->mii_media_status = IFM_AVALID;
20841a68e94Sthorpej 	mii->mii_media_active = IFM_ETHER;
20941a68e94Sthorpej 
210a5cdd4b4Smsaitoh 	PHY_READ(sc, MII_GLXTPHY_QSR, &qsr);
21141a68e94Sthorpej 
21241a68e94Sthorpej 	if (qsr & QSR_LINK)
21341a68e94Sthorpej 		mii->mii_media_status |= IFM_ACTIVE;
21441a68e94Sthorpej 
215a5cdd4b4Smsaitoh 	PHY_READ(sc, MII_BMCR, &bmcr);
21641a68e94Sthorpej 	if (bmcr & BMCR_ISO) {
21741a68e94Sthorpej 		mii->mii_media_active |= IFM_NONE;
21841a68e94Sthorpej 		mii->mii_media_status = 0;
21941a68e94Sthorpej 		return;
22041a68e94Sthorpej 	}
22141a68e94Sthorpej 
22241a68e94Sthorpej 	if (bmcr & BMCR_LOOP)
22341a68e94Sthorpej 		mii->mii_media_active |= IFM_LOOP;
22441a68e94Sthorpej 
22541a68e94Sthorpej 	if (bmcr & BMCR_AUTOEN) {
22641a68e94Sthorpej 		/*
227913e68ceSmsaitoh 		 * The media status bits are only valid if autonegotiation
22841a68e94Sthorpej 		 * has completed (or it's disabled).
22941a68e94Sthorpej 		 */
23041a68e94Sthorpej 		if ((qsr & QSR_ACOMP) == 0) {
23141a68e94Sthorpej 			/* Erg, still trying, I guess... */
23241a68e94Sthorpej 			mii->mii_media_active |= IFM_NONE;
23341a68e94Sthorpej 			return;
23441a68e94Sthorpej 		}
23541a68e94Sthorpej 
23641a68e94Sthorpej 		switch (QSR_SPEED_get(qsr)) {
23741a68e94Sthorpej 		case SPEED_1000:
23841a68e94Sthorpej 			mii->mii_media_active |= IFM_1000_T;
239a5cdd4b4Smsaitoh 			PHY_READ(sc, MII_100T2SR, &gtsr);
24041a68e94Sthorpej 			if (gtsr & GTSR_MS_RES)
24141a68e94Sthorpej 				mii->mii_media_active |= IFM_ETH_MASTER;
24241a68e94Sthorpej 			break;
24341a68e94Sthorpej 
24441a68e94Sthorpej 		case SPEED_100:
24541a68e94Sthorpej 			mii->mii_media_active |= IFM_100_TX;
24641a68e94Sthorpej 			break;
24741a68e94Sthorpej 
24841a68e94Sthorpej 		case SPEED_10_MII:
24941a68e94Sthorpej 		case SPEED_10_SERIAL:
25041a68e94Sthorpej 			mii->mii_media_active |= IFM_10_T;
25141a68e94Sthorpej 			break;
25241a68e94Sthorpej 		}
25341a68e94Sthorpej 
25441a68e94Sthorpej 		if (qsr & QSR_DUPLEX)
25584694bb5Sthorpej 			mii->mii_media_active |=
25608645d15Sthorpej 			    IFM_FDX | mii_phy_flowstatus(sc);
257b211437bSmsaitoh 		else
258b211437bSmsaitoh 			mii->mii_media_active |= IFM_HDX;
25941a68e94Sthorpej 	} else
26041a68e94Sthorpej 		mii->mii_media_active = ife->ifm_media;
26141a68e94Sthorpej }
262