2 * Copyright (c) 2006, Pyun YongHyeon <yongari@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * $FreeBSD: src/sys/dev/mii/ip1000phy.c,v 1.1 2006/07/25 00:16:09 yongari Exp $
28 * $DragonFly: src/sys/dev/netif/mii_layer/ip1000phy.c,v 1.3 2008/03/16 15:50:22 hasso Exp $
32 * Driver for the IC Plus IP1000A 10/100/1000 PHY.
35 #include <sys/param.h>
37 #include <sys/kernel.h>
38 #include <sys/module.h>
39 #include <sys/socket.h>
40 #include <sys/sysctl.h>
43 #include <net/if_arp.h>
44 #include <net/if_media.h>
46 #include <dev/netif/mii_layer/mii.h>
47 #include <dev/netif/mii_layer/miivar.h>
50 #include <dev/netif/mii_layer/ip1000phyreg.h>
52 #include "miibus_if.h"
54 #include <dev/netif/stge/if_stgereg.h>
55 #include <dev/netif/stge/if_stgevar.h>
57 static int ip1000phy_probe(device_t
);
58 static int ip1000phy_attach(device_t
);
59 static int ip1000phy_service(struct mii_softc
*, struct mii_data
*, int);
60 static void ip1000phy_status(struct mii_softc
*);
61 static void ip1000phy_reset(struct mii_softc
*);
62 static int ip1000phy_mii_phy_auto(struct mii_softc
*);
64 static device_method_t ip1000phy_methods
[] = {
65 /* device interface */
66 DEVMETHOD(device_probe
, ip1000phy_probe
),
67 DEVMETHOD(device_attach
, ip1000phy_attach
),
68 DEVMETHOD(device_detach
, ukphy_detach
),
69 DEVMETHOD(device_shutdown
, bus_generic_shutdown
),
73 static devclass_t ip1000phy_devclass
;
74 static driver_t ip1000phy_driver
= {
77 sizeof (struct mii_softc
)
80 DRIVER_MODULE(ip1000phy
, miibus
, ip1000phy_driver
, ip1000phy_devclass
, 0, 0);
82 static const struct mii_phydesc ip1000phys
[] = {
83 MII_PHYDESC(ICPLUS
, IP1000A
),
88 ip1000phy_probe(device_t dev
)
90 struct mii_attach_args
*ma
;
91 const struct mii_phydesc
*mpd
;
93 ma
= device_get_ivars(dev
);
94 mpd
= mii_phy_match(ma
, ip1000phys
);
96 device_set_desc(dev
, mpd
->mpd_name
);
104 ip1000phy_attach(device_t dev
)
106 struct mii_softc
*sc
;
107 struct mii_attach_args
*ma
;
108 struct mii_data
*mii
;
110 sc
= device_get_softc(dev
);
111 ma
= device_get_ivars(dev
);
112 mii_softc_init(sc
, ma
);
113 sc
->mii_dev
= device_get_parent(dev
);
114 mii
= device_get_softc(sc
->mii_dev
);
115 LIST_INSERT_HEAD(&mii
->mii_phys
, sc
, mii_list
);
117 sc
->mii_inst
= mii
->mii_instance
;
118 sc
->mii_service
= ip1000phy_service
;
121 sc
->mii_anegticks
= MII_ANEGTICKS_GIGE
;
122 sc
->mii_flags
|= MIIF_NOISOLATE
;
126 device_printf(dev
, " ");
128 #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
130 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_NONE
, 0, sc
->mii_inst
),
133 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_10_T
, 0, sc
->mii_inst
),
135 kprintf("10baseT, ");
136 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_10_T
, IFM_FDX
, sc
->mii_inst
),
137 IP1000PHY_BMCR_10
| IP1000PHY_BMCR_FDX
);
138 kprintf("10baseT-FDX, ");
139 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_100_TX
, 0, sc
->mii_inst
),
141 kprintf("100baseTX, ");
142 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_100_TX
, IFM_FDX
, sc
->mii_inst
),
143 IP1000PHY_BMCR_100
| IP1000PHY_BMCR_FDX
);
144 kprintf("100baseTX-FDX, ");
145 /* 1000baseT half-duplex, really supported? */
146 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_1000_T
, 0, sc
->mii_inst
),
147 IP1000PHY_BMCR_1000
);
148 kprintf("1000baseT, ");
149 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_1000_T
, IFM_FDX
, sc
->mii_inst
),
150 IP1000PHY_BMCR_1000
| IP1000PHY_BMCR_FDX
);
151 kprintf("1000baseT-FDX, ");
152 ADD(IFM_MAKEWORD(IFM_ETHER
, IFM_AUTO
, 0, sc
->mii_inst
), 0);
158 MIIBUS_MEDIAINIT(sc
->mii_dev
);
163 ip1000phy_service(struct mii_softc
*sc
, struct mii_data
*mii
, int cmd
)
165 struct ifmedia_entry
*ife
= mii
->mii_media
.ifm_cur
;
166 uint32_t gig
, reg
, speed
;
171 * If we're not polling our PHY instance, just return.
173 if (IFM_INST(ife
->ifm_media
) != sc
->mii_inst
)
179 * If the media indicates a different PHY instance,
182 if (IFM_INST(ife
->ifm_media
) != sc
->mii_inst
) {
183 reg
= PHY_READ(sc
, IP1000PHY_MII_BMCR
);
184 PHY_WRITE(sc
, IP1000PHY_MII_BMCR
,
185 reg
| IP1000PHY_BMCR_ISO
);
190 * If the interface is not up, don't do anything.
192 if ((mii
->mii_ifp
->if_flags
& IFF_UP
) == 0)
196 switch (IFM_SUBTYPE(ife
->ifm_media
)) {
198 ip1000phy_mii_phy_auto(sc
);
204 * Manual 1000baseT setting doesn't seem to work.
206 speed
= IP1000PHY_BMCR_1000
;
210 speed
= IP1000PHY_BMCR_100
;
214 speed
= IP1000PHY_BMCR_10
;
221 if (((ife
->ifm_media
& IFM_GMASK
) & IFM_FDX
) != 0) {
222 speed
|= IP1000PHY_BMCR_FDX
;
223 gig
= IP1000PHY_1000CR_1000T_FDX
;
225 gig
= IP1000PHY_1000CR_1000T
;
228 PHY_WRITE(sc
, IP1000PHY_MII_1000CR
, 0);
229 PHY_WRITE(sc
, IP1000PHY_MII_BMCR
, speed
);
231 if (IFM_SUBTYPE(ife
->ifm_media
) != IFM_1000_T
)
234 PHY_WRITE(sc
, IP1000PHY_MII_1000CR
, gig
);
235 PHY_WRITE(sc
, IP1000PHY_MII_BMCR
, speed
);
238 * When settning the link manually, one side must
239 * be the master and the other the slave. However
240 * ifmedia doesn't give us a good way to specify
241 * this, so we fake it by using one of the LINK
242 * flags. If LINK0 is set, we program the PHY to
243 * be a master, otherwise it's a slave.
245 if ((mii
->mii_ifp
->if_flags
& IFF_LINK0
)) {
246 PHY_WRITE(sc
, IP1000PHY_MII_1000CR
, gig
|
247 IP1000PHY_1000CR_MASTER
|
248 IP1000PHY_1000CR_MMASTER
|
249 IP1000PHY_1000CR_MANUAL
);
251 PHY_WRITE(sc
, IP1000PHY_MII_1000CR
, gig
|
252 IP1000PHY_1000CR_MASTER
|
253 IP1000PHY_1000CR_MANUAL
);
261 * If we're not currently selected, just return.
263 if (IFM_INST(ife
->ifm_media
) != sc
->mii_inst
)
266 * Is the interface even up?
268 if ((mii
->mii_ifp
->if_flags
& IFF_UP
) == 0)
272 * Only used for autonegotiation.
274 if (IFM_SUBTYPE(ife
->ifm_media
) != IFM_AUTO
) {
282 reg
= PHY_READ(sc
, MII_BMSR
) | PHY_READ(sc
, MII_BMSR
);
283 if (reg
& BMSR_LINK
) {
288 /* Announce link loss right after it happens */
289 if (sc
->mii_ticks
++ == 0)
293 * Only retry autonegotiation every mii_anegticks seconds.
295 if (sc
->mii_ticks
<= sc
->mii_anegticks
)
299 ip1000phy_mii_phy_auto(sc
);
303 /* Update the media status. */
304 ip1000phy_status(sc
);
306 /* Callback if something changed. */
307 mii_phy_update(sc
, cmd
);
312 ip1000phy_status(struct mii_softc
*sc
)
314 struct mii_data
*mii
= sc
->mii_pdata
;
315 uint32_t bmsr
, bmcr
, stat
;
318 mii
->mii_media_status
= IFM_AVALID
;
319 mii
->mii_media_active
= IFM_ETHER
;
321 bmsr
= PHY_READ(sc
, IP1000PHY_MII_BMSR
) |
322 PHY_READ(sc
, IP1000PHY_MII_BMSR
);
323 if ((bmsr
& IP1000PHY_BMSR_LINK
) != 0)
324 mii
->mii_media_status
|= IFM_ACTIVE
;
326 bmcr
= PHY_READ(sc
, IP1000PHY_MII_BMCR
);
327 if ((bmcr
& IP1000PHY_BMCR_LOOP
) != 0)
328 mii
->mii_media_active
|= IFM_LOOP
;
330 if ((bmcr
& IP1000PHY_BMCR_AUTOEN
) != 0) {
331 if ((bmsr
& IP1000PHY_BMSR_ANEGCOMP
) == 0) {
332 /* Erg, still trying, I guess... */
333 mii
->mii_media_active
|= IFM_NONE
;
338 stat
= PHY_READ(sc
, STGE_PhyCtrl
);
339 switch (PC_LinkSpeed(stat
)) {
340 case PC_LinkSpeed_Down
:
341 mii
->mii_media_active
|= IFM_NONE
;
343 case PC_LinkSpeed_10
:
344 mii
->mii_media_active
|= IFM_10_T
;
346 case PC_LinkSpeed_100
:
347 mii
->mii_media_active
|= IFM_100_TX
;
349 case PC_LinkSpeed_1000
:
350 mii
->mii_media_active
|= IFM_1000_T
;
353 if ((stat
& PC_PhyDuplexStatus
) != 0)
354 mii
->mii_media_active
|= IFM_FDX
;
356 mii
->mii_media_active
|= IFM_HDX
;
358 ar
= PHY_READ(sc
, IP1000PHY_MII_ANAR
);
359 lpar
= PHY_READ(sc
, IP1000PHY_MII_ANLPAR
);
362 * FLAG0 : Rx flow-control
363 * FLAG1 : Tx flow-control
365 if ((ar
& IP1000PHY_ANAR_PAUSE
) && (lpar
& IP1000PHY_ANLPAR_PAUSE
))
366 mii
->mii_media_active
|= IFM_FLAG0
| IFM_FLAG1
;
367 else if (!(ar
& IP1000PHY_ANAR_PAUSE
) && (ar
& IP1000PHY_ANAR_APAUSE
) &&
368 (lpar
& IP1000PHY_ANLPAR_PAUSE
) && (lpar
& IP1000PHY_ANLPAR_APAUSE
))
369 mii
->mii_media_active
|= IFM_FLAG1
;
370 else if ((ar
& IP1000PHY_ANAR_PAUSE
) && (ar
& IP1000PHY_ANAR_APAUSE
) &&
371 !(lpar
& IP1000PHY_ANLPAR_PAUSE
) &&
372 (lpar
& IP1000PHY_ANLPAR_APAUSE
)) {
373 mii
->mii_media_active
|= IFM_FLAG0
;
377 * FLAG2 : local PHY resolved to MASTER
379 if ((mii
->mii_media_active
& IFM_1000_T
) != 0) {
380 stat
= PHY_READ(sc
, IP1000PHY_MII_1000SR
);
381 if ((stat
& IP1000PHY_1000SR_MASTER
) != 0)
382 mii
->mii_media_active
|= IFM_FLAG2
;
387 ip1000phy_mii_phy_auto(struct mii_softc
*mii
)
391 PHY_WRITE(mii
, IP1000PHY_MII_ANAR
,
392 IP1000PHY_ANAR_10T
| IP1000PHY_ANAR_10T_FDX
|
393 IP1000PHY_ANAR_100TX
| IP1000PHY_ANAR_100TX_FDX
|
394 IP1000PHY_ANAR_PAUSE
| IP1000PHY_ANAR_APAUSE
);
395 reg
= IP1000PHY_1000CR_1000T
| IP1000PHY_1000CR_1000T_FDX
;
396 reg
|= IP1000PHY_1000CR_MASTER
;
397 PHY_WRITE(mii
, IP1000PHY_MII_1000CR
, reg
);
398 PHY_WRITE(mii
, IP1000PHY_MII_BMCR
, (IP1000PHY_BMCR_FDX
|
399 IP1000PHY_BMCR_AUTOEN
| IP1000PHY_BMCR_STARTNEG
));
401 return (EJUSTRETURN
);
405 ip1000phy_load_dspcode(struct mii_softc
*sc
)
408 PHY_WRITE(sc
, 31, 0x0001);
409 PHY_WRITE(sc
, 27, 0x01e0);
410 PHY_WRITE(sc
, 31, 0x0002);
411 PHY_WRITE(sc
, 27, 0xeb8e);
412 PHY_WRITE(sc
, 31, 0x0000);
413 PHY_WRITE(sc
, 30, 0x005e);
414 PHY_WRITE(sc
, 9, 0x0700);
420 ip1000phy_reset(struct mii_softc
*sc
)
422 struct stge_softc
*stge_sc
;
423 struct mii_data
*mii
;
429 /* clear autoneg/full-duplex as we don't want it after reset */
430 reg
= PHY_READ(sc
, IP1000PHY_MII_BMCR
);
431 reg
&= ~(IP1000PHY_BMCR_AUTOEN
| IP1000PHY_BMCR_FDX
);
432 PHY_WRITE(sc
, MII_BMCR
, reg
);
436 * XXX There should be more general way to pass PHY specific
437 * data via mii interface.
439 parent
= device_get_parent(sc
->mii_dev
);
440 if (strncmp(device_get_name(parent
), "stge", 4) == 0) {
441 stge_sc
= device_get_softc(parent
);
442 if (stge_sc
->sc_rev
>= 0x40 && stge_sc
->sc_rev
<= 0x4e)
443 ip1000phy_load_dspcode(sc
);