xref: /netbsd-src/sys/dev/mii/exphy.c (revision 7a9a30c5e763bb556f73924ae04973e33cc385da)
1*7a9a30c5Sthorpej /*	$NetBSD: exphy.c,v 1.58 2020/03/15 23:04:50 thorpej Exp $	*/
25bec5543Sthorpej 
35bec5543Sthorpej /*-
449014bf5Sthorpej  * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
55bec5543Sthorpej  * All rights reserved.
65bec5543Sthorpej  *
75bec5543Sthorpej  * This code is derived from software contributed to The NetBSD Foundation
85bec5543Sthorpej  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
95bec5543Sthorpej  * NASA Ames Research Center, and by Frank van der Linden.
105bec5543Sthorpej  *
115bec5543Sthorpej  * Redistribution and use in source and binary forms, with or without
125bec5543Sthorpej  * modification, are permitted provided that the following conditions
135bec5543Sthorpej  * are met:
145bec5543Sthorpej  * 1. Redistributions of source code must retain the above copyright
155bec5543Sthorpej  *    notice, this list of conditions and the following disclaimer.
165bec5543Sthorpej  * 2. Redistributions in binary form must reproduce the above copyright
175bec5543Sthorpej  *    notice, this list of conditions and the following disclaimer in the
185bec5543Sthorpej  *    documentation and/or other materials provided with the distribution.
195bec5543Sthorpej  *
205bec5543Sthorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
215bec5543Sthorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
225bec5543Sthorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
235bec5543Sthorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
245bec5543Sthorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
255bec5543Sthorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
265bec5543Sthorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
275bec5543Sthorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
285bec5543Sthorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
295bec5543Sthorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
305bec5543Sthorpej  * POSSIBILITY OF SUCH DAMAGE.
315bec5543Sthorpej  */
325bec5543Sthorpej 
335bec5543Sthorpej /*
345bec5543Sthorpej  * Copyright (c) 1997 Manuel Bouyer.  All rights reserved.
355bec5543Sthorpej  *
365bec5543Sthorpej  * Redistribution and use in source and binary forms, with or without
375bec5543Sthorpej  * modification, are permitted provided that the following conditions
385bec5543Sthorpej  * are met:
395bec5543Sthorpej  * 1. Redistributions of source code must retain the above copyright
405bec5543Sthorpej  *    notice, this list of conditions and the following disclaimer.
415bec5543Sthorpej  * 2. Redistributions in binary form must reproduce the above copyright
425bec5543Sthorpej  *    notice, this list of conditions and the following disclaimer in the
435bec5543Sthorpej  *    documentation and/or other materials provided with the distribution.
445bec5543Sthorpej  *
455bec5543Sthorpej  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
465bec5543Sthorpej  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
475bec5543Sthorpej  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
485bec5543Sthorpej  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
495bec5543Sthorpej  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
505bec5543Sthorpej  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
515bec5543Sthorpej  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
525bec5543Sthorpej  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
535bec5543Sthorpej  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
545bec5543Sthorpej  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
555bec5543Sthorpej  */
565bec5543Sthorpej 
575bec5543Sthorpej /*
585bec5543Sthorpej  * driver for 3Com internal PHYs
595bec5543Sthorpej  */
605bec5543Sthorpej 
618b7bb912Slukem #include <sys/cdefs.h>
62*7a9a30c5Sthorpej __KERNEL_RCSID(0, "$NetBSD: exphy.c,v 1.58 2020/03/15 23:04:50 thorpej Exp $");
638b7bb912Slukem 
645bec5543Sthorpej #include <sys/param.h>
655bec5543Sthorpej #include <sys/systm.h>
665bec5543Sthorpej #include <sys/kernel.h>
675bec5543Sthorpej #include <sys/device.h>
685bec5543Sthorpej #include <sys/socket.h>
695bec5543Sthorpej 
705bec5543Sthorpej #include <net/if.h>
715bec5543Sthorpej #include <net/if_media.h>
725bec5543Sthorpej 
735bec5543Sthorpej #include <dev/mii/mii.h>
745bec5543Sthorpej #include <dev/mii/miivar.h>
755bec5543Sthorpej #include <dev/mii/miidevs.h>
765bec5543Sthorpej 
777db0e577Sxtraeme static int	exphymatch(device_t, cfdata_t, void *);
787db0e577Sxtraeme static void	exphyattach(device_t, device_t, void *);
795bec5543Sthorpej 
807db0e577Sxtraeme CFATTACH_DECL_NEW(exphy, sizeof(struct mii_softc),
81c9b3657cSthorpej     exphymatch, exphyattach, mii_phy_detach, mii_phy_activate);
825bec5543Sthorpej 
831efb3da0Sthorpej static int	exphy_service(struct mii_softc *, struct mii_data *, int);
841efb3da0Sthorpej static void	exphy_reset(struct mii_softc *);
855bec5543Sthorpej 
861efb3da0Sthorpej static const struct mii_phy_funcs exphy_funcs = {
8749014bf5Sthorpej 	exphy_service, ukphy_status, exphy_reset,
8849014bf5Sthorpej };
8949014bf5Sthorpej 
901efb3da0Sthorpej static int
exphymatch(device_t parent,cfdata_t match,void * aux)917db0e577Sxtraeme exphymatch(device_t parent, cfdata_t match, void *aux)
925bec5543Sthorpej {
935bec5543Sthorpej 	struct mii_attach_args *ma = aux;
945bec5543Sthorpej 
955bec5543Sthorpej 	/*
965bec5543Sthorpej 	 * Argh, 3Com PHY reports oui == 0 model == 0!
975bec5543Sthorpej 	 */
98322ba3ccSthorpej 	if (MII_OUI(ma->mii_id1, ma->mii_id2) != 0 &&
99322ba3ccSthorpej 	    MII_MODEL(ma->mii_id2) != 0)
10002341723Smsaitoh 		return 0;
101322ba3ccSthorpej 
102322ba3ccSthorpej 	/*
103322ba3ccSthorpej 	 * Make sure the parent is an `ex'.
104322ba3ccSthorpej 	 */
105f518d0e3Skleink 	if (!device_is_a(parent, "ex"))
10602341723Smsaitoh 		return 0;
107322ba3ccSthorpej 
10802341723Smsaitoh 	return 10;
1095bec5543Sthorpej }
1105bec5543Sthorpej 
1111efb3da0Sthorpej static void
exphyattach(device_t parent,device_t self,void * aux)1127db0e577Sxtraeme exphyattach(device_t parent, device_t self, void *aux)
1135bec5543Sthorpej {
114838ee1e0Sthorpej 	struct mii_softc *sc = device_private(self);
1155bec5543Sthorpej 	struct mii_attach_args *ma = aux;
1165bec5543Sthorpej 	struct mii_data *mii = ma->mii_data;
1175bec5543Sthorpej 
118c31f87a5Sthorpej 	aprint_naive(": Media interface\n");
119c31f87a5Sthorpej 	aprint_normal(": 3Com internal media interface\n");
1205bec5543Sthorpej 
1217db0e577Sxtraeme 	sc->mii_dev = self;
1222a17544cSthorpej 	sc->mii_inst = mii->mii_instance;
1232a17544cSthorpej 	sc->mii_phy = ma->mii_phyno;
12449014bf5Sthorpej 	sc->mii_funcs = &exphy_funcs;
1252a17544cSthorpej 	sc->mii_pdata = mii;
126b0178985Sthorpej 	sc->mii_flags = ma->mii_flags;
1275bec5543Sthorpej 
1285bec5543Sthorpej 	/*
1295bec5543Sthorpej 	 * The 3Com PHY can never be isolated, so never allow non-zero
1305bec5543Sthorpej 	 * instances!
1315bec5543Sthorpej 	 */
1325bec5543Sthorpej 	if (mii->mii_instance != 0) {
133123ed98aSspz 		aprint_error_dev(self,
134123ed98aSspz 		    "ignoring this PHY, non-zero instance\n");
1355bec5543Sthorpej 		return;
1365bec5543Sthorpej 	}
1372a17544cSthorpej 	sc->mii_flags |= MIIF_NOISOLATE;
1385bec5543Sthorpej 
139*7a9a30c5Sthorpej 	mii_lock(mii);
140*7a9a30c5Sthorpej 
14149014bf5Sthorpej 	PHY_RESET(sc);
1425bec5543Sthorpej 
143a5cdd4b4Smsaitoh 	PHY_READ(sc, MII_BMSR, &sc->mii_capabilities);
144a5cdd4b4Smsaitoh 	sc->mii_capabilities &= ma->mii_capmask;
145509697f3Smsaitoh 
146*7a9a30c5Sthorpej 	mii_unlock(mii);
147*7a9a30c5Sthorpej 
14884dc99fdSthorpej 	mii_phy_add_media(sc);
1495bec5543Sthorpej }
1505bec5543Sthorpej 
1511efb3da0Sthorpej static int
exphy_service(struct mii_softc * sc,struct mii_data * mii,int cmd)15289893e42Sthorpej exphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
1535bec5543Sthorpej {
1541f074c78Sthorpej 	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
1555bec5543Sthorpej 
15602341723Smsaitoh 	/* We can't isolate the 3Com PHY, so it has to be the only one! */
1572a17544cSthorpej 	if (IFM_INST(ife->ifm_media) != sc->mii_inst)
158a24f6f77Sthorpej 		panic("exphy_service: can't isolate 3Com PHY");
1595bec5543Sthorpej 
160*7a9a30c5Sthorpej 	KASSERT(mii_locked(mii));
161*7a9a30c5Sthorpej 
1625bec5543Sthorpej 	switch (cmd) {
1635bec5543Sthorpej 	case MII_POLLSTAT:
1645bec5543Sthorpej 		break;
1655bec5543Sthorpej 
1665bec5543Sthorpej 	case MII_MEDIACHG:
16702341723Smsaitoh 		/* If the interface is not up, don't do anything. */
1685bec5543Sthorpej 		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
1695bec5543Sthorpej 			break;
1705bec5543Sthorpej 
1718fc600c3Sthorpej 		mii_phy_setmedia(sc);
1725bec5543Sthorpej 		break;
1735bec5543Sthorpej 
1745bec5543Sthorpej 	case MII_TICK:
17502341723Smsaitoh 		/* Only used for autonegotiation. */
1761f074c78Sthorpej 		if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
177d2c936efSmsaitoh 			break;
1785bec5543Sthorpej 
179ad61d101Sthorpej 		if (mii_phy_tick(sc) == EJUSTRETURN)
18002341723Smsaitoh 			return 0;
1815bec5543Sthorpej 		break;
182bca88a28Sthorpej 
183bca88a28Sthorpej 	case MII_DOWN:
184bca88a28Sthorpej 		mii_phy_down(sc);
18502341723Smsaitoh 		return 0;
1865bec5543Sthorpej 	}
1875bec5543Sthorpej 
1885bec5543Sthorpej 	/* Update the media status. */
1898923ca0bSthorpej 	mii_phy_status(sc);
1905bec5543Sthorpej 
1915bec5543Sthorpej 	/* Callback if something changed. */
192ad61d101Sthorpej 	mii_phy_update(sc, cmd);
19302341723Smsaitoh 	return 0;
1945bec5543Sthorpej }
1955bec5543Sthorpej 
1961efb3da0Sthorpej static void
exphy_reset(struct mii_softc * sc)19789893e42Sthorpej exphy_reset(struct mii_softc *sc)
1985bec5543Sthorpej {
1995bec5543Sthorpej 
200*7a9a30c5Sthorpej 	KASSERT(mii_locked(sc->mii_pdata));
201*7a9a30c5Sthorpej 
2022a17544cSthorpej 	mii_phy_reset(sc);
2035bec5543Sthorpej 
2045bec5543Sthorpej 	/*
2055bec5543Sthorpej 	 * XXX 3Com PHY doesn't set the BMCR properly after
2065bec5543Sthorpej 	 * XXX reset, which breaks autonegotiation.
2075bec5543Sthorpej 	 */
2082a17544cSthorpej 	PHY_WRITE(sc, MII_BMCR, BMCR_S100 | BMCR_AUTOEN | BMCR_FDX);
2095bec5543Sthorpej }
210