1 /* $FreeBSD: src/sys/dev/mii/e1000phy.c,v 1.18 2006/12/11 11:09:48 yongari Exp $ */
2 /* $DragonFly: src/sys/dev/netif/mii_layer/e1000phy.c,v 1.11 2008/03/16 15:50:22 hasso Exp $ */
3 /* $OpenBSD: eephy.c,v 1.26 2006/06/08 00:27:12 brad Exp $ */
5 * Principal Author: Parag Patel
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice unmodified, this list of conditions, and the following
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * Additonal Copyright (c) 2001 by Traakan Software under same licence.
32 * Secondary Author: Matthew Jacob
36 * driver for the Marvell 88E1000 series external 1000/100/10-BT PHY.
40 * Support added for the Marvell 88E1011 (Alaska) 1000/100/10baseT and
42 * Nathan Binkert <nate@openbsd.org>
43 * Jung-uk Kim <jkim@niksun.com>
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/kernel.h>
49 #include <sys/socket.h>
53 #include <net/if_media.h>
59 #include "e1000phyreg.h"
61 #include "miibus_if.h"
63 static int e1000phy_probe(device_t
);
64 static int e1000phy_attach(device_t
);
65 static int e1000phy_service(struct mii_softc
*, struct mii_data
*, int);
66 static void e1000phy_status(struct mii_softc
*);
67 static void e1000phy_mii_phy_auto(struct mii_softc
*);
68 static void e1000phy_reset(struct mii_softc
*);
70 static device_method_t e1000phy_methods
[] = {
71 /* device interface */
72 DEVMETHOD(device_probe
, e1000phy_probe
),
73 DEVMETHOD(device_attach
, e1000phy_attach
),
74 DEVMETHOD(device_detach
, ukphy_detach
),
75 DEVMETHOD(device_shutdown
, bus_generic_shutdown
),
79 static const struct mii_phydesc e1000phys
[] = {
80 MII_PHYDESC(xxMARVELL
, E1000_2
),
81 MII_PHYDESC(xxMARVELL
, E1000_3
),
82 MII_PHYDESC(xxMARVELL
, E1000_5
),
83 MII_PHYDESC(xxMARVELL
, E1111
),
84 MII_PHYDESC(MARVELL
, E1000
),
85 MII_PHYDESC(MARVELL
, E1011
),
86 MII_PHYDESC(MARVELL
, E1000_3
),
87 MII_PHYDESC(MARVELL
, E1000_4
),
88 MII_PHYDESC(MARVELL
, E1000_5
),
89 MII_PHYDESC(MARVELL
, E1000_6
),
90 MII_PHYDESC(MARVELL
, E3082
),
91 MII_PHYDESC(MARVELL
, E1112
),
92 MII_PHYDESC(MARVELL
, E1149
),
93 MII_PHYDESC(MARVELL
, E1111
),
94 MII_PHYDESC(MARVELL
, E1116
),
95 MII_PHYDESC(MARVELL
, E1118
),
99 static devclass_t e1000phy_devclass
;
101 static driver_t e1000phy_driver
= {
104 sizeof(struct mii_softc
)
106 DRIVER_MODULE(e1000phy
, miibus
, e1000phy_driver
, e1000phy_devclass
, 0, 0);
109 e1000phy_probe(device_t dev
)
111 struct mii_attach_args
*ma
= device_get_ivars(dev
);
112 const struct mii_phydesc
*mpd
;
114 mpd
= mii_phy_match(ma
, e1000phys
);
116 device_set_desc(dev
, mpd
->mpd_name
);
123 e1000phy_attach(device_t dev
)
125 struct mii_softc
*sc
;
126 struct mii_attach_args
*ma
;
127 struct mii_data
*mii
;
128 const char *sep
= "";
131 sc
= device_get_softc(dev
);
132 ma
= device_get_ivars(dev
);
133 mii_softc_init(sc
, ma
);
134 sc
->mii_dev
= device_get_parent(dev
);
135 mii
= device_get_softc(sc
->mii_dev
);
136 LIST_INSERT_HEAD(&mii
->mii_phys
, sc
, mii_list
);
138 sc
->mii_inst
= mii
->mii_instance
;
139 sc
->mii_service
= e1000phy_service
;
140 sc
->mii_reset
= e1000phy_reset
;
141 sc
->mii_anegticks
= MII_ANEGTICKS_GIGE
;
144 sc
->mii_flags
|= MIIF_NOISOLATE
;
146 switch (sc
->mii_model
) {
147 case MII_MODEL_MARVELL_E1011
:
148 case MII_MODEL_MARVELL_E1112
:
149 if (PHY_READ(sc
, E1000_ESSR
) & E1000_ESSR_FIBER_LINK
)
150 sc
->mii_flags
|= MIIF_HAVEFIBER
;
152 case MII_MODEL_MARVELL_E3082
:
153 /* 88E3082 10/100 Fast Ethernet PHY. */
154 sc
->mii_anegticks
= MII_ANEGTICKS
;
163 #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
164 #define PRINT(s) kprintf("%s%s", sep, s); sep = ", "
166 device_printf(dev
, "%s", "");
168 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_NONE
, 0, sc
->mii_inst
),
170 if ((sc
->mii_flags
& MIIF_HAVEFIBER
) == 0) {
173 * 1000T-simplex not supported; driver must ignore
174 * this entry, but it must be present in order to
175 * manually set full-duplex.
177 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_1000_T
, 0,
178 sc
->mii_inst
), E1000_CR_SPEED_1000
);
179 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_1000_T
, IFM_FDX
,
181 E1000_CR_SPEED_1000
| E1000_CR_FULL_DUPLEX
);
182 PRINT("1000baseT-FDX");
184 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_100_TX
, IFM_FDX
, sc
->mii_inst
),
185 E1000_CR_SPEED_100
| E1000_CR_FULL_DUPLEX
);
186 PRINT("100baseTX-FDX");
187 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_100_TX
, 0, sc
->mii_inst
),
190 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_10_T
, IFM_FDX
, sc
->mii_inst
),
191 E1000_CR_SPEED_10
| E1000_CR_FULL_DUPLEX
);
192 PRINT("10baseTX-FDX");
193 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_10_T
, 0, sc
->mii_inst
),
197 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_1000_SX
, IFM_FDX
, sc
->mii_inst
),
198 E1000_CR_SPEED_1000
| E1000_CR_FULL_DUPLEX
);
199 PRINT("1000baseSX-FDX");
202 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_AUTO
, 0, sc
->mii_inst
), 0);
208 MIIBUS_MEDIAINIT(sc
->mii_dev
);
213 e1000phy_reset(struct mii_softc
*sc
)
217 reg
= PHY_READ(sc
, E1000_SCR
);
218 if ((sc
->mii_flags
& MIIF_HAVEFIBER
) != 0) {
219 reg
&= ~E1000_SCR_AUTO_X_MODE
;
220 PHY_WRITE(sc
, E1000_SCR
, reg
);
221 if (sc
->mii_model
== MII_MODEL_MARVELL_E1112
) {
222 /* Select 1000BASE-X only mode. */
223 PHY_WRITE(sc
, E1000_EADR
, 2);
224 reg
= PHY_READ(sc
, E1000_SCR
);
225 reg
&= ~E1000_SCR_MODE_MASK
;
226 reg
|= E1000_SCR_MODE_1000BX
;
227 PHY_WRITE(sc
, E1000_SCR
, reg
);
228 PHY_WRITE(sc
, E1000_EADR
, 1);
231 switch (sc
->mii_model
) {
232 case MII_MODEL_MARVELL_E1111
:
233 case MII_MODEL_MARVELL_E1112
:
234 case MII_MODEL_MARVELL_E1116
:
235 case MII_MODEL_MARVELL_E1118
:
236 case MII_MODEL_MARVELL_E1149
:
237 /* Disable energy detect mode. */
238 reg
&= ~E1000_SCR_EN_DETECT_MASK
;
239 reg
|= E1000_SCR_AUTO_X_MODE
;
241 case MII_MODEL_MARVELL_E3082
:
242 reg
|= (E1000_SCR_AUTO_X_MODE
>> 1);
245 reg
&= ~E1000_SCR_AUTO_X_MODE
;
248 /* Enable CRS on TX. */
249 reg
|= E1000_SCR_ASSERT_CRS_ON_TX
;
250 /* Auto correction for reversed cable polarity. */
251 reg
&= ~E1000_SCR_POLARITY_REVERSAL
;
252 PHY_WRITE(sc
, E1000_SCR
, reg
);
255 switch (MII_MODEL(sc
->mii_model
)) {
256 case MII_MODEL_MARVELL_E3082
:
257 case MII_MODEL_MARVELL_E1112
:
258 case MII_MODEL_MARVELL_E1116
:
259 case MII_MODEL_MARVELL_E1118
:
260 case MII_MODEL_MARVELL_E1149
:
263 /* Force TX_CLK to 25MHz clock. */
264 reg
= PHY_READ(sc
, E1000_ESCR
);
265 reg
|= E1000_ESCR_TX_CLK_25
;
266 PHY_WRITE(sc
, E1000_ESCR
, reg
);
270 /* Reset the PHY so all changes take effect. */
271 reg
= PHY_READ(sc
, E1000_CR
);
272 reg
|= E1000_CR_RESET
;
273 PHY_WRITE(sc
, E1000_CR
, reg
);
277 e1000phy_service(struct mii_softc
*sc
, struct mii_data
*mii
, int cmd
)
279 struct ifmedia_entry
*ife
= mii
->mii_media
.ifm_cur
;
286 * If we're not polling our PHY instance, just return.
288 if (IFM_INST(ife
->ifm_media
) != sc
->mii_inst
)
294 * If the media indicates a different PHY instance,
297 if (IFM_INST(ife
->ifm_media
) != sc
->mii_inst
) {
298 reg
= PHY_READ(sc
, E1000_CR
);
299 PHY_WRITE(sc
, E1000_CR
, reg
| E1000_CR_ISOLATE
);
304 * If the interface is not up, don't do anything.
306 if ((mii
->mii_ifp
->if_flags
& IFF_UP
) == 0)
309 if (IFM_SUBTYPE(ife
->ifm_media
) == IFM_AUTO
) {
310 e1000phy_mii_phy_auto(sc
);
315 switch (IFM_SUBTYPE(ife
->ifm_media
)) {
317 if (sc
->mii_model
== MII_MODEL_MARVELL_E3082
)
319 speed
= E1000_CR_SPEED_1000
;
322 if (sc
->mii_model
== MII_MODEL_MARVELL_E3082
)
324 speed
= E1000_CR_SPEED_1000
;
327 speed
= E1000_CR_SPEED_100
;
330 speed
= E1000_CR_SPEED_10
;
333 reg
= PHY_READ(sc
, E1000_CR
);
334 PHY_WRITE(sc
, E1000_CR
,
335 reg
| E1000_CR_ISOLATE
| E1000_CR_POWER_DOWN
);
341 if (((ife
->ifm_media
& IFM_GMASK
) & IFM_FDX
) != 0) {
342 speed
|= E1000_CR_FULL_DUPLEX
;
343 gig
= E1000_1GCR_1000T_FD
;
345 gig
= E1000_1GCR_1000T
;
348 reg
= PHY_READ(sc
, E1000_CR
);
349 reg
&= ~E1000_CR_AUTO_NEG_ENABLE
;
350 PHY_WRITE(sc
, E1000_CR
, reg
| E1000_CR_RESET
);
353 * When setting the link manually, one side must
354 * be the master and the other the slave. However
355 * ifmedia doesn't give us a good way to specify
356 * this, so we fake it by using one of the LINK
357 * flags. If LINK0 is set, we program the PHY to
358 * be a master, otherwise it's a slave.
360 if (IFM_SUBTYPE(ife
->ifm_media
) == IFM_1000_T
||
361 IFM_SUBTYPE(ife
->ifm_media
) == IFM_1000_SX
) {
362 if (mii
->mii_ifp
->if_flags
& IFF_LINK0
) {
363 PHY_WRITE(sc
, E1000_1GCR
, gig
|
364 E1000_1GCR_MS_ENABLE
| E1000_1GCR_MS_VALUE
);
366 PHY_WRITE(sc
, E1000_1GCR
, gig
|
367 E1000_1GCR_MS_ENABLE
);
370 if (sc
->mii_model
!= MII_MODEL_MARVELL_E3082
)
371 PHY_WRITE(sc
, E1000_1GCR
, 0);
373 PHY_WRITE(sc
, E1000_AR
, E1000_AR_SELECTOR_FIELD
);
374 PHY_WRITE(sc
, E1000_CR
, speed
| E1000_CR_RESET
);
380 * If we're not currently selected, just return.
382 if (IFM_INST(ife
->ifm_media
) != sc
->mii_inst
)
386 * Is the interface even up?
388 if ((mii
->mii_ifp
->if_flags
& IFF_UP
) == 0)
392 * Only used for autonegotiation.
394 if (IFM_SUBTYPE(ife
->ifm_media
) != IFM_AUTO
)
398 * Check to see if we have link. If we do, we don't
399 * need to restart the autonegotiation process. Read
400 * the BMSR twice in case it's latched.
402 reg
= PHY_READ(sc
, MII_BMSR
) | PHY_READ(sc
, MII_BMSR
);
403 if (reg
& BMSR_LINK
) {
409 * Only retry autonegotiation every mii_anegticks seconds.
411 if (++sc
->mii_ticks
!= sc
->mii_anegticks
)
416 e1000phy_mii_phy_auto(sc
);
420 /* Update the media status. */
423 /* Callback if something changed. */
424 mii_phy_update(sc
, cmd
);
429 e1000phy_status(struct mii_softc
*sc
)
431 struct mii_data
*mii
= sc
->mii_pdata
;
432 int bmsr
, bmcr
, esr
, gsr
, ssr
, isr
, ar
, lpar
;
434 mii
->mii_media_status
= IFM_AVALID
;
435 mii
->mii_media_active
= IFM_ETHER
;
437 bmsr
= PHY_READ(sc
, E1000_SR
) | PHY_READ(sc
, E1000_SR
);
438 esr
= PHY_READ(sc
, E1000_ESR
);
439 bmcr
= PHY_READ(sc
, E1000_CR
);
440 ssr
= PHY_READ(sc
, E1000_SSR
);
441 isr
= PHY_READ(sc
, E1000_ISR
);
442 ar
= PHY_READ(sc
, E1000_AR
);
443 lpar
= PHY_READ(sc
, E1000_LPAR
);
445 if (bmsr
& E1000_SR_LINK_STATUS
)
446 mii
->mii_media_status
|= IFM_ACTIVE
;
448 if (bmcr
& E1000_CR_LOOPBACK
)
449 mii
->mii_media_active
|= IFM_LOOP
;
451 if (((bmcr
& E1000_CR_AUTO_NEG_ENABLE
) != 0 &&
452 (bmsr
& E1000_SR_AUTO_NEG_COMPLETE
) == 0) ||
453 (ssr
& E1000_SSR_LINK
) == 0 ||
454 (ssr
& E1000_SSR_SPD_DPLX_RESOLVED
) == 0) {
455 /* Erg, still trying, I guess... */
456 mii
->mii_media_active
|= IFM_NONE
;
460 if ((sc
->mii_flags
& MIIF_HAVEFIBER
) == 0) {
461 if (ssr
& E1000_SSR_1000MBS
)
462 mii
->mii_media_active
|= IFM_1000_T
;
463 else if (ssr
& E1000_SSR_100MBS
)
464 mii
->mii_media_active
|= IFM_100_TX
;
466 mii
->mii_media_active
|= IFM_10_T
;
468 if (ssr
& E1000_SSR_1000MBS
)
469 mii
->mii_media_active
|= IFM_1000_SX
;
472 if (ssr
& E1000_SSR_DUPLEX
)
473 mii
->mii_media_active
|= IFM_FDX
;
475 mii
->mii_media_active
|= IFM_HDX
;
477 if ((sc
->mii_flags
& MIIF_HAVEFIBER
) == 0) {
478 /* FLAG0==rx-flow-control FLAG1==tx-flow-control */
479 if ((ar
& E1000_AR_PAUSE
) && (lpar
& E1000_LPAR_PAUSE
)) {
480 mii
->mii_media_active
|= IFM_FLAG0
| IFM_FLAG1
;
481 } else if (!(ar
& E1000_AR_PAUSE
) && (ar
& E1000_AR_ASM_DIR
) &&
482 (lpar
& E1000_LPAR_PAUSE
) && (lpar
& E1000_LPAR_ASM_DIR
)) {
483 mii
->mii_media_active
|= IFM_FLAG1
;
484 } else if ((ar
& E1000_AR_PAUSE
) && (ar
& E1000_AR_ASM_DIR
) &&
485 !(lpar
& E1000_LPAR_PAUSE
) && (lpar
& E1000_LPAR_ASM_DIR
)) {
486 mii
->mii_media_active
|= IFM_FLAG0
;
490 /* FLAG2 : local PHY resolved to MASTER */
491 if (IFM_SUBTYPE(mii
->mii_media_active
) == IFM_1000_T
||
492 IFM_SUBTYPE(mii
->mii_media_active
) == IFM_1000_SX
) {
493 PHY_READ(sc
, E1000_1GSR
);
494 gsr
= PHY_READ(sc
, E1000_1GSR
);
495 if ((gsr
& E1000_1GSR_MS_CONFIG_RES
) != 0)
496 mii
->mii_media_active
|= IFM_FLAG2
;
501 e1000phy_mii_phy_auto(struct mii_softc
*sc
)
503 if ((sc
->mii_flags
& MIIF_HAVEFIBER
) == 0) {
504 PHY_WRITE(sc
, E1000_AR
, E1000_AR_10T
| E1000_AR_10T_FD
|
505 E1000_AR_100TX
| E1000_AR_100TX_FD
|
506 E1000_AR_PAUSE
| E1000_AR_ASM_DIR
);
508 PHY_WRITE(sc
, E1000_AR
, E1000_FA_1000X_FD
| E1000_FA_1000X
|
509 E1000_FA_SYM_PAUSE
| E1000_FA_ASYM_PAUSE
);
511 if (sc
->mii_model
!= MII_MODEL_MARVELL_E3082
) {
512 PHY_WRITE(sc
, E1000_1GCR
,
513 E1000_1GCR_1000T_FD
| E1000_1GCR_1000T
);
515 PHY_WRITE(sc
, E1000_CR
,
516 E1000_CR_AUTO_NEG_ENABLE
| E1000_CR_RESTART_AUTO_NEG
);