1 /* $OpenBSD: lxtphy.c,v 1.14 2005/02/19 06:00:04 brad Exp $ */
2 /* NetBSD: lxtphy.c,v 1.19 2000/02/02 23:34:57 thorpej Exp */
5 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10 * NASA Ames Research Center.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the NetBSD
23 * Foundation, Inc. and its contributors.
24 * 4. Neither the name of The NetBSD Foundation nor the names of its
25 * contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
40 * $FreeBSD: src/sys/dev/mii/lxtphy.c,v 1.1.2.1 2001/06/08 19:58:33 semenu Exp $
41 * $DragonFly: src/sys/dev/netif/mii_layer/lxtphy.c,v 1.10 2006/12/22 23:26:20 swildner Exp $
45 * Copyright (c) 1997 Manuel Bouyer. All rights reserved.
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions
50 * 1. Redistributions of source code must retain the above copyright
51 * notice, this list of conditions and the following disclaimer.
52 * 2. Redistributions in binary form must reproduce the above copyright
53 * notice, this list of conditions and the following disclaimer in the
54 * documentation and/or other materials provided with the distribution.
55 * 3. All advertising materials mentioning features or use of this software
56 * must display the following acknowledgement:
57 * This product includes software developed by Manuel Bouyer.
58 * 4. The name of the author may not be used to endorse or promote products
59 * derived from this software without specific prior written permission.
61 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
62 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
63 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
64 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
65 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
66 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
67 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
68 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
69 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
70 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
74 * driver for Level One's LXT-970/LXT-971 ethernet 10/100 PHY
75 * datasheet from www.level1.com
78 #include <sys/param.h>
79 #include <sys/systm.h>
80 #include <sys/kernel.h>
81 #include <sys/socket.h>
82 #include <sys/errno.h>
83 #include <sys/module.h>
87 #include <net/if_media.h>
93 #include "lxtphyreg.h"
95 #include "miibus_if.h"
97 static int lxtphy_probe(device_t
);
98 static int lxtphy_attach(device_t
);
100 static int lxtphy_service(struct mii_softc
*, struct mii_data
*, int);
101 static void lxtphy_status(struct mii_softc
*);
102 static void lxtphy_reset(struct mii_softc
*);
103 static void lxtphy_set_tp(struct mii_softc
*);
104 static void lxtphy_set_fx(struct mii_softc
*);
106 static device_method_t lxtphy_methods
[] = {
107 /* device interface */
108 DEVMETHOD(device_probe
, lxtphy_probe
),
109 DEVMETHOD(device_attach
, lxtphy_attach
),
110 DEVMETHOD(device_detach
, ukphy_detach
),
111 DEVMETHOD(device_shutdown
, bus_generic_shutdown
),
115 static const struct mii_phydesc lxtphys
[] = {
116 MII_PHYDESC_ARG(xxLEVEL1
, LXT970
, lxtphy_status
),
117 MII_PHYDESC_ARG(xxLEVEL1a
, LXT971
, ukphy_status
),
121 static devclass_t lxtphy_devclass
;
123 static driver_t lxtphy_driver
= {
126 sizeof(struct mii_softc
)
129 DRIVER_MODULE(lxtphy
, miibus
, lxtphy_driver
, lxtphy_devclass
, 0, 0);
132 lxtphy_probe(device_t dev
)
134 struct mii_attach_args
*ma
= device_get_ivars(dev
);
135 const struct mii_phydesc
*mpd
;
137 mpd
= mii_phy_match(ma
, lxtphys
);
139 struct mii_softc
*sc
= device_get_softc(dev
);
141 sc
->mii_status
= mpd
->mpd_priv
;
142 device_set_desc(dev
, mpd
->mpd_name
);
149 lxtphy_attach(device_t dev
)
151 struct mii_softc
*sc
;
152 struct mii_attach_args
*ma
;
153 struct mii_data
*mii
;
155 sc
= device_get_softc(dev
);
156 ma
= device_get_ivars(dev
);
157 mii_softc_init(sc
, ma
);
158 sc
->mii_dev
= device_get_parent(dev
);
159 mii
= device_get_softc(sc
->mii_dev
);
160 LIST_INSERT_HEAD(&mii
->mii_phys
, sc
, mii_list
);
162 sc
->mii_inst
= mii
->mii_instance
;
163 sc
->mii_service
= lxtphy_service
;
164 sc
->mii_reset
= lxtphy_reset
;
166 sc
->mii_flags
|= MIIF_NOISOLATE
;
172 #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
173 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_NONE
, 0, sc
->mii_inst
),
177 sc
->mii_capabilities
= PHY_READ(sc
, MII_BMSR
) & ma
->mii_capmask
;
179 device_printf(dev
, " ");
180 if (sc
->mii_capabilities
& BMSR_MEDIAMASK
)
181 mii_phy_add_media(sc
);
183 kprintf("no media present");
186 MIIBUS_MEDIAINIT(sc
->mii_dev
);
191 lxtphy_service(struct mii_softc
*sc
, struct mii_data
*mii
, int cmd
)
193 struct ifmedia_entry
*ife
= mii
->mii_media
.ifm_cur
;
199 * If we're not polling our PHY instance, just return.
201 if (IFM_INST(ife
->ifm_media
) != sc
->mii_inst
)
207 * If the media indicates a different PHY instance,
210 if (IFM_INST(ife
->ifm_media
) != sc
->mii_inst
) {
211 reg
= PHY_READ(sc
, MII_BMCR
);
212 PHY_WRITE(sc
, MII_BMCR
, reg
| BMCR_ISO
);
217 * If the interface is not up, don't do anything.
219 if ((mii
->mii_ifp
->if_flags
& IFF_UP
) == 0)
222 if (IFM_SUBTYPE(ife
->ifm_media
) == IFM_100_FX
)
227 mii_phy_set_media(sc
);
232 * If we're not currently selected, just return.
234 if (IFM_INST(ife
->ifm_media
) != sc
->mii_inst
)
237 if (mii_phy_tick(sc
) == EJUSTRETURN
)
242 /* Update the media status. */
245 /* Callback if something changed. */
246 mii_phy_update(sc
, cmd
);
251 lxtphy_status(struct mii_softc
*sc
)
253 struct mii_data
*mii
= sc
->mii_pdata
;
254 struct ifmedia_entry
*ife
= mii
->mii_media
.ifm_cur
;
257 mii
->mii_media_status
= IFM_AVALID
;
258 mii
->mii_media_active
= IFM_ETHER
;
261 * Get link status from the CSR; we need to read the CSR
262 * for media type anyhow, and the link status in the CSR
263 * doens't latch, so fewer register reads are required.
265 csr
= PHY_READ(sc
, MII_LXTPHY_CSR
);
267 mii
->mii_media_status
|= IFM_ACTIVE
;
269 bmcr
= PHY_READ(sc
, MII_BMCR
);
270 if (bmcr
& BMCR_ISO
) {
271 mii
->mii_media_active
|= IFM_NONE
;
272 mii
->mii_media_status
= 0;
276 if (bmcr
& BMCR_LOOP
)
277 mii
->mii_media_active
|= IFM_LOOP
;
279 if (bmcr
& BMCR_AUTOEN
) {
280 bmsr
= PHY_READ(sc
, MII_BMSR
) | PHY_READ(sc
, MII_BMSR
);
281 if ((bmsr
& BMSR_ACOMP
) == 0) {
282 /* Erg, still trying, I guess... */
283 mii
->mii_media_active
|= IFM_NONE
;
287 mii
->mii_media_active
|= IFM_100_TX
;
289 mii
->mii_media_active
|= IFM_10_T
;
290 if (csr
& CSR_DUPLEX
)
291 mii
->mii_media_active
|= IFM_FDX
;
293 mii
->mii_media_active
= ife
->ifm_media
;
297 lxtphy_set_tp(struct mii_softc
*sc
)
301 cfg
= PHY_READ(sc
, MII_LXTPHY_CONFIG
);
302 cfg
&= ~CONFIG_100BASEFX
;
303 PHY_WRITE(sc
, MII_LXTPHY_CONFIG
, cfg
);
307 lxtphy_set_fx(struct mii_softc
*sc
)
311 cfg
= PHY_READ(sc
, MII_LXTPHY_CONFIG
);
312 cfg
|= CONFIG_100BASEFX
;
313 PHY_WRITE(sc
, MII_LXTPHY_CONFIG
, cfg
);
317 lxtphy_reset(struct mii_softc
*sc
)
321 PHY_WRITE(sc
, MII_LXTPHY_IER
,
322 PHY_READ(sc
, MII_LXTPHY_IER
) & ~IER_INTEN
);