rgephy.c (51dd214c84efceda87c2ac10d34b7e3ee5b6c28f) rgephy.c (72200a8ab5fcb903f8d9908c63a8c3dde456e906)
1/*-
2 * Copyright (c) 2003
3 * Bill Paul <wpaul@windriver.com>. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 73 unchanged lines hidden (view full) ---

82};
83
84DRIVER_MODULE(rgephy, miibus, rgephy_driver, rgephy_devclass, 0, 0);
85
86static int rgephy_service(struct mii_softc *, struct mii_data *, int);
87static void rgephy_status(struct mii_softc *);
88static int rgephy_mii_phy_auto(struct mii_softc *, int);
89static void rgephy_reset(struct mii_softc *);
1/*-
2 * Copyright (c) 2003
3 * Bill Paul <wpaul@windriver.com>. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 73 unchanged lines hidden (view full) ---

82};
83
84DRIVER_MODULE(rgephy, miibus, rgephy_driver, rgephy_devclass, 0, 0);
85
86static int rgephy_service(struct mii_softc *, struct mii_data *, int);
87static void rgephy_status(struct mii_softc *);
88static int rgephy_mii_phy_auto(struct mii_softc *, int);
89static void rgephy_reset(struct mii_softc *);
90static int rgephy_linkup(struct mii_softc *);
90static void rgephy_loop(struct mii_softc *);
91static void rgephy_load_dspcode(struct mii_softc *);
92
93static const struct mii_phydesc rgephys[] = {
94 MII_PHY_DESC(REALTEK, RTL8169S),
95 MII_PHY_DESC(REALTEK, RTL8251),
96 MII_PHY_END
97};

--- 44 unchanged lines hidden (view full) ---

142 MIIBUS_MEDIAINIT(sc->mii_dev);
143 return (0);
144}
145
146static int
147rgephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
148{
149 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
91static void rgephy_loop(struct mii_softc *);
92static void rgephy_load_dspcode(struct mii_softc *);
93
94static const struct mii_phydesc rgephys[] = {
95 MII_PHY_DESC(REALTEK, RTL8169S),
96 MII_PHY_DESC(REALTEK, RTL8251),
97 MII_PHY_END
98};

--- 44 unchanged lines hidden (view full) ---

143 MIIBUS_MEDIAINIT(sc->mii_dev);
144 return (0);
145}
146
147static int
148rgephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
149{
150 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
150 int reg, speed, gig, anar;
151 int speed, gig, anar;
151
152 switch (cmd) {
153 case MII_POLLSTAT:
154 break;
155
156 case MII_MEDIACHG:
157 PHY_RESET(sc); /* XXX hardware bug work-around */
158

--- 73 unchanged lines hidden (view full) ---

232 sc->mii_ticks = 0;
233 break;
234 }
235
236 /*
237 * Check to see if we have link. If we do, we don't
238 * need to restart the autonegotiation process.
239 */
152
153 switch (cmd) {
154 case MII_POLLSTAT:
155 break;
156
157 case MII_MEDIACHG:
158 PHY_RESET(sc); /* XXX hardware bug work-around */
159

--- 73 unchanged lines hidden (view full) ---

233 sc->mii_ticks = 0;
234 break;
235 }
236
237 /*
238 * Check to see if we have link. If we do, we don't
239 * need to restart the autonegotiation process.
240 */
240 if ((sc->mii_flags & MIIF_PHYPRIV0) == 0 &&
241 sc->mii_mpd_rev >= 2) {
242 /* RTL8211B(L) */
243 reg = PHY_READ(sc, RGEPHY_MII_SSR);
244 if (reg & RGEPHY_SSR_LINK) {
245 sc->mii_ticks = 0;
246 break;
247 }
248 } else {
249 reg = PHY_READ(sc, RL_GMEDIASTAT);
250 if (reg & RL_GMEDIASTAT_LINK) {
251 sc->mii_ticks = 0;
252 break;
253 }
241 if (rgephy_linkup(sc) != 0) {
242 sc->mii_ticks = 0;
243 break;
254 }
255
256 /* Announce link loss right after it happens. */
257 if (sc->mii_ticks++ == 0)
258 break;
259
260 /* Only retry autonegotiation every mii_anegticks seconds. */
261 if (sc->mii_ticks <= sc->mii_anegticks)

--- 16 unchanged lines hidden (view full) ---

278 sc->mii_media_status != mii->mii_media_status ||
279 cmd == MII_MEDIACHG) {
280 rgephy_load_dspcode(sc);
281 }
282 mii_phy_update(sc, cmd);
283 return (0);
284}
285
244 }
245
246 /* Announce link loss right after it happens. */
247 if (sc->mii_ticks++ == 0)
248 break;
249
250 /* Only retry autonegotiation every mii_anegticks seconds. */
251 if (sc->mii_ticks <= sc->mii_anegticks)

