1170525Syongari/*	$NetBSD: icsphy.c,v 1.41 2006/11/16 21:24:07 christos Exp $	*/
2170525Syongari
3170525Syongari/*-
4170525Syongari * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
5170525Syongari * All rights reserved.
6170525Syongari *
7170525Syongari * This code is derived from software contributed to The NetBSD Foundation
8170525Syongari * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9170525Syongari * NASA Ames Research Center.
10170525Syongari *
11170525Syongari * Redistribution and use in source and binary forms, with or without
12170525Syongari * modification, are permitted provided that the following conditions
13170525Syongari * are met:
14170525Syongari * 1. Redistributions of source code must retain the above copyright
15170525Syongari *    notice, this list of conditions and the following disclaimer.
16170525Syongari * 2. Redistributions in binary form must reproduce the above copyright
17170525Syongari *    notice, this list of conditions and the following disclaimer in the
18170525Syongari *    documentation and/or other materials provided with the distribution.
19170525Syongari *
20170525Syongari * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21170525Syongari * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22170525Syongari * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23170525Syongari * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24170525Syongari * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25170525Syongari * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26170525Syongari * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27170525Syongari * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28170525Syongari * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29170525Syongari * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30170525Syongari * POSSIBILITY OF SUCH DAMAGE.
31170525Syongari */
32170525Syongari
33170525Syongari/*
34170525Syongari * Copyright (c) 1997 Manuel Bouyer.  All rights reserved.
35170525Syongari *
36170525Syongari * Redistribution and use in source and binary forms, with or without
37170525Syongari * modification, are permitted provided that the following conditions
38170525Syongari * are met:
39170525Syongari * 1. Redistributions of source code must retain the above copyright
40170525Syongari *    notice, this list of conditions and the following disclaimer.
41170525Syongari * 2. Redistributions in binary form must reproduce the above copyright
42170525Syongari *    notice, this list of conditions and the following disclaimer in the
43170525Syongari *    documentation and/or other materials provided with the distribution.
44170525Syongari *
45170525Syongari * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
46170525Syongari * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47170525Syongari * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
48170525Syongari * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
49170525Syongari * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50170525Syongari * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
51170525Syongari * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
52170525Syongari * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
53170525Syongari * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
54170525Syongari * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
55170525Syongari */
56170525Syongari
57170525Syongari#include <sys/cdefs.h>
58170525Syongari__FBSDID("$FreeBSD$");
59170525Syongari
60170525Syongari/*
61170525Syongari * driver for Integrated Circuit Systems' ICS1889-1893 ethernet 10/100 PHY
62170525Syongari * datasheet from www.icst.com
63170525Syongari */
64170525Syongari
65170525Syongari#include <sys/param.h>
66170525Syongari#include <sys/systm.h>
67170525Syongari#include <sys/kernel.h>
68170525Syongari#include <sys/module.h>
69170525Syongari#include <sys/socket.h>
70170525Syongari#include <sys/bus.h>
71170525Syongari
72170525Syongari#include <net/if.h>
73170525Syongari#include <net/if_media.h>
74170525Syongari
75170525Syongari#include <dev/mii/mii.h>
76170525Syongari#include <dev/mii/miivar.h>
77170525Syongari#include "miidevs.h"
78170525Syongari
79170525Syongari#include <dev/mii/icsphyreg.h>
80170525Syongari
81170525Syongari#include "miibus_if.h"
82170525Syongari
83170525Syongaristatic int	icsphy_probe(device_t dev);
84170525Syongaristatic int	icsphy_attach(device_t dev);
85170525Syongari
86170525Syongaristatic device_method_t icsphy_methods[] = {
87170525Syongari	/* device interface */
88170525Syongari	DEVMETHOD(device_probe,		icsphy_probe),
89170525Syongari	DEVMETHOD(device_attach,	icsphy_attach),
90170525Syongari	DEVMETHOD(device_detach,	mii_phy_detach),
91170525Syongari	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
92229093Shselasky	DEVMETHOD_END
93170525Syongari};
94170525Syongari
95170525Syongaristatic devclass_t icsphy_devclass;
96170525Syongari
97170525Syongaristatic driver_t icsphy_driver = {
98170525Syongari	"icsphy",
99170525Syongari	icsphy_methods,
100221407Smarius	sizeof(struct mii_softc)
101170525Syongari};
102170525Syongari
103170525SyongariDRIVER_MODULE(icsphy, miibus, icsphy_driver, icsphy_devclass, 0, 0);
104170525Syongari
105170525Syongaristatic int	icsphy_service(struct mii_softc *, struct mii_data *, int);
106170525Syongaristatic void	icsphy_status(struct mii_softc *);
107170525Syongaristatic void	icsphy_reset(struct mii_softc *);
108170525Syongari
109170525Syongaristatic const struct mii_phydesc icsphys[] = {
110221407Smarius	MII_PHY_DESC(ICS, 1889),
111221407Smarius	MII_PHY_DESC(ICS, 1890),
112221407Smarius	MII_PHY_DESC(ICS, 1892),
113221407Smarius	MII_PHY_DESC(ICS, 1893),
114170525Syongari	MII_PHY_END
115170525Syongari};
116170525Syongari
117221407Smariusstatic const struct mii_phy_funcs icsphy_funcs = {
118221407Smarius	icsphy_service,
119221407Smarius	icsphy_status,
120221407Smarius	icsphy_reset
121221407Smarius};
122221407Smarius
123170525Syongaristatic int
124170525Syongariicsphy_probe(device_t dev)
125170525Syongari{
126170525Syongari
127170525Syongari	return (mii_phy_dev_probe(dev, icsphys, BUS_PROBE_DEFAULT));
128170525Syongari}
129170525Syongari
130170525Syongaristatic int
131170525Syongariicsphy_attach(device_t dev)
132170525Syongari{
133170525Syongari
134221407Smarius	mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE,
135221407Smarius	    &icsphy_funcs, 1);
136170525Syongari	return (0);
137170525Syongari}
138170525Syongari
139170525Syongaristatic int
140170525Syongariicsphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
141170525Syongari{
142170525Syongari
143170525Syongari	switch (cmd) {
144170525Syongari	case MII_POLLSTAT:
145170525Syongari		break;
146170525Syongari
147170525Syongari	case MII_MEDIACHG:
148170525Syongari		/*
149170525Syongari		 * If the interface is not up, don't do anything.
150170525Syongari		 */
151170525Syongari		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
152170525Syongari			break;
153170525Syongari
154170525Syongari		mii_phy_setmedia(sc);
155170525Syongari		break;
156170525Syongari
157170525Syongari	case MII_TICK:
158170525Syongari		if (mii_phy_tick(sc) == EJUSTRETURN)
159170525Syongari			return (0);
160170525Syongari		break;
161170525Syongari	}
162170525Syongari
163170525Syongari	/* Update the media status. */
164221407Smarius	PHY_STATUS(sc);
165170525Syongari
166170525Syongari	/* Callback if something changed. */
167170525Syongari	mii_phy_update(sc, cmd);
168170525Syongari	return (0);
169170525Syongari}
170170525Syongari
171170525Syongaristatic void
172170525Syongariicsphy_status(struct mii_softc *sc)
173170525Syongari{
174170525Syongari	struct mii_data *mii = sc->mii_pdata;
175170525Syongari	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
176170525Syongari	int bmcr, qpr;
177170525Syongari
178170525Syongari	mii->mii_media_status = IFM_AVALID;
179170525Syongari	mii->mii_media_active = IFM_ETHER;
180170525Syongari
181170525Syongari	/*
182170525Syongari	 * Don't get link from the BMSR.  It's available in the QPR,
183170525Syongari	 * and we have to read it twice to unlatch it anyhow.  This
184170525Syongari	 * gives us fewer register reads.
185170525Syongari	 */
186170525Syongari	qpr = PHY_READ(sc, MII_ICSPHY_QPR);		/* unlatch */
187170525Syongari	qpr = PHY_READ(sc, MII_ICSPHY_QPR);		/* real value */
188170525Syongari
189170525Syongari	if (qpr & QPR_LINK)
190170525Syongari		mii->mii_media_status |= IFM_ACTIVE;
191170525Syongari
192170525Syongari	bmcr = PHY_READ(sc, MII_BMCR);
193170525Syongari	if (bmcr & BMCR_ISO) {
194170525Syongari		mii->mii_media_active |= IFM_NONE;
195170525Syongari		mii->mii_media_status = 0;
196170525Syongari		return;
197170525Syongari	}
198170525Syongari
199170525Syongari	if (bmcr & BMCR_LOOP)
200170525Syongari		mii->mii_media_active |= IFM_LOOP;
201170525Syongari
202170525Syongari	if (bmcr & BMCR_AUTOEN) {
203170525Syongari		if ((qpr & QPR_ACOMP) == 0) {
204170525Syongari			/* Erg, still trying, I guess... */
205170525Syongari			mii->mii_media_active |= IFM_NONE;
206170525Syongari			return;
207170525Syongari		}
208170525Syongari		if (qpr & QPR_SPEED)
209170525Syongari			mii->mii_media_active |= IFM_100_TX;
210170525Syongari		else
211170525Syongari			mii->mii_media_active |= IFM_10_T;
212170525Syongari		if (qpr & QPR_FDX)
213221407Smarius			mii->mii_media_active |=
214221407Smarius			    IFM_FDX | mii_phy_flowstatus(sc);
215170525Syongari		else
216170525Syongari			mii->mii_media_active |= IFM_HDX;
217170525Syongari	} else
218170525Syongari		mii->mii_media_active = ife->ifm_media;
219170525Syongari}
220170525Syongari
221170525Syongaristatic void
222170525Syongariicsphy_reset(struct mii_softc *sc)
223170525Syongari{
224170525Syongari
225170525Syongari	mii_phy_reset(sc);
226170525Syongari	/* set powerdown feature */
227221407Smarius	switch (sc->mii_mpd_model) {
228221407Smarius		case MII_MODEL_ICS_1890:
229221407Smarius		case MII_MODEL_ICS_1893:
230170525Syongari			PHY_WRITE(sc, MII_ICSPHY_ECR2, ECR2_100AUTOPWRDN);
231170525Syongari			break;
232221407Smarius		case MII_MODEL_ICS_1892:
233170525Syongari			PHY_WRITE(sc, MII_ICSPHY_ECR2,
234170525Syongari			    ECR2_10AUTOPWRDN|ECR2_100AUTOPWRDN);
235170525Syongari			break;
236170525Syongari		default:
237170525Syongari			/* 1889 have no ECR2 */
238170525Syongari			break;
239170525Syongari	}
240170525Syongari	/*
241170525Syongari	 * There is no description that the reset do auto-negotiation in the
242170525Syongari	 * data sheet.
243170525Syongari	 */
244170525Syongari	PHY_WRITE(sc, MII_BMCR, BMCR_S100|BMCR_STARTNEG|BMCR_FDX);
245170525Syongari}
246