xref: /netbsd-src/sys/dev/mii/rgephy.c (revision 2980e352a13e8f0b545a366830c411e7a542ada8)
1 /*	$NetBSD: rgephy.c,v 1.21 2008/05/04 17:06:10 xtraeme Exp $	*/
2 
3 /*
4  * Copyright (c) 2003
5  *	Bill Paul <wpaul@windriver.com>.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by Bill Paul.
18  * 4. Neither the name of the author nor the names of any co-contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32  * THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: rgephy.c,v 1.21 2008/05/04 17:06:10 xtraeme Exp $");
37 
38 
39 /*
40  * Driver for the RealTek 8169S/8110S internal 10/100/1000 PHY.
41  */
42 
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/device.h>
47 #include <sys/socket.h>
48 
49 
50 #include <net/if.h>
51 #include <net/if_media.h>
52 
53 #include <dev/mii/mii.h>
54 #include <dev/mii/miivar.h>
55 #include <dev/mii/miidevs.h>
56 
57 #include <dev/mii/rgephyreg.h>
58 
59 #include <dev/ic/rtl81x9reg.h>
60 
61 static int	rgephy_match(device_t, cfdata_t, void *);
62 static void	rgephy_attach(device_t, device_t, void *);
63 
64 struct rgephy_softc {
65 	struct mii_softc mii_sc;
66 	int mii_revision;
67 };
68 
69 CFATTACH_DECL_NEW(rgephy, sizeof(struct rgephy_softc),
70     rgephy_match, rgephy_attach, mii_phy_detach, mii_phy_activate);
71 
72 
73 static int	rgephy_service(struct mii_softc *, struct mii_data *, int);
74 static void	rgephy_status(struct mii_softc *);
75 static int	rgephy_mii_phy_auto(struct mii_softc *);
76 static void	rgephy_reset(struct mii_softc *);
77 static void	rgephy_loop(struct mii_softc *);
78 static void	rgephy_load_dspcode(struct mii_softc *);
79 
80 static const struct mii_phy_funcs rgephy_funcs = {
81 	rgephy_service, rgephy_status, rgephy_reset,
82 };
83 
84 static const struct mii_phydesc rgephys[] = {
85 	{ MII_OUI_xxREALTEK,		MII_MODEL_xxREALTEK_RTL8169S,
86 	  MII_STR_xxREALTEK_RTL8169S },
87 
88 	{ MII_OUI_REALTEK,		MII_MODEL_REALTEK_RTL8169S,
89 	  MII_STR_REALTEK_RTL8169S },
90 
91 	{ 0,				0,
92 	  NULL }
93 };
94 
95 static int
96 rgephy_match(device_t parent, cfdata_t match, void *aux)
97 {
98 	struct mii_attach_args *ma = aux;
99 
100 	if (mii_phy_match(ma, rgephys) != NULL)
101 		return 10;
102 
103 	return 0;
104 }
105 
106 static void
107 rgephy_attach(device_t parent, device_t self, void *aux)
108 {
109 	struct rgephy_softc *rsc = device_private(self);
110 	struct mii_softc *sc = &rsc->mii_sc;
111 	struct mii_attach_args *ma = aux;
112 	struct mii_data *mii = ma->mii_data;
113 	const struct mii_phydesc *mpd;
114 	int rev;
115 	const char *sep = "";
116 
117 	ma = aux;
118 	mii = ma->mii_data;
119 
120 	rev = MII_REV(ma->mii_id2);
121 	mpd = mii_phy_match(ma, rgephys);
122 	aprint_naive(": Media interface\n");
123 	aprint_normal(": %s, rev. %d\n", mpd->mpd_name, rev);
124 
125 	rsc->mii_revision = rev;
126 
127 	sc->mii_dev = self;
128 	sc->mii_inst = mii->mii_instance;
129 	sc->mii_phy = ma->mii_phyno;
130 	sc->mii_pdata = mii;
131 	sc->mii_flags = mii->mii_flags;
132 	sc->mii_anegticks = MII_ANEGTICKS;
133 
134 	sc->mii_funcs = &rgephy_funcs;
135 
136 #define	ADD(m, c)	ifmedia_add(&mii->mii_media, (m), (c), NULL)
137 #define	PRINT(n)	aprint_normal("%s%s", sep, (n)); sep = ", "
138 
139 #ifdef __FreeBSD__
140 	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
141 	    BMCR_LOOP|BMCR_S100);
142 #endif
143 
144 	sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
145 	sc->mii_capabilities &= ~BMSR_ANEG;
146 
147 	/*
148 	 * FreeBSD does not check EXSTAT, but instead adds gigabit
149 	 * media explicitly. Why?
150 	 */
151 	aprint_normal_dev(self, "");
152 	if (sc->mii_capabilities & BMSR_EXTSTAT) {
153 		sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
154 	}
155 	mii_phy_add_media(sc);
156 
157 	/* rtl8169S does not report auto-sense; add manually.  */
158 	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), MII_NMEDIA);
159 	sep =", ";
160 	PRINT("auto");
161 
162 #undef	ADD
163 #undef	PRINT
164 
165 	PHY_RESET(sc);
166 	aprint_normal("\n");
167 
168 	if (!pmf_device_register(self, NULL, mii_phy_resume))
169 		aprint_error_dev(self, "couldn't establish power handler\n");
170 }
171 
172 static int
173 rgephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
174 {
175 	struct rgephy_softc *rsc;
176 	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
177 	int reg, speed, gig, anar;
178 
179 	rsc = (struct rgephy_softc *)sc;
180 
181 	switch (cmd) {
182 	case MII_POLLSTAT:
183 		/*
184 		 * If we're not polling our PHY instance, just return.
185 		 */
186 		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
187 			return 0;
188 		break;
189 
190 	case MII_MEDIACHG:
191 		/*
192 		 * If the media indicates a different PHY instance,
193 		 * isolate ourselves.
194 		 */
195 		if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
196 			reg = PHY_READ(sc, MII_BMCR);
197 			PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
198 			return 0;
199 		}
200 
201 		/*
202 		 * If the interface is not up, don't do anything.
203 		 */
204 		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
205 			break;
206 
207 		PHY_RESET(sc);	/* XXX hardware bug work-around */
208 
209 		anar = PHY_READ(sc, RGEPHY_MII_ANAR);
210 		anar &= ~(RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX |
211 		    RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10);
212 
213 		switch (IFM_SUBTYPE(ife->ifm_media)) {
214 		case IFM_AUTO:
215 #ifdef foo
216 			/*
217 			 * If we're already in auto mode, just return.
218 			 */
219 			if (PHY_READ(sc, RGEPHY_MII_BMCR) & RGEPHY_BMCR_AUTOEN)
220 				return 0;
221 #endif
222 			(void)rgephy_mii_phy_auto(sc);
223 			break;
224 		case IFM_1000_T:
225 			speed = RGEPHY_S1000;
226 			goto setit;
227 		case IFM_100_TX:
228 			speed = RGEPHY_S100;
229 			anar |= RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX;
230 			goto setit;
231 		case IFM_10_T:
232 			speed = RGEPHY_S10;
233 			anar |= RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10;
234  setit:
235 			rgephy_loop(sc);
236 			if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
237 				speed |= RGEPHY_BMCR_FDX;
238 				gig = RGEPHY_1000CTL_AFD;
239 				anar &= ~(RGEPHY_ANAR_TX | RGEPHY_ANAR_10);
240 			} else {
241 				gig = RGEPHY_1000CTL_AHD;
242 				anar &=
243 				    ~(RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_10_FD);
244 			}
245 
246 			if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) {
247 				PHY_WRITE(sc, RGEPHY_MII_1000CTL, 0);
248 				PHY_WRITE(sc, RGEPHY_MII_ANAR, anar);
249 				PHY_WRITE(sc, RGEPHY_MII_BMCR, speed |
250 				    RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
251 				break;
252 			}
253 
254 			/*
255 			 * When setting the link manually, one side must
256 			 * be the master and the other the slave. However
257 			 * ifmedia doesn't give us a good way to specify
258 			 * this, so we fake it by using one of the LINK
259 			 * flags. If LINK0 is set, we program the PHY to
260 			 * be a master, otherwise it's a slave.
261 			 */
262 			if ((mii->mii_ifp->if_flags & IFF_LINK0)) {
263 				PHY_WRITE(sc, RGEPHY_MII_1000CTL,
264 				    gig|RGEPHY_1000CTL_MSE|RGEPHY_1000CTL_MSC);
265 			} else {
266 				PHY_WRITE(sc, RGEPHY_MII_1000CTL,
267 				    gig|RGEPHY_1000CTL_MSE);
268 			}
269 			PHY_WRITE(sc, RGEPHY_MII_BMCR, speed |
270 			    RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
271 			break;
272 		case IFM_NONE:
273 			PHY_WRITE(sc, MII_BMCR, BMCR_ISO|BMCR_PDOWN);
274 			break;
275 		case IFM_100_T4:
276 		default:
277 			return EINVAL;
278 		}
279 		break;
280 
281 	case MII_TICK:
282 		/*
283 		 * If we're not currently selected, just return.
284 		 */
285 		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
286 			return 0;
287 
288 		/*
289 		 * Is the interface even up?
290 		 */
291 		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
292 			return 0;
293 
294 		/*
295 		 * Only used for autonegotiation.
296 		 */
297 		if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
298 			break;
299 
300 		/*
301 		 * Check to see if we have link.  If we do, we don't
302 		 * need to restart the autonegotiation process.  Read
303 		 * the BMSR twice in case it's latched.
304 		 */
305 		if (rsc->mii_revision >= 2) {
306 			/* RTL8211B(L) */
307 			reg = PHY_READ(sc, RGEPHY_MII_SSR);
308 			if (reg & RGEPHY_SSR_LINK) {
309 				sc->mii_ticks = 0;
310 				break;
311 			}
312 		} else {
313 			reg = PHY_READ(sc, RTK_GMEDIASTAT);
314 			if ((reg & RTK_GMEDIASTAT_LINK) != 0) {
315 				sc->mii_ticks = 0;
316 				break;
317 			}
318 		}
319 
320 		/*
321 		 * Only retry autonegotiation every 5 seconds.
322 		 */
323 		if (++sc->mii_ticks <= MII_ANEGTICKS)
324 			break;
325 
326 		sc->mii_ticks = 0;
327 		rgephy_mii_phy_auto(sc);
328 		return 0;
329 	}
330 
331 	/* Update the media status. */
332 	rgephy_status(sc);
333 
334 	/*
335 	 * Callback if something changed. Note that we need to poke
336 	 * the DSP on the RealTek PHYs if the media changes.
337 	 *
338 	 */
339 	if (sc->mii_media_active != mii->mii_media_active ||
340 	    sc->mii_media_status != mii->mii_media_status ||
341 	    cmd == MII_MEDIACHG) {
342 	  	/* XXX only for v0/v1 phys. */
343 		if (rsc->mii_revision < 2)
344 		rgephy_load_dspcode(sc);
345 	}
346 	mii_phy_update(sc, cmd);
347 	return 0;
348 }
349 
350 static void
351 rgephy_status(struct mii_softc *sc)
352 {
353 	struct rgephy_softc *rsc;
354 	struct mii_data *mii = sc->mii_pdata;
355 	int gstat, bmsr, bmcr;
356 	uint16_t ssr;
357 
358 	mii->mii_media_status = IFM_AVALID;
359 	mii->mii_media_active = IFM_ETHER;
360 
361 	rsc = (struct rgephy_softc *)sc;
362 	if (rsc->mii_revision >= 2) {
363 		ssr = PHY_READ(sc, RGEPHY_MII_SSR);
364 		if (ssr & RGEPHY_SSR_LINK)
365 			mii->mii_media_status |= IFM_ACTIVE;
366 	} else {
367 		gstat = PHY_READ(sc, RTK_GMEDIASTAT);
368 		if ((gstat & RTK_GMEDIASTAT_LINK) != 0)
369 			mii->mii_media_status |= IFM_ACTIVE;
370 	}
371 
372 	bmsr = PHY_READ(sc, RGEPHY_MII_BMSR);
373 	bmsr = PHY_READ(sc, RGEPHY_MII_BMSR);
374 	bmcr = PHY_READ(sc, RGEPHY_MII_BMCR);
375 
376 	if ((bmcr & RGEPHY_BMCR_ISO) != 0) {
377 		mii->mii_media_active |= IFM_NONE;
378 		mii->mii_media_status = 0;
379 		return;
380 	}
381 
382 	if ((bmcr & RGEPHY_BMCR_LOOP) != 0)
383 		mii->mii_media_active |= IFM_LOOP;
384 
385 	if ((bmcr & RGEPHY_BMCR_AUTOEN) != 0) {
386 		if ((bmsr & RGEPHY_BMSR_ACOMP) == 0) {
387 			/* Erg, still trying, I guess... */
388 			mii->mii_media_active |= IFM_NONE;
389 			return;
390 		}
391 	}
392 
393 	if (rsc->mii_revision >= 2) {
394 		ssr = PHY_READ(sc, RGEPHY_MII_SSR);
395 		switch (ssr & RGEPHY_SSR_SPD_MASK) {
396 		case RGEPHY_SSR_S1000:
397 			mii->mii_media_active |= IFM_1000_T;
398 			break;
399 		case RGEPHY_SSR_S100:
400 			mii->mii_media_active |= IFM_100_TX;
401 			break;
402 		case RGEPHY_SSR_S10:
403 			mii->mii_media_active |= IFM_10_T;
404 			break;
405 		default:
406 			mii->mii_media_active |= IFM_NONE;
407 			break;
408 		}
409 		if (ssr & RGEPHY_SSR_FDX)
410 			mii->mii_media_active |= IFM_FDX;
411 		else
412 			mii->mii_media_active |= IFM_HDX;
413 	} else {
414 		gstat = PHY_READ(sc, RTK_GMEDIASTAT);
415 		if ((gstat & RTK_GMEDIASTAT_1000MBPS) != 0)
416 			mii->mii_media_active |= IFM_1000_T;
417 		else if ((gstat & RTK_GMEDIASTAT_100MBPS) != 0)
418 			mii->mii_media_active |= IFM_100_TX;
419 		else if ((gstat & RTK_GMEDIASTAT_10MBPS) != 0)
420 			mii->mii_media_active |= IFM_10_T;
421 		else
422 			mii->mii_media_active |= IFM_NONE;
423 		if ((gstat & RTK_GMEDIASTAT_FDX) != 0)
424 			mii->mii_media_active |= IFM_FDX;
425 	}
426 }
427 
428 
429 static int
430 rgephy_mii_phy_auto(struct mii_softc *mii)
431 {
432 
433 	rgephy_loop(mii);
434 	PHY_RESET(mii);
435 
436 	PHY_WRITE(mii, RGEPHY_MII_ANAR,
437 	    BMSR_MEDIA_TO_ANAR(mii->mii_capabilities) | ANAR_CSMA);
438 	DELAY(1000);
439 	PHY_WRITE(mii, RGEPHY_MII_1000CTL,
440 	    RGEPHY_1000CTL_AHD | RGEPHY_1000CTL_AFD);
441 	DELAY(1000);
442 	PHY_WRITE(mii, RGEPHY_MII_BMCR,
443 	    RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
444 	DELAY(100);
445 
446 	return EJUSTRETURN;
447 }
448 
449 static void
450 rgephy_loop(struct mii_softc *sc)
451 {
452 	struct rgephy_softc *rsc;
453 	uint32_t bmsr;
454 	int i;
455 
456 	rsc = (struct rgephy_softc *)sc;
457 	if (rsc->mii_revision < 2) {
458 		PHY_WRITE(sc, RGEPHY_MII_BMCR, RGEPHY_BMCR_PDOWN);
459 		DELAY(1000);
460 	}
461 
462 	for (i = 0; i < 15000; i++) {
463 		bmsr = PHY_READ(sc, RGEPHY_MII_BMSR);
464 		if ((bmsr & RGEPHY_BMSR_LINK) == 0) {
465 #if 0
466 			device_printf(sc->mii_dev, "looped %d\n", i);
467 #endif
468 			break;
469 		}
470 		DELAY(10);
471 	}
472 }
473 
474 #define PHY_SETBIT(x, y, z) \
475 	PHY_WRITE(x, y, (PHY_READ(x, y) | (z)))
476 #define PHY_CLRBIT(x, y, z) \
477 	PHY_WRITE(x, y, (PHY_READ(x, y) & ~(z)))
478 
479 /*
480  * Initialize RealTek PHY per the datasheet. The DSP in the PHYs of
481  * existing revisions of the 8169S/8110S chips need to be tuned in
482  * order to reliably negotiate a 1000Mbps link. This is only needed
483  * for rev 0 and rev 1 of the PHY. Later versions work without
484  * any fixups.
485  */
486 static void
487 rgephy_load_dspcode(struct mii_softc *sc)
488 {
489 	int val;
490 
491 #if 1
492 	PHY_WRITE(sc, 31, 0x0001);
493 	PHY_WRITE(sc, 21, 0x1000);
494 	PHY_WRITE(sc, 24, 0x65C7);
495 	PHY_CLRBIT(sc, 4, 0x0800);
496 	val = PHY_READ(sc, 4) & 0xFFF;
497 	PHY_WRITE(sc, 4, val);
498 	PHY_WRITE(sc, 3, 0x00A1);
499 	PHY_WRITE(sc, 2, 0x0008);
500 	PHY_WRITE(sc, 1, 0x1020);
501 	PHY_WRITE(sc, 0, 0x1000);
502 	PHY_SETBIT(sc, 4, 0x0800);
503 	PHY_CLRBIT(sc, 4, 0x0800);
504 	val = (PHY_READ(sc, 4) & 0xFFF) | 0x7000;
505 	PHY_WRITE(sc, 4, val);
506 	PHY_WRITE(sc, 3, 0xFF41);
507 	PHY_WRITE(sc, 2, 0xDE60);
508 	PHY_WRITE(sc, 1, 0x0140);
509 	PHY_WRITE(sc, 0, 0x0077);
510 	val = (PHY_READ(sc, 4) & 0xFFF) | 0xA000;
511 	PHY_WRITE(sc, 4, val);
512 	PHY_WRITE(sc, 3, 0xDF01);
513 	PHY_WRITE(sc, 2, 0xDF20);
514 	PHY_WRITE(sc, 1, 0xFF95);
515 	PHY_WRITE(sc, 0, 0xFA00);
516 	val = (PHY_READ(sc, 4) & 0xFFF) | 0xB000;
517 	PHY_WRITE(sc, 4, val);
518 	PHY_WRITE(sc, 3, 0xFF41);
519 	PHY_WRITE(sc, 2, 0xDE20);
520 	PHY_WRITE(sc, 1, 0x0140);
521 	PHY_WRITE(sc, 0, 0x00BB);
522 	val = (PHY_READ(sc, 4) & 0xFFF) | 0xF000;
523 	PHY_WRITE(sc, 4, val);
524 	PHY_WRITE(sc, 3, 0xDF01);
525 	PHY_WRITE(sc, 2, 0xDF20);
526 	PHY_WRITE(sc, 1, 0xFF95);
527 	PHY_WRITE(sc, 0, 0xBF00);
528 	PHY_SETBIT(sc, 4, 0x0800);
529 	PHY_CLRBIT(sc, 4, 0x0800);
530 	PHY_WRITE(sc, 31, 0x0000);
531 #else
532 	(void)val;
533 	PHY_WRITE(sc, 0x1f, 0x0001);
534 	PHY_WRITE(sc, 0x15, 0x1000);
535 	PHY_WRITE(sc, 0x18, 0x65c7);
536 	PHY_WRITE(sc, 0x04, 0x0000);
537 	PHY_WRITE(sc, 0x03, 0x00a1);
538 	PHY_WRITE(sc, 0x02, 0x0008);
539 	PHY_WRITE(sc, 0x01, 0x1020);
540 	PHY_WRITE(sc, 0x00, 0x1000);
541 	PHY_WRITE(sc, 0x04, 0x0800);
542 	PHY_WRITE(sc, 0x04, 0x0000);
543 	PHY_WRITE(sc, 0x04, 0x7000);
544 	PHY_WRITE(sc, 0x03, 0xff41);
545 	PHY_WRITE(sc, 0x02, 0xde60);
546 	PHY_WRITE(sc, 0x01, 0x0140);
547 	PHY_WRITE(sc, 0x00, 0x0077);
548 	PHY_WRITE(sc, 0x04, 0x7800);
549 	PHY_WRITE(sc, 0x04, 0x7000);
550 	PHY_WRITE(sc, 0x04, 0xa000);
551 	PHY_WRITE(sc, 0x03, 0xdf01);
552 	PHY_WRITE(sc, 0x02, 0xdf20);
553 	PHY_WRITE(sc, 0x01, 0xff95);
554 	PHY_WRITE(sc, 0x00, 0xfa00);
555 	PHY_WRITE(sc, 0x04, 0xa800);
556 	PHY_WRITE(sc, 0x04, 0xa000);
557 	PHY_WRITE(sc, 0x04, 0xb000);
558 	PHY_WRITE(sc, 0x0e, 0xff41);
559 	PHY_WRITE(sc, 0x02, 0xde20);
560 	PHY_WRITE(sc, 0x01, 0x0140);
561 	PHY_WRITE(sc, 0x00, 0x00bb);
562 	PHY_WRITE(sc, 0x04, 0xb800);
563 	PHY_WRITE(sc, 0x04, 0xb000);
564 	PHY_WRITE(sc, 0x04, 0xf000);
565 	PHY_WRITE(sc, 0x03, 0xdf01);
566 	PHY_WRITE(sc, 0x02, 0xdf20);
567 	PHY_WRITE(sc, 0x01, 0xff95);
568 	PHY_WRITE(sc, 0x00, 0xbf00);
569 	PHY_WRITE(sc, 0x04, 0xf800);
570 	PHY_WRITE(sc, 0x04, 0xf000);
571 	PHY_WRITE(sc, 0x04, 0x0000);
572 	PHY_WRITE(sc, 0x1f, 0x0000);
573 	PHY_WRITE(sc, 0x0b, 0x0000);
574 
575 #endif
576 
577 	DELAY(40);
578 }
579 
580 static void
581 rgephy_reset(struct mii_softc *sc)
582 {
583 	struct rgephy_softc *rsc;
584 
585 	mii_phy_reset(sc);
586 	DELAY(1000);
587 
588 	rsc = (struct rgephy_softc *)sc;
589 	if (rsc->mii_revision < 2)
590 		rgephy_load_dspcode(sc);
591 	else {
592 		PHY_WRITE(sc, 0x1F, 0x0001);
593 		PHY_WRITE(sc, 0x09, 0x273a);
594 		PHY_WRITE(sc, 0x0e, 0x7bfb);
595 		PHY_WRITE(sc, 0x1b, 0x841e);
596 
597 		PHY_WRITE(sc, 0x1F, 0x0002);
598 		PHY_WRITE(sc, 0x01, 0x90D0);
599 		PHY_WRITE(sc, 0x1F, 0x0000);
600 		PHY_WRITE(sc, 0x0e, 0x0000);
601 	}
602 
603 	/* Reset capabilities */
604 	/* Step1: write our capability */
605 	/* 10/100 capability */
606 	PHY_WRITE(sc, RGEPHY_MII_ANAR,
607 	    RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX |
608 	    RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10 | ANAR_CSMA);
609 	/* 1000 capability */
610 	PHY_WRITE(sc, RGEPHY_MII_1000CTL,
611 	    RGEPHY_1000CTL_AFD | RGEPHY_1000CTL_AHD);
612 
613 	/* Step2: Restart NWay */
614 	/* NWay enable and Restart NWay */
615 	PHY_WRITE(sc, RGEPHY_MII_BMCR,
616 	    RGEPHY_BMCR_RESET | RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
617 }
618