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, ®);
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, >sr);
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