igphy.c revision 1.11 1 1.11 msaitoh /* $NetBSD: igphy.c,v 1.11 2007/02/23 03:03:10 msaitoh Exp $ */
2 1.1 fvdl
3 1.1 fvdl /*
4 1.1 fvdl * The Intel copyright applies to the analog register setup, and the
5 1.1 fvdl * (currently disabled) SmartSpeed workaround code.
6 1.1 fvdl */
7 1.1 fvdl
8 1.1 fvdl /*******************************************************************************
9 1.1 fvdl
10 1.1 fvdl Copyright (c) 2001-2003, Intel Corporation
11 1.1 fvdl All rights reserved.
12 1.1 fvdl
13 1.1 fvdl Redistribution and use in source and binary forms, with or without
14 1.1 fvdl modification, are permitted provided that the following conditions are met:
15 1.1 fvdl
16 1.1 fvdl 1. Redistributions of source code must retain the above copyright notice,
17 1.1 fvdl this list of conditions and the following disclaimer.
18 1.1 fvdl
19 1.1 fvdl 2. Redistributions in binary form must reproduce the above copyright
20 1.1 fvdl notice, this list of conditions and the following disclaimer in the
21 1.1 fvdl documentation and/or other materials provided with the distribution.
22 1.1 fvdl
23 1.1 fvdl 3. Neither the name of the Intel Corporation nor the names of its
24 1.1 fvdl contributors may be used to endorse or promote products derived from
25 1.1 fvdl this software without specific prior written permission.
26 1.1 fvdl
27 1.1 fvdl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28 1.1 fvdl AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 1.1 fvdl IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 1.1 fvdl ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31 1.1 fvdl LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 1.1 fvdl CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 1.1 fvdl SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 1.1 fvdl INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 1.1 fvdl CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 1.1 fvdl ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 1.1 fvdl POSSIBILITY OF SUCH DAMAGE.
38 1.1 fvdl
39 1.1 fvdl *******************************************************************************/
40 1.1 fvdl
41 1.1 fvdl
42 1.1 fvdl /*-
43 1.1 fvdl * Copyright (c) 1998, 1999, 2000, 2003 The NetBSD Foundation, Inc.
44 1.1 fvdl * All rights reserved.
45 1.1 fvdl *
46 1.1 fvdl * This code is derived from software contributed to The NetBSD Foundation
47 1.1 fvdl * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
48 1.1 fvdl * NASA Ames Research Center, and by Frank van der Linden.
49 1.1 fvdl *
50 1.1 fvdl * Redistribution and use in source and binary forms, with or without
51 1.1 fvdl * modification, are permitted provided that the following conditions
52 1.1 fvdl * are met:
53 1.1 fvdl * 1. Redistributions of source code must retain the above copyright
54 1.1 fvdl * notice, this list of conditions and the following disclaimer.
55 1.1 fvdl * 2. Redistributions in binary form must reproduce the above copyright
56 1.1 fvdl * notice, this list of conditions and the following disclaimer in the
57 1.1 fvdl * documentation and/or other materials provided with the distribution.
58 1.1 fvdl * 3. All advertising materials mentioning features or use of this software
59 1.1 fvdl * must display the following acknowledgement:
60 1.1 fvdl * This product includes software developed by the NetBSD
61 1.1 fvdl * Foundation, Inc. and its contributors.
62 1.1 fvdl * 4. Neither the name of The NetBSD Foundation nor the names of its
63 1.1 fvdl * contributors may be used to endorse or promote products derived
64 1.1 fvdl * from this software without specific prior written permission.
65 1.1 fvdl *
66 1.1 fvdl * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
67 1.1 fvdl * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
68 1.1 fvdl * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
69 1.1 fvdl * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
70 1.1 fvdl * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
71 1.1 fvdl * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
72 1.1 fvdl * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
73 1.1 fvdl * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
74 1.1 fvdl * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
75 1.1 fvdl * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
76 1.1 fvdl * POSSIBILITY OF SUCH DAMAGE.
77 1.1 fvdl */
78 1.1 fvdl
79 1.1 fvdl #include <sys/cdefs.h>
80 1.11 msaitoh __KERNEL_RCSID(0, "$NetBSD: igphy.c,v 1.11 2007/02/23 03:03:10 msaitoh Exp $");
81 1.1 fvdl
82 1.1 fvdl #include "opt_mii.h"
83 1.1 fvdl
84 1.1 fvdl #include <sys/param.h>
85 1.1 fvdl #include <sys/systm.h>
86 1.1 fvdl #include <sys/kernel.h>
87 1.1 fvdl #include <sys/device.h>
88 1.1 fvdl #include <sys/socket.h>
89 1.1 fvdl #include <sys/errno.h>
90 1.1 fvdl
91 1.1 fvdl #include <net/if.h>
92 1.1 fvdl #include <net/if_media.h>
93 1.1 fvdl
94 1.1 fvdl #include <dev/mii/mii.h>
95 1.1 fvdl #include <dev/mii/miivar.h>
96 1.1 fvdl #include <dev/mii/miidevs.h>
97 1.1 fvdl
98 1.1 fvdl #include <dev/mii/igphyreg.h>
99 1.1 fvdl
100 1.5 thorpej struct igphy_softc {
101 1.5 thorpej struct mii_softc sc_mii;
102 1.5 thorpej int sc_smartspeed;
103 1.5 thorpej };
104 1.5 thorpej
105 1.1 fvdl static void igphy_reset(struct mii_softc *);
106 1.1 fvdl static void igphy_load_dspcode(struct mii_softc *);
107 1.1 fvdl static void igphy_smartspeed_workaround(struct mii_softc *sc);
108 1.1 fvdl
109 1.4 thorpej static int igphymatch(struct device *, struct cfdata *, void *);
110 1.4 thorpej static void igphyattach(struct device *, struct device *, void *);
111 1.1 fvdl
112 1.5 thorpej CFATTACH_DECL(igphy, sizeof(struct igphy_softc),
113 1.1 fvdl igphymatch, igphyattach, mii_phy_detach, mii_phy_activate);
114 1.1 fvdl
115 1.4 thorpej static int igphy_service(struct mii_softc *, struct mii_data *, int);
116 1.4 thorpej static void igphy_status(struct mii_softc *);
117 1.1 fvdl
118 1.4 thorpej static const struct mii_phy_funcs igphy_funcs = {
119 1.1 fvdl igphy_service, igphy_status, igphy_reset,
120 1.1 fvdl };
121 1.1 fvdl
122 1.4 thorpej static const struct mii_phydesc igphys[] = {
123 1.1 fvdl { MII_OUI_yyINTEL, MII_MODEL_yyINTEL_IGP01E1000,
124 1.1 fvdl MII_STR_yyINTEL_IGP01E1000 },
125 1.1 fvdl
126 1.1 fvdl {0, 0,
127 1.1 fvdl NULL },
128 1.1 fvdl };
129 1.1 fvdl
130 1.4 thorpej static int
131 1.9 christos igphymatch(struct device *parent, struct cfdata *match,
132 1.8 christos void *aux)
133 1.1 fvdl {
134 1.1 fvdl struct mii_attach_args *ma = aux;
135 1.1 fvdl
136 1.1 fvdl if (mii_phy_match(ma, igphys) != NULL)
137 1.1 fvdl return 10;
138 1.1 fvdl
139 1.1 fvdl return 0;
140 1.1 fvdl }
141 1.1 fvdl
142 1.4 thorpej static void
143 1.9 christos igphyattach(struct device *parent, struct device *self, void *aux)
144 1.1 fvdl {
145 1.7 thorpej struct mii_softc *sc = device_private(self);
146 1.1 fvdl struct mii_attach_args *ma = aux;
147 1.1 fvdl struct mii_data *mii = ma->mii_data;
148 1.1 fvdl const struct mii_phydesc *mpd;
149 1.1 fvdl
150 1.1 fvdl mpd = mii_phy_match(ma, igphys);
151 1.1 fvdl aprint_naive(": Media interface\n");
152 1.1 fvdl aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
153 1.1 fvdl
154 1.1 fvdl sc->mii_inst = mii->mii_instance;
155 1.1 fvdl sc->mii_phy = ma->mii_phyno;
156 1.1 fvdl sc->mii_funcs = &igphy_funcs;
157 1.1 fvdl sc->mii_pdata = mii;
158 1.1 fvdl sc->mii_flags = ma->mii_flags;
159 1.10 christos sc->mii_anegticks = MII_ANEGTICKS_GIGE;
160 1.1 fvdl
161 1.1 fvdl PHY_RESET(sc);
162 1.1 fvdl
163 1.1 fvdl sc->mii_capabilities =
164 1.1 fvdl PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
165 1.1 fvdl if (sc->mii_capabilities & BMSR_EXTSTAT)
166 1.1 fvdl sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
167 1.1 fvdl aprint_normal("%s: ", sc->mii_dev.dv_xname);
168 1.1 fvdl if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 &&
169 1.1 fvdl (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0)
170 1.1 fvdl aprint_error("no media present");
171 1.1 fvdl else
172 1.1 fvdl mii_phy_add_media(sc);
173 1.1 fvdl aprint_normal("\n");
174 1.1 fvdl }
175 1.1 fvdl
176 1.1 fvdl static void
177 1.1 fvdl igphy_load_dspcode(struct mii_softc *sc)
178 1.1 fvdl {
179 1.1 fvdl static const struct {
180 1.1 fvdl int reg;
181 1.1 fvdl uint16_t val;
182 1.1 fvdl } dspcode[] = {
183 1.1 fvdl { 0x1f95, 0x0001 },
184 1.1 fvdl { 0x1f71, 0xbd21 },
185 1.1 fvdl { 0x1f79, 0x0018 },
186 1.1 fvdl { 0x1f30, 0x1600 },
187 1.1 fvdl { 0x1f31, 0x0014 },
188 1.1 fvdl { 0x1f32, 0x161c },
189 1.1 fvdl { 0x1f94, 0x0003 },
190 1.1 fvdl { 0x1f96, 0x003f },
191 1.1 fvdl { 0x2010, 0x0008 },
192 1.1 fvdl { 0, 0 },
193 1.1 fvdl };
194 1.1 fvdl int i;
195 1.1 fvdl
196 1.1 fvdl delay(10);
197 1.1 fvdl
198 1.1 fvdl PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT, 0x0000);
199 1.1 fvdl PHY_WRITE(sc, 0x0000, 0x0140);
200 1.1 fvdl
201 1.1 fvdl delay(5);
202 1.1 fvdl
203 1.1 fvdl for (i = 0; dspcode[i].reg != 0; i++)
204 1.1 fvdl IGPHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
205 1.1 fvdl
206 1.1 fvdl PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT,0x0000);
207 1.1 fvdl PHY_WRITE(sc, 0x0000, 0x3300);
208 1.1 fvdl }
209 1.1 fvdl
210 1.1 fvdl static void
211 1.1 fvdl igphy_reset(struct mii_softc *sc)
212 1.1 fvdl {
213 1.1 fvdl uint16_t fused, fine, coarse;
214 1.1 fvdl
215 1.1 fvdl mii_phy_reset(sc);
216 1.1 fvdl igphy_load_dspcode(sc);
217 1.1 fvdl
218 1.1 fvdl fused = IGPHY_READ(sc, MII_IGPHY_ANALOG_SPARE_FUSE_STATUS);
219 1.1 fvdl if ((fused & ANALOG_SPARE_FUSE_ENABLED) == 0) {
220 1.1 fvdl fused = IGPHY_READ(sc, MII_IGPHY_ANALOG_FUSE_STATUS);
221 1.1 fvdl
222 1.1 fvdl fine = fused & ANALOG_FUSE_FINE_MASK;
223 1.1 fvdl coarse = fused & ANALOG_FUSE_COARSE_MASK;
224 1.1 fvdl
225 1.1 fvdl if (coarse > ANALOG_FUSE_COARSE_THRESH) {
226 1.1 fvdl coarse -= ANALOG_FUSE_COARSE_10;
227 1.1 fvdl fine -= ANALOG_FUSE_FINE_1;
228 1.1 fvdl } else if (coarse == ANALOG_FUSE_COARSE_THRESH)
229 1.1 fvdl fine -= ANALOG_FUSE_FINE_10;
230 1.1 fvdl
231 1.1 fvdl fused = (fused & ANALOG_FUSE_POLY_MASK) |
232 1.1 fvdl (fine & ANALOG_FUSE_FINE_MASK) |
233 1.1 fvdl (coarse & ANALOG_FUSE_COARSE_MASK);
234 1.1 fvdl
235 1.1 fvdl IGPHY_WRITE(sc, MII_IGPHY_ANALOG_FUSE_CONTROL, fused);
236 1.1 fvdl IGPHY_WRITE(sc, MII_IGPHY_ANALOG_FUSE_BYPASS,
237 1.1 fvdl ANALOG_FUSE_ENABLE_SW_CONTROL);
238 1.1 fvdl }
239 1.1 fvdl PHY_WRITE(sc, MII_IGPHY_PAGE_SELECT,0x0000);
240 1.1 fvdl }
241 1.1 fvdl
242 1.1 fvdl
243 1.4 thorpej static int
244 1.1 fvdl igphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
245 1.1 fvdl {
246 1.1 fvdl struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
247 1.1 fvdl uint16_t reg;
248 1.1 fvdl
249 1.1 fvdl switch (cmd) {
250 1.1 fvdl case MII_POLLSTAT:
251 1.1 fvdl /*
252 1.1 fvdl * If we're not polling our PHY instance, just return.
253 1.1 fvdl */
254 1.1 fvdl if (IFM_INST(ife->ifm_media) != sc->mii_inst)
255 1.1 fvdl return (0);
256 1.1 fvdl break;
257 1.1 fvdl
258 1.1 fvdl case MII_MEDIACHG:
259 1.1 fvdl /*
260 1.1 fvdl * If the media indicates a different PHY instance,
261 1.1 fvdl * isolate ourselves.
262 1.1 fvdl */
263 1.1 fvdl if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
264 1.1 fvdl reg = PHY_READ(sc, MII_BMCR);
265 1.1 fvdl PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
266 1.1 fvdl return (0);
267 1.1 fvdl }
268 1.1 fvdl
269 1.1 fvdl /*
270 1.1 fvdl * If the interface is not up, don't do anything.
271 1.1 fvdl */
272 1.1 fvdl if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
273 1.1 fvdl break;
274 1.1 fvdl
275 1.11 msaitoh reg = PHY_READ(sc, MII_IGPHY_PORT_CTRL);
276 1.11 msaitoh if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
277 1.11 msaitoh reg |= PSCR_AUTO_MDIX;
278 1.11 msaitoh reg &= ~PSCR_FORCE_MDI_MDIX;
279 1.11 msaitoh PHY_WRITE(sc, MII_IGPHY_PORT_CTRL, reg);
280 1.11 msaitoh } else {
281 1.11 msaitoh reg &= ~(PSCR_AUTO_MDIX | PSCR_FORCE_MDI_MDIX);
282 1.11 msaitoh PHY_WRITE(sc, MII_IGPHY_PORT_CTRL, reg);
283 1.11 msaitoh }
284 1.11 msaitoh
285 1.1 fvdl mii_phy_setmedia(sc);
286 1.1 fvdl break;
287 1.1 fvdl
288 1.1 fvdl case MII_TICK:
289 1.1 fvdl /*
290 1.1 fvdl * If we're not currently selected, just return.
291 1.1 fvdl */
292 1.1 fvdl if (IFM_INST(ife->ifm_media) != sc->mii_inst)
293 1.1 fvdl return (0);
294 1.1 fvdl
295 1.1 fvdl igphy_smartspeed_workaround(sc);
296 1.1 fvdl
297 1.1 fvdl if (mii_phy_tick(sc) == EJUSTRETURN)
298 1.1 fvdl return (0);
299 1.1 fvdl break;
300 1.1 fvdl
301 1.1 fvdl case MII_DOWN:
302 1.1 fvdl mii_phy_down(sc);
303 1.1 fvdl return (0);
304 1.1 fvdl }
305 1.1 fvdl
306 1.1 fvdl /* Update the media status. */
307 1.1 fvdl mii_phy_status(sc);
308 1.1 fvdl
309 1.1 fvdl /* Callback if something changed. */
310 1.1 fvdl mii_phy_update(sc, cmd);
311 1.1 fvdl return (0);
312 1.1 fvdl }
313 1.1 fvdl
314 1.1 fvdl
315 1.4 thorpej static void
316 1.1 fvdl igphy_status(struct mii_softc *sc)
317 1.1 fvdl {
318 1.1 fvdl struct mii_data *mii = sc->mii_pdata;
319 1.1 fvdl struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
320 1.1 fvdl uint16_t bmcr, pssr, gtsr, bmsr;
321 1.1 fvdl
322 1.1 fvdl mii->mii_media_status = IFM_AVALID;
323 1.1 fvdl mii->mii_media_active = IFM_ETHER;
324 1.1 fvdl
325 1.1 fvdl pssr = PHY_READ(sc, MII_IGPHY_PORT_STATUS);
326 1.1 fvdl
327 1.1 fvdl if (pssr & PSSR_LINK_UP)
328 1.1 fvdl mii->mii_media_status |= IFM_ACTIVE;
329 1.1 fvdl
330 1.1 fvdl bmcr = PHY_READ(sc, MII_BMCR);
331 1.1 fvdl if (bmcr & BMCR_ISO) {
332 1.1 fvdl mii->mii_media_active |= IFM_NONE;
333 1.1 fvdl mii->mii_media_status = 0;
334 1.1 fvdl return;
335 1.1 fvdl }
336 1.1 fvdl
337 1.1 fvdl if (bmcr & BMCR_LOOP)
338 1.1 fvdl mii->mii_media_active |= IFM_LOOP;
339 1.1 fvdl
340 1.1 fvdl bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
341 1.1 fvdl
342 1.1 fvdl /*
343 1.1 fvdl * XXX can't check if the info is valid, no
344 1.1 fvdl * 'negotiation done' bit?
345 1.1 fvdl */
346 1.1 fvdl if (bmcr & BMCR_AUTOEN) {
347 1.1 fvdl if ((bmsr & BMSR_ACOMP) == 0) {
348 1.1 fvdl mii->mii_media_active |= IFM_NONE;
349 1.1 fvdl return;
350 1.1 fvdl }
351 1.1 fvdl switch (pssr & PSSR_SPEED_MASK) {
352 1.1 fvdl case PSSR_SPEED_1000MBPS:
353 1.1 fvdl mii->mii_media_active |= IFM_1000_T;
354 1.1 fvdl gtsr = PHY_READ(sc, MII_100T2SR);
355 1.1 fvdl if (gtsr & GTSR_MS_RES)
356 1.1 fvdl mii->mii_media_active |= IFM_ETH_MASTER;
357 1.1 fvdl break;
358 1.1 fvdl
359 1.1 fvdl case PSSR_SPEED_100MBPS:
360 1.1 fvdl mii->mii_media_active |= IFM_100_TX;
361 1.1 fvdl break;
362 1.1 fvdl
363 1.1 fvdl case PSSR_SPEED_10MBPS:
364 1.1 fvdl mii->mii_media_active |= IFM_10_T;
365 1.1 fvdl break;
366 1.1 fvdl
367 1.1 fvdl default:
368 1.1 fvdl mii->mii_media_active |= IFM_NONE;
369 1.1 fvdl mii->mii_media_status = 0;
370 1.1 fvdl return;
371 1.1 fvdl }
372 1.1 fvdl
373 1.1 fvdl if (pssr & PSSR_FULL_DUPLEX)
374 1.2 thorpej mii->mii_media_active |=
375 1.3 thorpej IFM_FDX | mii_phy_flowstatus(sc);
376 1.1 fvdl } else
377 1.1 fvdl mii->mii_media_active = ife->ifm_media;
378 1.1 fvdl }
379 1.1 fvdl
380 1.1 fvdl static void
381 1.1 fvdl igphy_smartspeed_workaround(struct mii_softc *sc)
382 1.1 fvdl {
383 1.5 thorpej struct igphy_softc *igsc = (struct igphy_softc *) sc;
384 1.5 thorpej uint16_t reg, gtsr, gtcr;
385 1.5 thorpej
386 1.5 thorpej if ((PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) == 0)
387 1.5 thorpej return;
388 1.5 thorpej
389 1.5 thorpej /* XXX Assume 1000TX-FDX is advertized if doing autonegotiation. */
390 1.1 fvdl
391 1.1 fvdl reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
392 1.5 thorpej if ((reg & BMSR_LINK) == 0) {
393 1.5 thorpej switch (igsc->sc_smartspeed) {
394 1.1 fvdl case 0:
395 1.1 fvdl gtsr = PHY_READ(sc, MII_100T2SR);
396 1.1 fvdl if (!(gtsr & GTSR_MAN_MS_FLT))
397 1.1 fvdl break;
398 1.1 fvdl gtsr = PHY_READ(sc, MII_100T2SR);
399 1.1 fvdl if (gtsr & GTSR_MAN_MS_FLT) {
400 1.1 fvdl gtcr = PHY_READ(sc, MII_100T2CR);
401 1.1 fvdl if (gtcr & GTCR_MAN_MS) {
402 1.1 fvdl gtcr &= ~GTCR_MAN_MS;
403 1.1 fvdl PHY_WRITE(sc, MII_100T2CR,
404 1.1 fvdl gtcr);
405 1.1 fvdl }
406 1.1 fvdl mii_phy_auto(sc, 0);
407 1.1 fvdl }
408 1.1 fvdl break;
409 1.1 fvdl case IGPHY_TICK_DOWNSHIFT:
410 1.1 fvdl gtcr = PHY_READ(sc, MII_100T2CR);
411 1.1 fvdl gtcr |= GTCR_MAN_MS;
412 1.1 fvdl PHY_WRITE(sc, MII_100T2CR, gtcr);
413 1.1 fvdl mii_phy_auto(sc, 0);
414 1.1 fvdl break;
415 1.1 fvdl default:
416 1.1 fvdl break;
417 1.1 fvdl }
418 1.5 thorpej if (igsc->sc_smartspeed++ == IGPHY_TICK_MAX)
419 1.5 thorpej igsc->sc_smartspeed = 0;
420 1.5 thorpej } else
421 1.5 thorpej igsc->sc_smartspeed = 0;
422 1.1 fvdl }
423