--- 16 unchanged lines hidden (view full) ---

268 sc->mii_media_status != mii->mii_media_status ||
269 cmd == MII_MEDIACHG) {
270 rgephy_load_dspcode(sc);
271 }
272 mii_phy_update(sc, cmd);
273 return (0);
274}
275
276static int
277rgephy_linkup(struct mii_softc *sc)
278{
279 int linkup;
280 uint16_t reg;
281
282 linkup = 0;
283 if ((sc->mii_flags & MIIF_PHYPRIV0) == 0 &&
284 sc->mii_mpd_rev >= RGEPHY_8211B) {
285 if (sc->mii_mpd_rev == RGEPHY_8211F) {
286 reg = PHY_READ(sc, RGEPHY_F_MII_SSR);
287 if (reg & RGEPHY_F_SSR_LINK)
288 linkup++;
289 } else {
290 reg = PHY_READ(sc, RGEPHY_MII_SSR);
291 if (reg & RGEPHY_SSR_LINK)
292 linkup++;
293 }
294 } else {
295 reg = PHY_READ(sc, RL_GMEDIASTAT);
296 if (reg & RL_GMEDIASTAT_LINK)
297 linkup++;
298 }
299
300 return (linkup);
301}
302
286static void
287rgephy_status(struct mii_softc *sc)
288{
289 struct mii_data *mii = sc->mii_pdata;
290 int bmsr, bmcr;
291 uint16_t ssr;
292
293 mii->mii_media_status = IFM_AVALID;
294 mii->mii_media_active = IFM_ETHER;
295
303static void
304rgephy_status(struct mii_softc *sc)
305{
306 struct mii_data *mii = sc->mii_pdata;
307 int bmsr, bmcr;
308 uint16_t ssr;
309
310 mii->mii_media_status = IFM_AVALID;
311 mii->mii_media_active = IFM_ETHER;
312
296 if ((sc->mii_flags & MIIF_PHYPRIV0) == 0 && sc->mii_mpd_rev >= 2) {
297 ssr = PHY_READ(sc, RGEPHY_MII_SSR);
298 if (ssr & RGEPHY_SSR_LINK)
299 mii->mii_media_status |= IFM_ACTIVE;
300 } else {
301 bmsr = PHY_READ(sc, RL_GMEDIASTAT);
302 if (bmsr & RL_GMEDIASTAT_LINK)
303 mii->mii_media_status |= IFM_ACTIVE;
304 }
313 if (rgephy_linkup(sc) != 0)
314 mii->mii_media_status |= IFM_ACTIVE;
305
306 bmsr = PHY_READ(sc, RGEPHY_MII_BMSR);
315
316 bmsr = PHY_READ(sc, RGEPHY_MII_BMSR);
307
308 bmcr = PHY_READ(sc, RGEPHY_MII_BMCR);
309 if (bmcr & RGEPHY_BMCR_ISO) {
310 mii->mii_media_active |= IFM_NONE;
311 mii->mii_media_status = 0;
312 return;
313 }
314
315 if (bmcr & RGEPHY_BMCR_LOOP)
316 mii->mii_media_active |= IFM_LOOP;
317
318 if (bmcr & RGEPHY_BMCR_AUTOEN) {
319 if ((bmsr & RGEPHY_BMSR_ACOMP) == 0) {
320 /* Erg, still trying, I guess... */
321 mii->mii_media_active |= IFM_NONE;
322 return;
323 }
324 }
325
317 bmcr = PHY_READ(sc, RGEPHY_MII_BMCR);
318 if (bmcr & RGEPHY_BMCR_ISO) {
319 mii->mii_media_active |= IFM_NONE;
320 mii->mii_media_status = 0;
321 return;
322 }
323
324 if (bmcr & RGEPHY_BMCR_LOOP)
325 mii->mii_media_active |= IFM_LOOP;
326
327 if (bmcr & RGEPHY_BMCR_AUTOEN) {
328 if ((bmsr & RGEPHY_BMSR_ACOMP) == 0) {
329 /* Erg, still trying, I guess... */
330 mii->mii_media_active |= IFM_NONE;
331 return;
332 }
333 }
334
326 if ((sc->mii_flags & MIIF_PHYPRIV0) == 0 && sc->mii_mpd_rev >= 2) {
327 ssr = PHY_READ(sc, RGEPHY_MII_SSR);
328 switch (ssr & RGEPHY_SSR_SPD_MASK) {
329 case RGEPHY_SSR_S1000:
330 mii->mii_media_active |= IFM_1000_T;
331 break;
332 case RGEPHY_SSR_S100:
333 mii->mii_media_active |= IFM_100_TX;
334 break;
335 case RGEPHY_SSR_S10:
336 mii->mii_media_active |= IFM_10_T;
337 break;
338 default:
339 mii->mii_media_active |= IFM_NONE;
340 break;
335 if ((sc->mii_flags & MIIF_PHYPRIV0) == 0 &&
336 sc->mii_mpd_rev >= RGEPHY_8211B) {
337 if (sc->mii_mpd_rev == RGEPHY_8211F) {
338 ssr = PHY_READ(sc, RGEPHY_F_MII_SSR);
339 switch (ssr & RGEPHY_F_SSR_SPD_MASK) {
340 case RGEPHY_F_SSR_S1000:
341 mii->mii_media_active |= IFM_1000_T;
342 break;
343 case RGEPHY_F_SSR_S100:
344 mii->mii_media_active |= IFM_100_TX;
345 break;
346 case RGEPHY_F_SSR_S10:
347 mii->mii_media_active |= IFM_10_T;
348 break;
349 default:
350 mii->mii_media_active |= IFM_NONE;
351 break;
352 }
353 if (ssr & RGEPHY_F_SSR_FDX)
354 mii->mii_media_active |= IFM_FDX;
355 else
356 mii->mii_media_active |= IFM_HDX;
357
358 } else {
359 ssr = PHY_READ(sc, RGEPHY_MII_SSR);
360 switch (ssr & RGEPHY_SSR_SPD_MASK) {
361 case RGEPHY_SSR_S1000:
362 mii->mii_media_active |= IFM_1000_T;
363 break;
364 case RGEPHY_SSR_S100:
365 mii->mii_media_active |= IFM_100_TX;
366 break;
367 case RGEPHY_SSR_S10:
368 mii->mii_media_active |= IFM_10_T;
369 break;
370 default:
371 mii->mii_media_active |= IFM_NONE;
372 break;
373 }
374 if (ssr & RGEPHY_SSR_FDX)
375 mii->mii_media_active |= IFM_FDX;
376 else
377 mii->mii_media_active |= IFM_HDX;
341 }
378 }
342 if (ssr & RGEPHY_SSR_FDX)
343 mii->mii_media_active |= IFM_FDX;
344 else
345 mii->mii_media_active |= IFM_HDX;
346 } else {
347 bmsr = PHY_READ(sc, RL_GMEDIASTAT);
348 if (bmsr & RL_GMEDIASTAT_1000MBPS)
349 mii->mii_media_active |= IFM_1000_T;
350 else if (bmsr & RL_GMEDIASTAT_100MBPS)
351 mii->mii_media_active |= IFM_100_TX;
352 else if (bmsr & RL_GMEDIASTAT_10MBPS)
353 mii->mii_media_active |= IFM_10_T;

--- 37 unchanged lines hidden (view full) ---

391}
392
393static void
394rgephy_loop(struct mii_softc *sc)
395{
396 int i;
397
398 if (sc->mii_mpd_model != MII_MODEL_REALTEK_RTL8251 &&
379 } else {
380 bmsr = PHY_READ(sc, RL_GMEDIASTAT);
381 if (bmsr & RL_GMEDIASTAT_1000MBPS)
382 mii->mii_media_active |= IFM_1000_T;
383 else if (bmsr & RL_GMEDIASTAT_100MBPS)
384 mii->mii_media_active |= IFM_100_TX;
385 else if (bmsr & RL_GMEDIASTAT_10MBPS)
386 mii->mii_media_active |= IFM_10_T;

--- 37 unchanged lines hidden (view full) ---

424}
425
426static void
427rgephy_loop(struct mii_softc *sc)
428{
429 int i;
430
431 if (sc->mii_mpd_model != MII_MODEL_REALTEK_RTL8251 &&
399 sc->mii_mpd_rev < 2) {
432 sc->mii_mpd_rev < RGEPHY_8211B) {
400 PHY_WRITE(sc, RGEPHY_MII_BMCR, RGEPHY_BMCR_PDOWN);
401 DELAY(1000);
402 }
403
404 for (i = 0; i < 15000; i++) {
405 if (!(PHY_READ(sc, RGEPHY_MII_BMSR) & RGEPHY_BMSR_LINK)) {
406#if 0
407 device_printf(sc->mii_dev, "looped %d\n", i);

--- 17 unchanged lines hidden (view full) ---

425 * any fixups.
426 */
427static void
428rgephy_load_dspcode(struct mii_softc *sc)
429{
430 int val;
431
432 if (sc->mii_mpd_model == MII_MODEL_REALTEK_RTL8251 ||
433 PHY_WRITE(sc, RGEPHY_MII_BMCR, RGEPHY_BMCR_PDOWN);
434 DELAY(1000);
435 }
436
437 for (i = 0; i < 15000; i++) {
438 if (!(PHY_READ(sc, RGEPHY_MII_BMSR) & RGEPHY_BMSR_LINK)) {
439#if 0
440 device_printf(sc->mii_dev, "looped %d\n", i);

--- 17 unchanged lines hidden (view full) ---

458 * any fixups.
459 */
460static void
461rgephy_load_dspcode(struct mii_softc *sc)
462{
463 int val;
464
465 if (sc->mii_mpd_model == MII_MODEL_REALTEK_RTL8251 ||
433 sc->mii_mpd_rev >= 2)
466 sc->mii_mpd_rev >= RGEPHY_8211B)
434 return;
435
436 PHY_WRITE(sc, 31, 0x0001);
437 PHY_WRITE(sc, 21, 0x1000);
438 PHY_WRITE(sc, 24, 0x65C7);
439 PHY_CLRBIT(sc, 4, 0x0800);
440 val = PHY_READ(sc, 4) & 0xFFF;
441 PHY_WRITE(sc, 4, val);

--- 34 unchanged lines hidden (view full) ---

476 DELAY(40);
477}
478
479static void
480rgephy_reset(struct mii_softc *sc)
481{
482 uint16_t pcr, ssr;
483
467 return;
468
469 PHY_WRITE(sc, 31, 0x0001);
470 PHY_WRITE(sc, 21, 0x1000);
471 PHY_WRITE(sc, 24, 0x65C7);
472 PHY_CLRBIT(sc, 4, 0x0800);
473 val = PHY_READ(sc, 4) & 0xFFF;
474 PHY_WRITE(sc, 4, val);

--- 34 unchanged lines hidden (view full) ---

509 DELAY(40);
510}
511
512static void
513rgephy_reset(struct mii_softc *sc)
514{
515 uint16_t pcr, ssr;
516
484 if ((sc->mii_flags & MIIF_PHYPRIV0) == 0 && sc->mii_mpd_rev == 3) {
485 /* RTL8211C(L) */
486 ssr = PHY_READ(sc, RGEPHY_MII_SSR);
487 if ((ssr & RGEPHY_SSR_ALDPS) != 0) {
488 ssr &= ~RGEPHY_SSR_ALDPS;
489 PHY_WRITE(sc, RGEPHY_MII_SSR, ssr);
517 switch (sc->mii_mpd_rev) {
518 case RGEPHY_8211F:
519 pcr = PHY_READ(sc, RGEPHY_F_MII_PCR1);
520 if ((pcr & RGEPHY_F_PCR1_MDI_MM) != 0) {
521 pcr &= ~RGEPHY_F_PCR1_MDI_MM;
522 PHY_WRITE(sc, RGEPHY_F_MII_PCR1, pcr);
490 }
523 }
491 }
492
493 if (sc->mii_mpd_rev >= 2) {
494 pcr = PHY_READ(sc, RGEPHY_MII_PCR);
495 if ((pcr & RGEPHY_PCR_MDIX_AUTO) == 0) {
496 pcr &= ~RGEPHY_PCR_MDI_MASK;
497 pcr |= RGEPHY_PCR_MDIX_AUTO;
498 PHY_WRITE(sc, RGEPHY_MII_PCR, pcr);
524 break;
525 case RGEPHY_8211C:
526 if ((sc->mii_flags & MIIF_PHYPRIV0) == 0) {
527 /* RTL8211C(L) */
528 ssr = PHY_READ(sc, RGEPHY_MII_SSR);
529 if ((ssr & RGEPHY_SSR_ALDPS) != 0) {
530 ssr &= ~RGEPHY_SSR_ALDPS;
531 PHY_WRITE(sc, RGEPHY_MII_SSR, ssr);
532 }
499 }
533 }
534 break;
535 default:
536 if (sc->mii_mpd_rev >= RGEPHY_8211B) {
537 pcr = PHY_READ(sc, RGEPHY_MII_PCR);
538 if ((pcr & RGEPHY_PCR_MDIX_AUTO) == 0) {
539 pcr &= ~RGEPHY_PCR_MDI_MASK;
540 pcr |= RGEPHY_PCR_MDIX_AUTO;
541 PHY_WRITE(sc, RGEPHY_MII_PCR, pcr);
542 }
543 }
544 break;
500 }
501
502 mii_phy_reset(sc);
503 DELAY(1000);
504 rgephy_load_dspcode(sc);
505}
545 }
546
547 mii_phy_reset(sc);
548 DELAY(1000);
549 rgephy_load_dspcode(sc);
550}