xref: /dflybsd-src/sys/dev/netif/mii_layer/ciphy.c (revision 2267fd784e8a7d1ca13e6d3541caa91f36c9e9fb)
146ad174eSSepherosa Ziehau /*	$OpenBSD: ciphy.c,v 1.13 2006/03/10 09:53:16 jsg Exp $	*/
246ad174eSSepherosa Ziehau 
313bca4c6SSepherosa Ziehau /*
413bca4c6SSepherosa Ziehau  * Copyright (c) 2004
513bca4c6SSepherosa Ziehau  *	Bill Paul <wpaul@windriver.com>.  All rights reserved.
613bca4c6SSepherosa Ziehau  *
713bca4c6SSepherosa Ziehau  * Redistribution and use in source and binary forms, with or without
813bca4c6SSepherosa Ziehau  * modification, are permitted provided that the following conditions
913bca4c6SSepherosa Ziehau  * are met:
1013bca4c6SSepherosa Ziehau  * 1. Redistributions of source code must retain the above copyright
1113bca4c6SSepherosa Ziehau  *    notice, this list of conditions and the following disclaimer.
1213bca4c6SSepherosa Ziehau  * 2. Redistributions in binary form must reproduce the above copyright
1313bca4c6SSepherosa Ziehau  *    notice, this list of conditions and the following disclaimer in the
1413bca4c6SSepherosa Ziehau  *    documentation and/or other materials provided with the distribution.
1513bca4c6SSepherosa Ziehau  * 3. All advertising materials mentioning features or use of this software
1613bca4c6SSepherosa Ziehau  *    must display the following acknowledgement:
1713bca4c6SSepherosa Ziehau  *	This product includes software developed by Bill Paul.
1813bca4c6SSepherosa Ziehau  * 4. Neither the name of the author nor the names of any co-contributors
1913bca4c6SSepherosa Ziehau  *    may be used to endorse or promote products derived from this software
2013bca4c6SSepherosa Ziehau  *    without specific prior written permission.
2113bca4c6SSepherosa Ziehau  *
2213bca4c6SSepherosa Ziehau  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
2313bca4c6SSepherosa Ziehau  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2413bca4c6SSepherosa Ziehau  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2513bca4c6SSepherosa Ziehau  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
2613bca4c6SSepherosa Ziehau  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2713bca4c6SSepherosa Ziehau  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2813bca4c6SSepherosa Ziehau  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2913bca4c6SSepherosa Ziehau  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3013bca4c6SSepherosa Ziehau  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3113bca4c6SSepherosa Ziehau  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
3213bca4c6SSepherosa Ziehau  * THE POSSIBILITY OF SUCH DAMAGE.
3313bca4c6SSepherosa Ziehau  *
3413bca4c6SSepherosa Ziehau  * $FreeBSD: src/sys/dev/mii/ciphy.c,v 1.3 2005/09/30 19:39:27 imp Exp $
3513bca4c6SSepherosa Ziehau  */
3613bca4c6SSepherosa Ziehau 
3713bca4c6SSepherosa Ziehau /*
3813bca4c6SSepherosa Ziehau  * Driver for the Cicada CS8201 10/100/1000 copper PHY.
3913bca4c6SSepherosa Ziehau  */
4013bca4c6SSepherosa Ziehau 
4113bca4c6SSepherosa Ziehau #include <sys/param.h>
4213bca4c6SSepherosa Ziehau #include <sys/systm.h>
4313bca4c6SSepherosa Ziehau #include <sys/kernel.h>
4413bca4c6SSepherosa Ziehau #include <sys/module.h>
4513bca4c6SSepherosa Ziehau #include <sys/socket.h>
4613bca4c6SSepherosa Ziehau #include <sys/bus.h>
4713bca4c6SSepherosa Ziehau 
4813bca4c6SSepherosa Ziehau #include <net/if.h>
4913bca4c6SSepherosa Ziehau #include <net/if_arp.h>
5013bca4c6SSepherosa Ziehau #include <net/if_media.h>
5113bca4c6SSepherosa Ziehau 
5213bca4c6SSepherosa Ziehau #include <dev/netif/mii_layer/mii.h>
5313bca4c6SSepherosa Ziehau #include <dev/netif/mii_layer/miivar.h>
5413bca4c6SSepherosa Ziehau 
5513bca4c6SSepherosa Ziehau #include "miidevs.h"
5613bca4c6SSepherosa Ziehau #include "miibus_if.h"
5713bca4c6SSepherosa Ziehau 
5813bca4c6SSepherosa Ziehau #include <dev/netif/mii_layer/ciphyreg.h>
5913bca4c6SSepherosa Ziehau 
6013bca4c6SSepherosa Ziehau static int ciphy_probe(device_t);
6113bca4c6SSepherosa Ziehau static int ciphy_attach(device_t);
6213bca4c6SSepherosa Ziehau 
6313bca4c6SSepherosa Ziehau static device_method_t ciphy_methods[] = {
6413bca4c6SSepherosa Ziehau 	/* device interface */
6513bca4c6SSepherosa Ziehau 	DEVMETHOD(device_probe,		ciphy_probe),
6613bca4c6SSepherosa Ziehau 	DEVMETHOD(device_attach,	ciphy_attach),
6713bca4c6SSepherosa Ziehau 	DEVMETHOD(device_detach,	ukphy_detach),
6813bca4c6SSepherosa Ziehau 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
69*d3c9c58eSSascha Wildner 	DEVMETHOD_END
7013bca4c6SSepherosa Ziehau };
7113bca4c6SSepherosa Ziehau 
7246ad174eSSepherosa Ziehau static const struct mii_phydesc ciphys[] = {
7346ad174eSSepherosa Ziehau 	MII_PHYDESC(CICADA,	CS8201),
7446ad174eSSepherosa Ziehau 	MII_PHYDESC(CICADA,	CS8201A),
7546ad174eSSepherosa Ziehau 	MII_PHYDESC(CICADA,	CS8201B),
7646ad174eSSepherosa Ziehau 	MII_PHYDESC(xxCICADA,	CS8201),
7746ad174eSSepherosa Ziehau 	MII_PHYDESC(xxCICADA,	CS8201A),
7846ad174eSSepherosa Ziehau 	MII_PHYDESC(xxCICADA,	CS8201B),
797896c317SHasso Tepper 	MII_PHYDESC(VITESSE,	VSC8601),
8046ad174eSSepherosa Ziehau 	MII_PHYDESC_NULL
8146ad174eSSepherosa Ziehau };
8246ad174eSSepherosa Ziehau 
8313bca4c6SSepherosa Ziehau static devclass_t ciphy_devclass;
8413bca4c6SSepherosa Ziehau 
8513bca4c6SSepherosa Ziehau static driver_t ciphy_driver = {
8613bca4c6SSepherosa Ziehau 	"ciphy",
8713bca4c6SSepherosa Ziehau 	ciphy_methods,
8813bca4c6SSepherosa Ziehau 	sizeof(struct mii_softc)
8913bca4c6SSepherosa Ziehau };
9013bca4c6SSepherosa Ziehau 
91aa2b9d05SSascha Wildner DRIVER_MODULE(ciphy, miibus, ciphy_driver, ciphy_devclass, NULL, NULL);
9213bca4c6SSepherosa Ziehau 
9313bca4c6SSepherosa Ziehau static int	ciphy_service(struct mii_softc *, struct mii_data *, int);
9413bca4c6SSepherosa Ziehau static void	ciphy_status(struct mii_softc *);
9513bca4c6SSepherosa Ziehau static void	ciphy_reset(struct mii_softc *);
9613bca4c6SSepherosa Ziehau static void	ciphy_fixup(struct mii_softc *);
9713bca4c6SSepherosa Ziehau 
9813bca4c6SSepherosa Ziehau static int
ciphy_probe(device_t dev)9913bca4c6SSepherosa Ziehau ciphy_probe(device_t dev)
10013bca4c6SSepherosa Ziehau {
10146ad174eSSepherosa Ziehau 	struct mii_attach_args *ma = device_get_ivars(dev);
10246ad174eSSepherosa Ziehau 	const struct mii_phydesc *mpd;
10313bca4c6SSepherosa Ziehau 
10446ad174eSSepherosa Ziehau 	mpd = mii_phy_match(ma, ciphys);
10546ad174eSSepherosa Ziehau 	if (mpd != NULL) {
10646ad174eSSepherosa Ziehau 		device_set_desc(dev, mpd->mpd_name);
10713bca4c6SSepherosa Ziehau 		return (0);
10813bca4c6SSepherosa Ziehau 	}
10913bca4c6SSepherosa Ziehau 	return (ENXIO);
11013bca4c6SSepherosa Ziehau }
11113bca4c6SSepherosa Ziehau 
11213bca4c6SSepherosa Ziehau static int
ciphy_attach(device_t dev)11313bca4c6SSepherosa Ziehau ciphy_attach(device_t dev)
11413bca4c6SSepherosa Ziehau {
11513bca4c6SSepherosa Ziehau 	struct mii_softc *sc;
11613bca4c6SSepherosa Ziehau 	struct mii_attach_args *ma;
11713bca4c6SSepherosa Ziehau 	struct mii_data *mii;
11813bca4c6SSepherosa Ziehau 
11913bca4c6SSepherosa Ziehau 	sc = device_get_softc(dev);
12013bca4c6SSepherosa Ziehau 	ma = device_get_ivars(dev);
12113bca4c6SSepherosa Ziehau 	mii_softc_init(sc, ma);
12213bca4c6SSepherosa Ziehau 
12313bca4c6SSepherosa Ziehau 	sc->mii_dev = device_get_parent(dev);
12413bca4c6SSepherosa Ziehau 	mii = device_get_softc(sc->mii_dev);
12513bca4c6SSepherosa Ziehau 	LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
12613bca4c6SSepherosa Ziehau 
12713bca4c6SSepherosa Ziehau 	sc->mii_inst = mii->mii_instance;
12813bca4c6SSepherosa Ziehau 	sc->mii_service = ciphy_service;
12946ad174eSSepherosa Ziehau 	sc->mii_reset = ciphy_reset;
13013bca4c6SSepherosa Ziehau 	sc->mii_pdata = mii;
13113bca4c6SSepherosa Ziehau 
13213bca4c6SSepherosa Ziehau 	sc->mii_flags |= MIIF_NOISOLATE;
13313bca4c6SSepherosa Ziehau 	mii->mii_instance++;
13413bca4c6SSepherosa Ziehau 
13513bca4c6SSepherosa Ziehau 	ciphy_reset(sc);
13613bca4c6SSepherosa Ziehau 
13713bca4c6SSepherosa Ziehau 	sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
13813bca4c6SSepherosa Ziehau 	if (sc->mii_capabilities & BMSR_EXTSTAT)
13913bca4c6SSepherosa Ziehau 		sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
14013bca4c6SSepherosa Ziehau 
14113bca4c6SSepherosa Ziehau 	device_printf(dev, " ");
14246ad174eSSepherosa Ziehau 	if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 &&
14346ad174eSSepherosa Ziehau 	    (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0)
144e3869ec7SSascha Wildner 		kprintf("no media present");
14546ad174eSSepherosa Ziehau 	else
14646ad174eSSepherosa Ziehau 		mii_phy_add_media(sc);
147e3869ec7SSascha Wildner 	kprintf("\n");
14813bca4c6SSepherosa Ziehau 
14913bca4c6SSepherosa Ziehau 	MIIBUS_MEDIAINIT(sc->mii_dev);
15013bca4c6SSepherosa Ziehau 	return(0);
15113bca4c6SSepherosa Ziehau }
15213bca4c6SSepherosa Ziehau 
15313bca4c6SSepherosa Ziehau static int
ciphy_service(struct mii_softc * sc,struct mii_data * mii,int cmd)15413bca4c6SSepherosa Ziehau ciphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
15513bca4c6SSepherosa Ziehau {
15613bca4c6SSepherosa Ziehau 	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
15713bca4c6SSepherosa Ziehau 	int reg, speed, gig;
15813bca4c6SSepherosa Ziehau 
15913bca4c6SSepherosa Ziehau 	switch (cmd) {
16013bca4c6SSepherosa Ziehau 	case MII_POLLSTAT:
16113bca4c6SSepherosa Ziehau 		/*
16213bca4c6SSepherosa Ziehau 		 * If we're not polling our PHY instance, just return.
16313bca4c6SSepherosa Ziehau 		 */
16413bca4c6SSepherosa Ziehau 		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
16513bca4c6SSepherosa Ziehau 			return (0);
16613bca4c6SSepherosa Ziehau 		break;
16713bca4c6SSepherosa Ziehau 
16813bca4c6SSepherosa Ziehau 	case MII_MEDIACHG:
16913bca4c6SSepherosa Ziehau 		/*
17013bca4c6SSepherosa Ziehau 		 * If the media indicates a different PHY instance,
17113bca4c6SSepherosa Ziehau 		 * isolate ourselves.
17213bca4c6SSepherosa Ziehau 		 */
17313bca4c6SSepherosa Ziehau 		if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
17413bca4c6SSepherosa Ziehau 			reg = PHY_READ(sc, MII_BMCR);
17513bca4c6SSepherosa Ziehau 			PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
17613bca4c6SSepherosa Ziehau 			return (0);
17713bca4c6SSepherosa Ziehau 		}
17813bca4c6SSepherosa Ziehau 
17913bca4c6SSepherosa Ziehau 		/*
18013bca4c6SSepherosa Ziehau 		 * If the interface is not up, don't do anything.
18113bca4c6SSepherosa Ziehau 		 */
18213bca4c6SSepherosa Ziehau 		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
18313bca4c6SSepherosa Ziehau 			break;
18413bca4c6SSepherosa Ziehau 
18513bca4c6SSepherosa Ziehau 		ciphy_fixup(sc);	/* XXX hardware bug work-around */
18613bca4c6SSepherosa Ziehau 
18713bca4c6SSepherosa Ziehau 		switch (IFM_SUBTYPE(ife->ifm_media)) {
18813bca4c6SSepherosa Ziehau 		case IFM_AUTO:
18913bca4c6SSepherosa Ziehau #ifdef foo
19013bca4c6SSepherosa Ziehau 			/*
19113bca4c6SSepherosa Ziehau 			 * If we're already in auto mode, just return.
19213bca4c6SSepherosa Ziehau 			 */
19313bca4c6SSepherosa Ziehau 			if (PHY_READ(sc, CIPHY_MII_BMCR) & CIPHY_BMCR_AUTOEN)
19413bca4c6SSepherosa Ziehau 				return (0);
19513bca4c6SSepherosa Ziehau #endif
19646ad174eSSepherosa Ziehau 			if (mii_phy_auto(sc, 0) == EJUSTRETURN)
19746ad174eSSepherosa Ziehau 				return (0);
19813bca4c6SSepherosa Ziehau 			break;
19913bca4c6SSepherosa Ziehau 		case IFM_1000_T:
20013bca4c6SSepherosa Ziehau 			speed = CIPHY_S1000;
20113bca4c6SSepherosa Ziehau 			goto setit;
20213bca4c6SSepherosa Ziehau 		case IFM_100_TX:
20313bca4c6SSepherosa Ziehau 			speed = CIPHY_S100;
20413bca4c6SSepherosa Ziehau 			goto setit;
20513bca4c6SSepherosa Ziehau 		case IFM_10_T:
20613bca4c6SSepherosa Ziehau 			speed = CIPHY_S10;
20713bca4c6SSepherosa Ziehau setit:
20813bca4c6SSepherosa Ziehau 			if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
20913bca4c6SSepherosa Ziehau 				speed |= CIPHY_BMCR_FDX;
21013bca4c6SSepherosa Ziehau 				gig = CIPHY_1000CTL_AFD;
21113bca4c6SSepherosa Ziehau 			} else {
21213bca4c6SSepherosa Ziehau 				gig = CIPHY_1000CTL_AHD;
21313bca4c6SSepherosa Ziehau 			}
21413bca4c6SSepherosa Ziehau 
21513bca4c6SSepherosa Ziehau 			PHY_WRITE(sc, CIPHY_MII_1000CTL, 0);
21613bca4c6SSepherosa Ziehau 			PHY_WRITE(sc, CIPHY_MII_BMCR, speed);
21713bca4c6SSepherosa Ziehau 			PHY_WRITE(sc, CIPHY_MII_ANAR, CIPHY_SEL_TYPE);
21813bca4c6SSepherosa Ziehau 
21913bca4c6SSepherosa Ziehau 			if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)
22013bca4c6SSepherosa Ziehau 				break;
22113bca4c6SSepherosa Ziehau 
22213bca4c6SSepherosa Ziehau 			PHY_WRITE(sc, CIPHY_MII_1000CTL, gig);
22313bca4c6SSepherosa Ziehau 			PHY_WRITE(sc, CIPHY_MII_BMCR,
22413bca4c6SSepherosa Ziehau 			    speed|CIPHY_BMCR_AUTOEN|CIPHY_BMCR_STARTNEG);
22513bca4c6SSepherosa Ziehau 
22613bca4c6SSepherosa Ziehau 			/*
22713bca4c6SSepherosa Ziehau 			 * When setting the link manually, one side must
22813bca4c6SSepherosa Ziehau 			 * be the master and the other the slave. However
22913bca4c6SSepherosa Ziehau 			 * ifmedia doesn't give us a good way to specify
23013bca4c6SSepherosa Ziehau 			 * this, so we fake it by using one of the LINK
23113bca4c6SSepherosa Ziehau 			 * flags. If LINK0 is set, we program the PHY to
23213bca4c6SSepherosa Ziehau 			 * be a master, otherwise it's a slave.
23313bca4c6SSepherosa Ziehau 			 */
23413bca4c6SSepherosa Ziehau 			if ((mii->mii_ifp->if_flags & IFF_LINK0)) {
23513bca4c6SSepherosa Ziehau 				PHY_WRITE(sc, CIPHY_MII_1000CTL,
23613bca4c6SSepherosa Ziehau 				    gig|CIPHY_1000CTL_MSE|CIPHY_1000CTL_MSC);
23713bca4c6SSepherosa Ziehau 			} else {
23813bca4c6SSepherosa Ziehau 				PHY_WRITE(sc, CIPHY_MII_1000CTL,
23913bca4c6SSepherosa Ziehau 				    gig|CIPHY_1000CTL_MSE);
24013bca4c6SSepherosa Ziehau 			}
24113bca4c6SSepherosa Ziehau 			break;
24213bca4c6SSepherosa Ziehau 		case IFM_NONE:
24313bca4c6SSepherosa Ziehau 			PHY_WRITE(sc, MII_BMCR, BMCR_ISO|BMCR_PDOWN);
24413bca4c6SSepherosa Ziehau 			break;
24513bca4c6SSepherosa Ziehau 		case IFM_100_T4:
24613bca4c6SSepherosa Ziehau 		default:
24713bca4c6SSepherosa Ziehau 			return (EINVAL);
24813bca4c6SSepherosa Ziehau 		}
24913bca4c6SSepherosa Ziehau 		break;
25013bca4c6SSepherosa Ziehau 
25113bca4c6SSepherosa Ziehau 	case MII_TICK:
25213bca4c6SSepherosa Ziehau 		/*
25313bca4c6SSepherosa Ziehau 		 * If we're not currently selected, just return.
25413bca4c6SSepherosa Ziehau 		 */
25513bca4c6SSepherosa Ziehau 		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
25613bca4c6SSepherosa Ziehau 			return (0);
25713bca4c6SSepherosa Ziehau 
25846ad174eSSepherosa Ziehau 		if (mii_phy_tick(sc) == EJUSTRETURN)
25913bca4c6SSepherosa Ziehau 			return (0);
26013bca4c6SSepherosa Ziehau 		break;
26113bca4c6SSepherosa Ziehau 	}
26213bca4c6SSepherosa Ziehau 
26313bca4c6SSepherosa Ziehau 	/* Update the media status. */
26413bca4c6SSepherosa Ziehau 	ciphy_status(sc);
26513bca4c6SSepherosa Ziehau 
26613bca4c6SSepherosa Ziehau 	/*
26713bca4c6SSepherosa Ziehau 	 * Callback if something changed. Note that we need to poke
26813bca4c6SSepherosa Ziehau 	 * apply fixups for certain PHY revs.
26913bca4c6SSepherosa Ziehau 	 */
27046ad174eSSepherosa Ziehau 	if (sc->mii_media_active != mii->mii_media_active ||
27146ad174eSSepherosa Ziehau 	    sc->mii_media_status != mii->mii_media_status ||
27246ad174eSSepherosa Ziehau 	    cmd == MII_MEDIACHG)
27313bca4c6SSepherosa Ziehau 		ciphy_fixup(sc);
27446ad174eSSepherosa Ziehau 	mii_phy_update(sc, cmd);
27513bca4c6SSepherosa Ziehau 	return (0);
27613bca4c6SSepherosa Ziehau }
27713bca4c6SSepherosa Ziehau 
27813bca4c6SSepherosa Ziehau static void
ciphy_status(struct mii_softc * sc)27913bca4c6SSepherosa Ziehau ciphy_status(struct mii_softc *sc)
28013bca4c6SSepherosa Ziehau {
28113bca4c6SSepherosa Ziehau 	struct mii_data *mii = sc->mii_pdata;
28213bca4c6SSepherosa Ziehau 	int bmsr, bmcr;
28313bca4c6SSepherosa Ziehau 
28413bca4c6SSepherosa Ziehau 	mii->mii_media_status = IFM_AVALID;
28513bca4c6SSepherosa Ziehau 	mii->mii_media_active = IFM_ETHER;
28613bca4c6SSepherosa Ziehau 
28713bca4c6SSepherosa Ziehau 	bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
28813bca4c6SSepherosa Ziehau 
28913bca4c6SSepherosa Ziehau 	if (bmsr & BMSR_LINK)
29013bca4c6SSepherosa Ziehau 		mii->mii_media_status |= IFM_ACTIVE;
29113bca4c6SSepherosa Ziehau 
29213bca4c6SSepherosa Ziehau 	bmcr = PHY_READ(sc, CIPHY_MII_BMCR);
29313bca4c6SSepherosa Ziehau 
29413bca4c6SSepherosa Ziehau 	if (bmcr & CIPHY_BMCR_LOOP)
29513bca4c6SSepherosa Ziehau 		mii->mii_media_active |= IFM_LOOP;
29613bca4c6SSepherosa Ziehau 
29713bca4c6SSepherosa Ziehau 	if (bmcr & CIPHY_BMCR_AUTOEN) {
29813bca4c6SSepherosa Ziehau 		if ((bmsr & CIPHY_BMSR_ACOMP) == 0) {
29913bca4c6SSepherosa Ziehau 			/* Erg, still trying, I guess... */
30013bca4c6SSepherosa Ziehau 			mii->mii_media_active |= IFM_NONE;
30113bca4c6SSepherosa Ziehau 			return;
30213bca4c6SSepherosa Ziehau 		}
30313bca4c6SSepherosa Ziehau 	}
30413bca4c6SSepherosa Ziehau 
30513bca4c6SSepherosa Ziehau 	bmsr = PHY_READ(sc, CIPHY_MII_AUXCSR);
30613bca4c6SSepherosa Ziehau 	switch (bmsr & CIPHY_AUXCSR_SPEED) {
30713bca4c6SSepherosa Ziehau 	case CIPHY_SPEED10:
30813bca4c6SSepherosa Ziehau 		mii->mii_media_active |= IFM_10_T;
30913bca4c6SSepherosa Ziehau 		break;
31013bca4c6SSepherosa Ziehau 	case CIPHY_SPEED100:
31113bca4c6SSepherosa Ziehau 		mii->mii_media_active |= IFM_100_TX;
31213bca4c6SSepherosa Ziehau 		break;
31313bca4c6SSepherosa Ziehau 	case CIPHY_SPEED1000:
31413bca4c6SSepherosa Ziehau 		mii->mii_media_active |= IFM_1000_T;
31513bca4c6SSepherosa Ziehau 		break;
31613bca4c6SSepherosa Ziehau 	default:
31713bca4c6SSepherosa Ziehau 		device_printf(sc->mii_dev, "unknown PHY speed %x\n",
31813bca4c6SSepherosa Ziehau 		    bmsr & CIPHY_AUXCSR_SPEED);
31913bca4c6SSepherosa Ziehau 		break;
32013bca4c6SSepherosa Ziehau 	}
32113bca4c6SSepherosa Ziehau 
32213bca4c6SSepherosa Ziehau 	if (bmsr & CIPHY_AUXCSR_FDX)
32313bca4c6SSepherosa Ziehau 		mii->mii_media_active |= IFM_FDX;
32413bca4c6SSepherosa Ziehau }
32513bca4c6SSepherosa Ziehau 
32613bca4c6SSepherosa Ziehau static void
ciphy_reset(struct mii_softc * sc)32713bca4c6SSepherosa Ziehau ciphy_reset(struct mii_softc *sc)
32813bca4c6SSepherosa Ziehau {
32913bca4c6SSepherosa Ziehau 	mii_phy_reset(sc);
33013bca4c6SSepherosa Ziehau 	DELAY(1000);
33113bca4c6SSepherosa Ziehau }
33213bca4c6SSepherosa Ziehau 
33313bca4c6SSepherosa Ziehau #define PHY_SETBIT(x, y, z) \
33413bca4c6SSepherosa Ziehau 	PHY_WRITE(x, y, (PHY_READ(x, y) | (z)))
33513bca4c6SSepherosa Ziehau #define PHY_CLRBIT(x, y, z) \
33613bca4c6SSepherosa Ziehau 	PHY_WRITE(x, y, (PHY_READ(x, y) & ~(z)))
33713bca4c6SSepherosa Ziehau 
33813bca4c6SSepherosa Ziehau static void
ciphy_fixup(struct mii_softc * sc)33913bca4c6SSepherosa Ziehau ciphy_fixup(struct mii_softc *sc)
34013bca4c6SSepherosa Ziehau {
34146ad174eSSepherosa Ziehau 	uint16_t model, status, speed;
34246ad174eSSepherosa Ziehau 	device_t parent;
34313bca4c6SSepherosa Ziehau 
34413bca4c6SSepherosa Ziehau 	model = MII_MODEL(PHY_READ(sc, CIPHY_MII_PHYIDR2));
34513bca4c6SSepherosa Ziehau 	status = PHY_READ(sc, CIPHY_MII_AUXCSR);
34613bca4c6SSepherosa Ziehau 	speed = status & CIPHY_AUXCSR_SPEED;
34713bca4c6SSepherosa Ziehau 
34846ad174eSSepherosa Ziehau 	parent = device_get_parent(sc->mii_dev);
34946ad174eSSepherosa Ziehau 	if (strncmp(device_get_name(parent), "nfe", 3) == 0) {
35046ad174eSSepherosa Ziehau 		/* Need to set for 2.5V RGMII for NVIDIA adapters */
35146ad174eSSepherosa Ziehau 		PHY_SETBIT(sc, CIPHY_MII_ECTL1, CIPHY_INTSEL_RGMII);
35246ad174eSSepherosa Ziehau 		PHY_SETBIT(sc, CIPHY_MII_ECTL1, CIPHY_IOVOL_2500MV);
35346ad174eSSepherosa Ziehau 	}
35413bca4c6SSepherosa Ziehau 
35546ad174eSSepherosa Ziehau 	switch (model) {
35646ad174eSSepherosa Ziehau 	case MII_MODEL_CICADA_CS8201:	/* MII_MODEL_xxCICADA_CS8201 */
35713bca4c6SSepherosa Ziehau 		/* Turn off "aux mode" (whatever that means) */
35813bca4c6SSepherosa Ziehau 		PHY_SETBIT(sc, CIPHY_MII_AUXCSR, CIPHY_AUXCSR_MDPPS);
35913bca4c6SSepherosa Ziehau 
36013bca4c6SSepherosa Ziehau 		/*
36113bca4c6SSepherosa Ziehau 		 * Work around speed polling bug in VT3119/VT3216
36213bca4c6SSepherosa Ziehau 		 * when using MII in full duplex mode.
36313bca4c6SSepherosa Ziehau 		 */
36413bca4c6SSepherosa Ziehau 		if ((speed == CIPHY_SPEED10 || speed == CIPHY_SPEED100) &&
36513bca4c6SSepherosa Ziehau 		    (status & CIPHY_AUXCSR_FDX)) {
36613bca4c6SSepherosa Ziehau 			PHY_SETBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO);
36713bca4c6SSepherosa Ziehau 		} else {
36813bca4c6SSepherosa Ziehau 			PHY_CLRBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO);
36913bca4c6SSepherosa Ziehau 		}
37013bca4c6SSepherosa Ziehau 
37113bca4c6SSepherosa Ziehau 		/* Enable link/activity LED blink. */
37213bca4c6SSepherosa Ziehau 		PHY_SETBIT(sc, CIPHY_MII_LED, CIPHY_LED_LINKACTBLINK);
37313bca4c6SSepherosa Ziehau 		break;
37413bca4c6SSepherosa Ziehau 
37546ad174eSSepherosa Ziehau 	case MII_MODEL_CICADA_CS8201A:	/* MII_MODEL_xxCICADA_CS8201A */
37646ad174eSSepherosa Ziehau 	case MII_MODEL_CICADA_CS8201B:	/* MII_MODEL_xxCICADA_CS8201B */
37713bca4c6SSepherosa Ziehau 		/*
37813bca4c6SSepherosa Ziehau 		 * Work around speed polling bug in VT3119/VT3216
37913bca4c6SSepherosa Ziehau 		 * when using MII in full duplex mode.
38013bca4c6SSepherosa Ziehau 		 */
38113bca4c6SSepherosa Ziehau 		if ((speed == CIPHY_SPEED10 || speed == CIPHY_SPEED100) &&
38213bca4c6SSepherosa Ziehau 		    (status & CIPHY_AUXCSR_FDX)) {
38313bca4c6SSepherosa Ziehau 			PHY_SETBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO);
38413bca4c6SSepherosa Ziehau 		} else {
38513bca4c6SSepherosa Ziehau 			PHY_CLRBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO);
38613bca4c6SSepherosa Ziehau 		}
38713bca4c6SSepherosa Ziehau 		break;
38846ad174eSSepherosa Ziehau 
3897896c317SHasso Tepper 	case MII_MODEL_VITESSE_VSC8601:
3907896c317SHasso Tepper 		break;
3917896c317SHasso Tepper 
39213bca4c6SSepherosa Ziehau 	default:
39346ad174eSSepherosa Ziehau 		device_printf(sc->mii_dev,
39446ad174eSSepherosa Ziehau 			      "unknown CICADA PHY model %x\n", model);
39513bca4c6SSepherosa Ziehau 		break;
39613bca4c6SSepherosa Ziehau 	}
39713bca4c6SSepherosa Ziehau }
398