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