nsgphy.c revision 331722
1138568Ssam/*-
2178354Ssam * Copyright (c) 2001 Wind River Systems
3138568Ssam * Copyright (c) 2001
4138568Ssam *	Bill Paul <wpaul@bsdi.com>.  All rights reserved.
5138568Ssam * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
6138568Ssam * All rights reserved.
7138568Ssam *
8138568Ssam * This code is derived from software contributed to The NetBSD Foundation
9138568Ssam * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10138568Ssam * NASA Ames Research Center.
11138568Ssam *
12138568Ssam * Redistribution and use in source and binary forms, with or without
13138568Ssam * modification, are permitted provided that the following conditions
14138568Ssam * are met:
15138568Ssam * 1. Redistributions of source code must retain the above copyright
16138568Ssam *    notice, this list of conditions and the following disclaimer.
17138568Ssam * 2. Redistributions in binary form must reproduce the above copyright
18138568Ssam *    notice, this list of conditions and the following disclaimer in the
19138568Ssam *    documentation and/or other materials provided with the distribution.
20138568Ssam * 3. All advertising materials mentioning features or use of this software
21138568Ssam *    must display the following acknowledgement:
22138568Ssam *	This product includes software developed by Bill Paul.
23138568Ssam * 4. Neither the name of the author nor the names of any co-contributors
24138568Ssam *    may be used to endorse or promote products derived from this software
25138568Ssam *    without specific prior written permission.
26138568Ssam *
27138568Ssam * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
28138568Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29138568Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30165911Ssam * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
31298899Savos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32283614Sglebius * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33283614Sglebius * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34178354Ssam * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35178354Ssam * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36178354Ssam * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37192473Ssam * THE POSSIBILITY OF SUCH DAMAGE.
38191746Sthompsa */
39178354Ssam
40138568Ssam#include <sys/cdefs.h>
41170530Ssam__FBSDID("$FreeBSD: stable/11/sys/dev/mii/nsgphy.c 331722 2018-03-29 02:50:57Z eadler $");
42170530Ssam
43179388Ssam/*
44179388Ssam * Driver for the National Semiconductor DP83861, DP83865 and DP83891
45179388Ssam * 10/100/1000 PHYs.
46179388Ssam * Datasheet available at: http://www.national.com/ds/DP/DP83861.pdf
47179388Ssam * and at: http://www.national.com/ds/DP/DP83865.pdf
48179388Ssam *
49179388Ssam * The DP83891 is the older NS GigE PHY which isn't being sold
50179388Ssam * anymore.  The DP83861 is its replacement, which is an 'enhanced'
51179388Ssam * firmware driven component.  The major difference between the
52179388Ssam * two is that the DP83891 can't generate interrupts, while the
53179388Ssam * 83861 can (probably it wasn't originally designed to do this, but
54179388Ssam * it can now thanks to firmware updates).  The DP83861 also allows
55179388Ssam * access to its internal RAM via indirect register access.  The
56170530Ssam * DP83865 is an ultra low power version of the DP83861 and DP83891.
57179388Ssam */
58243532Sadrian
59243532Sadrian#include <sys/param.h>
60170530Ssam#include <sys/systm.h>
61170530Ssam#include <sys/kernel.h>
62248069Sadrian#include <sys/module.h>
63248069Sadrian#include <sys/socket.h>
64248069Sadrian#include <sys/bus.h>
65248069Sadrian
66248069Sadrian#include <net/if.h>
67248069Sadrian#include <net/if_media.h>
68296171Savos
69248069Sadrian#include <dev/mii/mii.h>
70248069Sadrian#include <dev/mii/miivar.h>
71248069Sadrian#include "miidevs.h"
72248069Sadrian
73248069Sadrian#include <dev/mii/nsgphyreg.h>
74248069Sadrian
75248069Sadrian#include "miibus_if.h"
76248069Sadrian
77248069Sadrianstatic int nsgphy_probe(device_t);
78248069Sadrianstatic int nsgphy_attach(device_t);
79248069Sadrian
80248069Sadrianstatic device_method_t nsgphy_methods[] = {
81248069Sadrian	/* device interface */
82248069Sadrian	DEVMETHOD(device_probe,		nsgphy_probe),
83248069Sadrian	DEVMETHOD(device_attach,	nsgphy_attach),
84248069Sadrian	DEVMETHOD(device_detach,	mii_phy_detach),
85248069Sadrian	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
86138568Ssam	DEVMETHOD_END
87138568Ssam};
88178354Ssam
89178354Ssamstatic devclass_t nsgphy_devclass;
90178354Ssam
91178354Ssamstatic driver_t nsgphy_driver = {
92178354Ssam	"nsgphy",
93178354Ssam	nsgphy_methods,
94178354Ssam	sizeof(struct mii_softc)
95179388Ssam};
96178354Ssam
97179388SsamDRIVER_MODULE(nsgphy, miibus, nsgphy_driver, nsgphy_devclass, 0, 0);
98178354Ssam
99179388Ssamstatic int	nsgphy_service(struct mii_softc *, struct mii_data *,int);
100178354Ssamstatic void	nsgphy_status(struct mii_softc *);
101179388Ssam
102178354Ssamstatic const struct mii_phydesc nsgphys[] = {
103179388Ssam	MII_PHY_DESC(xxNATSEMI, DP83861),
104178354Ssam	MII_PHY_DESC(xxNATSEMI, DP83865),
105179388Ssam	MII_PHY_DESC(xxNATSEMI, DP83891),
106178354Ssam	MII_PHY_END
107179388Ssam};
108138568Ssam
109138568Ssamstatic const struct mii_phy_funcs nsgphy_funcs = {
110178354Ssam	nsgphy_service,
111178354Ssam	nsgphy_status,
112178354Ssam	mii_phy_reset
113138568Ssam};
114178354Ssam
115178354Ssamstatic int
116178354Ssamnsgphy_probe(device_t dev)
117178354Ssam{
118178354Ssam
119178354Ssam	return (mii_phy_dev_probe(dev, nsgphys, BUS_PROBE_DEFAULT));
120178354Ssam}
121179388Ssam
122178354Ssamstatic int
123179388Ssamnsgphy_attach(device_t dev)
124178354Ssam{
125179388Ssam	struct mii_softc *sc;
126178354Ssam
127179388Ssam	sc = device_get_softc(dev);
128178354Ssam
129179388Ssam	mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &nsgphy_funcs, 0);
130138568Ssam
131138568Ssam	PHY_RESET(sc);
132184288Ssam
133138568Ssam	/*
134184288Ssam	 * NB: the PHY has the 10BASE-T BMSR bits hard-wired to 0,
135184288Ssam	 * even though it supports 10BASE-T.
136195379Ssam	 */
137184288Ssam	sc->mii_capabilities = (PHY_READ(sc, MII_BMSR) |
138184288Ssam	    BMSR_10TFDX | BMSR_10THDX) & sc->mii_capmask;
139184288Ssam	/*
140138568Ssam	 * Note that as documented manual 1000BASE-T modes of DP83865 only
141167284Ssam	 * work together with other National Semiconductor PHYs.
142167284Ssam	 */
143167284Ssam	if (sc->mii_capabilities & BMSR_EXTSTAT)
144167284Ssam		sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
145167284Ssam
146167284Ssam	mii_phy_add_media(sc);
147167284Ssam	printf("\n");
148167284Ssam
149167284Ssam	MIIBUS_MEDIAINIT(sc->mii_dev);
150167284Ssam	return (0);
151167284Ssam}
152167284Ssam
153167284Ssamstatic int
154167284Ssamnsgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
155195379Ssam{
156195379Ssam
157195379Ssam	switch (cmd) {
158195379Ssam	case MII_POLLSTAT:
159195379Ssam		break;
160195379Ssam
161195379Ssam	case MII_MEDIACHG:
162195379Ssam		mii_phy_setmedia(sc);
163195379Ssam		break;
164195379Ssam
165167284Ssam	case MII_TICK:
166138568Ssam		if (mii_phy_tick(sc) == EJUSTRETURN)
167138568Ssam			return (0);
168138568Ssam		break;
169138568Ssam	}
170138568Ssam
171138568Ssam	/* Update the media status. */
172138568Ssam	PHY_STATUS(sc);
173138568Ssam
174138568Ssam	/* Callback if something changed. */
175138568Ssam	mii_phy_update(sc, cmd);
176138568Ssam	return (0);
177138568Ssam}
178138568Ssam
179206617Srpaulostatic void
180206617Srpaulonsgphy_status(struct mii_softc *sc)
181206617Srpaulo{
182206617Srpaulo	struct mii_data *mii = sc->mii_pdata;
183206617Srpaulo	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
184206617Srpaulo	int bmsr, bmcr, physup, gtsr;
185206617Srpaulo
186206617Srpaulo	mii->mii_media_status = IFM_AVALID;
187206617Srpaulo	mii->mii_media_active = IFM_ETHER;
188283556Sadrian
189283556Sadrian	bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
190283556Sadrian
191283556Sadrian	physup = PHY_READ(sc, NSGPHY_MII_PHYSUP);
192283556Sadrian
193283556Sadrian	if (physup & PHY_SUP_LINK)
194283556Sadrian		mii->mii_media_status |= IFM_ACTIVE;
195206617Srpaulo
196283555Sadrian	bmcr = PHY_READ(sc, MII_BMCR);
197283555Sadrian	if (bmcr & BMCR_ISO) {
198283555Sadrian		mii->mii_media_active |= IFM_NONE;
199283555Sadrian		mii->mii_media_status = 0;
200283555Sadrian		return;
201283555Sadrian	}
202283555Sadrian
203283555Sadrian	if (bmcr & BMCR_LOOP)
204283555Sadrian		mii->mii_media_active |= IFM_LOOP;
205283555Sadrian
206283555Sadrian	if (bmcr & BMCR_AUTOEN) {
207283555Sadrian		/*
208283555Sadrian		 * The media status bits are only valid if autonegotiation
209283555Sadrian		 * has completed (or it's disabled).
210283555Sadrian		 */
211283555Sadrian		if ((bmsr & BMSR_ACOMP) == 0) {
212283555Sadrian			/* Erg, still trying, I guess... */
213283555Sadrian			mii->mii_media_active |= IFM_NONE;
214283555Sadrian			return;
215283555Sadrian		}
216283555Sadrian
217138568Ssam		switch (physup & (PHY_SUP_SPEED1 | PHY_SUP_SPEED0)) {
218138568Ssam		case PHY_SUP_SPEED1:
219138568Ssam			mii->mii_media_active |= IFM_1000_T;
220138568Ssam			gtsr = PHY_READ(sc, MII_100T2SR);
221138568Ssam			if (gtsr & GTSR_MS_RES)
222138568Ssam				mii->mii_media_active |= IFM_ETH_MASTER;
223138568Ssam			break;
224138568Ssam
225138568Ssam		case PHY_SUP_SPEED0:
226138568Ssam			mii->mii_media_active |= IFM_100_TX;
227138568Ssam			break;
228138568Ssam
229138568Ssam		case 0:
230138568Ssam			mii->mii_media_active |= IFM_10_T;
231138568Ssam			break;
232138568Ssam
233138568Ssam		default:
234138568Ssam			mii->mii_media_active |= IFM_NONE;
235144618Ssam			mii->mii_media_status = 0;
236138568Ssam			return;
237138568Ssam		}
238165904Ssam
239178354Ssam		if (physup & PHY_SUP_DUPLEX)
240165894Ssam			mii->mii_media_active |=
241178354Ssam			    IFM_FDX | mii_phy_flowstatus(sc);
242165894Ssam		else
243178354Ssam			mii->mii_media_active |= IFM_HDX;
244178354Ssam	} else
245178354Ssam		mii->mii_media_active = ife->ifm_media;
246178354Ssam}
247178354Ssam