1 /* $OpenBSD: qsphy.c,v 1.13 2005/02/19 06:00:04 brad Exp $ */
2 /* NetBSD: qsphy.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/qsphy.c,v 1.1.2.2 2002/10/21 21:21:42 semenu Exp $
41 * $DragonFly: src/sys/dev/netif/mii_layer/qsphy.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 Quality Semiconductor's QS6612 ethernet 10/100 PHY
75 * datasheet from www.qualitysemi.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>
95 #include "miibus_if.h"
97 static int qsphy_probe (device_t
);
98 static int qsphy_attach (device_t
);
100 static device_method_t qsphy_methods
[] = {
101 /* device interface */
102 DEVMETHOD(device_probe
, qsphy_probe
),
103 DEVMETHOD(device_attach
, qsphy_attach
),
104 DEVMETHOD(device_detach
, ukphy_detach
),
105 DEVMETHOD(device_shutdown
, bus_generic_shutdown
),
109 static const struct mii_phydesc qsphys
[] = {
110 MII_PHYDESC(QUALSEMI
, QS6612
),
114 static devclass_t qsphy_devclass
;
116 static driver_t qsphy_driver
= {
119 sizeof(struct mii_softc
)
122 DRIVER_MODULE(qsphy
, miibus
, qsphy_driver
, qsphy_devclass
, 0, 0);
124 static int qsphy_service(struct mii_softc
*, struct mii_data
*, int);
125 static void qsphy_reset(struct mii_softc
*);
126 static void qsphy_status(struct mii_softc
*);
129 qsphy_probe(device_t dev
)
131 struct mii_attach_args
*ma
= device_get_ivars(dev
);
132 const struct mii_phydesc
*mpd
;
134 mpd
= mii_phy_match(ma
, qsphys
);
136 device_set_desc(dev
, mpd
->mpd_name
);
143 qsphy_attach(device_t dev
)
145 struct mii_softc
*sc
;
146 struct mii_attach_args
*ma
;
147 struct mii_data
*mii
;
149 sc
= device_get_softc(dev
);
150 ma
= device_get_ivars(dev
);
151 mii_softc_init(sc
, ma
);
152 sc
->mii_dev
= device_get_parent(dev
);
153 mii
= device_get_softc(sc
->mii_dev
);
154 LIST_INSERT_HEAD(&mii
->mii_phys
, sc
, mii_list
);
156 sc
->mii_inst
= mii
->mii_instance
;
157 sc
->mii_service
= qsphy_service
;
158 sc
->mii_reset
= qsphy_reset
;
160 sc
->mii_flags
|= MIIF_NOISOLATE
;
166 sc
->mii_capabilities
= PHY_READ(sc
, MII_BMSR
) & ma
->mii_capmask
;
167 device_printf(dev
, " ");
168 if (sc
->mii_capabilities
& BMSR_MEDIAMASK
)
169 mii_phy_add_media(sc
);
171 kprintf("no media present");
174 MIIBUS_MEDIAINIT(sc
->mii_dev
);
179 qsphy_service(struct mii_softc
*sc
, struct mii_data
*mii
, int cmd
)
181 struct ifmedia_entry
*ife
= mii
->mii_media
.ifm_cur
;
185 * If we're not selected, then do nothing, just isolate, if
188 if (IFM_INST(ife
->ifm_media
) != sc
->mii_inst
) {
189 if (cmd
== MII_MEDIACHG
) {
190 reg
= PHY_READ(sc
, MII_BMCR
);
191 PHY_WRITE(sc
, MII_BMCR
, reg
| BMCR_ISO
);
203 * If the interface is not up, don't do anything.
205 if ((mii
->mii_ifp
->if_flags
& IFF_UP
) == 0)
208 mii_phy_set_media(sc
);
213 * Is the interface even up?
215 if ((mii
->mii_ifp
->if_flags
& IFF_UP
) == 0)
219 * Only used for autonegotiation.
221 if (IFM_SUBTYPE(ife
->ifm_media
) != IFM_AUTO
)
225 * This PHY's autonegotiation doesn't need to be kicked.
230 /* Update the media status. */
233 /* Callback if something changed. */
234 mii_phy_update(sc
, cmd
);
239 qsphy_status(struct mii_softc
*sc
)
241 struct mii_data
*mii
= sc
->mii_pdata
;
242 int bmsr
, bmcr
, pctl
;
244 mii
->mii_media_status
= IFM_AVALID
;
245 mii
->mii_media_active
= IFM_ETHER
;
247 bmsr
= PHY_READ(sc
, MII_BMSR
) |
248 PHY_READ(sc
, MII_BMSR
);
249 if (bmsr
& BMSR_LINK
)
250 mii
->mii_media_status
|= IFM_ACTIVE
;
252 bmcr
= PHY_READ(sc
, MII_BMCR
);
253 if (bmcr
& BMCR_ISO
) {
254 mii
->mii_media_active
|= IFM_NONE
;
255 mii
->mii_media_status
= 0;
259 if (bmcr
& BMCR_LOOP
)
260 mii
->mii_media_active
|= IFM_LOOP
;
262 if (bmcr
& BMCR_AUTOEN
) {
263 if ((bmsr
& BMSR_ACOMP
) == 0) {
264 /* Erg, still trying, I guess... */
265 mii
->mii_media_active
|= IFM_NONE
;
269 pctl
= PHY_READ(sc
, MII_QSPHY_PCTL
);
270 switch (pctl
& PCTL_OPMASK
) {
272 mii
->mii_media_active
|= IFM_10_T
;
275 mii
->mii_media_active
|= IFM_10_T
|IFM_FDX
;
278 mii
->mii_media_active
|= IFM_100_TX
;
280 case PCTL_100_TX_FDX
:
281 mii
->mii_media_active
|= IFM_100_TX
|IFM_FDX
;
284 mii
->mii_media_active
|= IFM_100_T4
;
287 mii
->mii_media_active
|= IFM_NONE
;
290 /* Erg... this shouldn't happen. */
291 mii
->mii_media_active
|= IFM_NONE
;
295 mii
->mii_media_active
= mii
->mii_media
.ifm_cur
->ifm_media
;
300 qsphy_reset(struct mii_softc
*sc
)
303 PHY_WRITE(sc
, MII_QSPHY_IMASK
, 0);