1/*	$NetBSD: icsphy.c,v 1.41 2006/11/16 21:24:07 christos Exp $	*/
2
3/*-
4 * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 1997 Manuel Bouyer.  All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 *    notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 *    notice, this list of conditions and the following disclaimer in the
43 *    documentation and/or other materials provided with the distribution.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
46 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
48 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
49 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
51 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
52 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
53 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
54 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
55 */
56
57#include <sys/cdefs.h>
58__FBSDID("$FreeBSD: releng/11.0/sys/dev/mii/icsphy.c 257184 2013-10-26 18:40:17Z glebius $");
59
60/*
61 * driver for Integrated Circuit Systems' ICS1889-1893 ethernet 10/100 PHY
62 * datasheet from www.icst.com
63 */
64
65#include <sys/param.h>
66#include <sys/systm.h>
67#include <sys/kernel.h>
68#include <sys/module.h>
69#include <sys/socket.h>
70#include <sys/bus.h>
71
72#include <net/if.h>
73#include <net/if_media.h>
74
75#include <dev/mii/mii.h>
76#include <dev/mii/miivar.h>
77#include "miidevs.h"
78
79#include <dev/mii/icsphyreg.h>
80
81#include "miibus_if.h"
82
83static int	icsphy_probe(device_t dev);
84static int	icsphy_attach(device_t dev);
85
86static device_method_t icsphy_methods[] = {
87	/* device interface */
88	DEVMETHOD(device_probe,		icsphy_probe),
89	DEVMETHOD(device_attach,	icsphy_attach),
90	DEVMETHOD(device_detach,	mii_phy_detach),
91	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
92	DEVMETHOD_END
93};
94
95static devclass_t icsphy_devclass;
96
97static driver_t icsphy_driver = {
98	"icsphy",
99	icsphy_methods,
100	sizeof(struct mii_softc)
101};
102
103DRIVER_MODULE(icsphy, miibus, icsphy_driver, icsphy_devclass, 0, 0);
104
105static int	icsphy_service(struct mii_softc *, struct mii_data *, int);
106static void	icsphy_status(struct mii_softc *);
107static void	icsphy_reset(struct mii_softc *);
108
109static const struct mii_phydesc icsphys[] = {
110	MII_PHY_DESC(ICS, 1889),
111	MII_PHY_DESC(ICS, 1890),
112	MII_PHY_DESC(ICS, 1892),
113	MII_PHY_DESC(ICS, 1893),
114	MII_PHY_END
115};
116
117static const struct mii_phy_funcs icsphy_funcs = {
118	icsphy_service,
119	icsphy_status,
120	icsphy_reset
121};
122
123static int
124icsphy_probe(device_t dev)
125{
126
127	return (mii_phy_dev_probe(dev, icsphys, BUS_PROBE_DEFAULT));
128}
129
130static int
131icsphy_attach(device_t dev)
132{
133
134	mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE,
135	    &icsphy_funcs, 1);
136	return (0);
137}
138
139static int
140icsphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
141{
142
143	switch (cmd) {
144	case MII_POLLSTAT:
145		break;
146
147	case MII_MEDIACHG:
148		mii_phy_setmedia(sc);
149		break;
150
151	case MII_TICK:
152		if (mii_phy_tick(sc) == EJUSTRETURN)
153			return (0);
154		break;
155	}
156
157	/* Update the media status. */
158	PHY_STATUS(sc);
159
160	/* Callback if something changed. */
161	mii_phy_update(sc, cmd);
162	return (0);
163}
164
165static void
166icsphy_status(struct mii_softc *sc)
167{
168	struct mii_data *mii = sc->mii_pdata;
169	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
170	int bmcr, qpr;
171
172	mii->mii_media_status = IFM_AVALID;
173	mii->mii_media_active = IFM_ETHER;
174
175	/*
176	 * Don't get link from the BMSR.  It's available in the QPR,
177	 * and we have to read it twice to unlatch it anyhow.  This
178	 * gives us fewer register reads.
179	 */
180	qpr = PHY_READ(sc, MII_ICSPHY_QPR);		/* unlatch */
181	qpr = PHY_READ(sc, MII_ICSPHY_QPR);		/* real value */
182
183	if (qpr & QPR_LINK)
184		mii->mii_media_status |= IFM_ACTIVE;
185
186	bmcr = PHY_READ(sc, MII_BMCR);
187	if (bmcr & BMCR_ISO) {
188		mii->mii_media_active |= IFM_NONE;
189		mii->mii_media_status = 0;
190		return;
191	}
192
193	if (bmcr & BMCR_LOOP)
194		mii->mii_media_active |= IFM_LOOP;
195
196	if (bmcr & BMCR_AUTOEN) {
197		if ((qpr & QPR_ACOMP) == 0) {
198			/* Erg, still trying, I guess... */
199			mii->mii_media_active |= IFM_NONE;
200			return;
201		}
202		if (qpr & QPR_SPEED)
203			mii->mii_media_active |= IFM_100_TX;
204		else
205			mii->mii_media_active |= IFM_10_T;
206		if (qpr & QPR_FDX)
207			mii->mii_media_active |=
208			    IFM_FDX | mii_phy_flowstatus(sc);
209		else
210			mii->mii_media_active |= IFM_HDX;
211	} else
212		mii->mii_media_active = ife->ifm_media;
213}
214
215static void
216icsphy_reset(struct mii_softc *sc)
217{
218
219	mii_phy_reset(sc);
220	/* set powerdown feature */
221	switch (sc->mii_mpd_model) {
222		case MII_MODEL_ICS_1890:
223		case MII_MODEL_ICS_1893:
224			PHY_WRITE(sc, MII_ICSPHY_ECR2, ECR2_100AUTOPWRDN);
225			break;
226		case MII_MODEL_ICS_1892:
227			PHY_WRITE(sc, MII_ICSPHY_ECR2,
228			    ECR2_10AUTOPWRDN|ECR2_100AUTOPWRDN);
229			break;
230		default:
231			/* 1889 have no ECR2 */
232			break;
233	}
234	/*
235	 * There is no description that the reset do auto-negotiation in the
236	 * data sheet.
237	 */
238	PHY_WRITE(sc, MII_BMCR, BMCR_S100|BMCR_STARTNEG|BMCR_FDX);
239}
240