2 * drivers/net/ibm_emac/ibm_emac_phy.c
4 * Driver for PowerPC 4xx on-chip ethernet controller, PHY support.
5 * Borrowed from sungem_phy.c, though I only kept the generic MII
8 * This file should be shared with other drivers or eventually
9 * merged as the "low level" part of miilib
11 * (c) 2003, Benjamin Herrenscmidt (benh@kernel.crashing.org)
12 * (c) 2004-2005, Eugene Surovegin <ebs@ebshome.net>
15 #include <linux/module.h>
16 #include <linux/kernel.h>
17 #include <linux/types.h>
18 #include <linux/netdevice.h>
19 #include <linux/mii.h>
20 #include <linux/ethtool.h>
21 #include <linux/delay.h>
25 #include "ibm_emac_phy.h"
27 static inline int phy_read(struct mii_phy
*phy
, int reg
)
29 return phy
->mdio_read(phy
->dev
, phy
->address
, reg
);
32 static inline void phy_write(struct mii_phy
*phy
, int reg
, int val
)
34 phy
->mdio_write(phy
->dev
, phy
->address
, reg
, val
);
37 int mii_reset_phy(struct mii_phy
*phy
)
42 val
= phy_read(phy
, MII_BMCR
);
45 phy_write(phy
, MII_BMCR
, val
);
50 val
= phy_read(phy
, MII_BMCR
);
51 if (val
>= 0 && (val
& BMCR_RESET
) == 0)
55 if ((val
& BMCR_ISOLATE
) && limit
> 0)
56 phy_write(phy
, MII_BMCR
, val
& ~BMCR_ISOLATE
);
61 static int genmii_setup_aneg(struct mii_phy
*phy
, u32 advertise
)
65 phy
->autoneg
= AUTONEG_ENABLE
;
66 phy
->speed
= SPEED_10
;
67 phy
->duplex
= DUPLEX_HALF
;
68 phy
->pause
= phy
->asym_pause
= 0;
69 phy
->advertising
= advertise
;
71 /* Setup standard advertise */
72 adv
= phy_read(phy
, MII_ADVERTISE
);
75 adv
&= ~(ADVERTISE_ALL
| ADVERTISE_100BASE4
| ADVERTISE_PAUSE_CAP
|
76 ADVERTISE_PAUSE_ASYM
);
77 if (advertise
& ADVERTISED_10baseT_Half
)
78 adv
|= ADVERTISE_10HALF
;
79 if (advertise
& ADVERTISED_10baseT_Full
)
80 adv
|= ADVERTISE_10FULL
;
81 if (advertise
& ADVERTISED_100baseT_Half
)
82 adv
|= ADVERTISE_100HALF
;
83 if (advertise
& ADVERTISED_100baseT_Full
)
84 adv
|= ADVERTISE_100FULL
;
85 if (advertise
& ADVERTISED_Pause
)
86 adv
|= ADVERTISE_PAUSE_CAP
;
87 if (advertise
& ADVERTISED_Asym_Pause
)
88 adv
|= ADVERTISE_PAUSE_ASYM
;
89 phy_write(phy
, MII_ADVERTISE
, adv
);
92 (SUPPORTED_1000baseT_Full
| SUPPORTED_1000baseT_Half
)) {
93 adv
= phy_read(phy
, MII_CTRL1000
);
96 adv
&= ~(ADVERTISE_1000FULL
| ADVERTISE_1000HALF
);
97 if (advertise
& ADVERTISED_1000baseT_Full
)
98 adv
|= ADVERTISE_1000FULL
;
99 if (advertise
& ADVERTISED_1000baseT_Half
)
100 adv
|= ADVERTISE_1000HALF
;
101 phy_write(phy
, MII_CTRL1000
, adv
);
104 /* Start/Restart aneg */
105 ctl
= phy_read(phy
, MII_BMCR
);
106 ctl
|= (BMCR_ANENABLE
| BMCR_ANRESTART
);
107 phy_write(phy
, MII_BMCR
, ctl
);
112 static int genmii_setup_forced(struct mii_phy
*phy
, int speed
, int fd
)
116 phy
->autoneg
= AUTONEG_DISABLE
;
119 phy
->pause
= phy
->asym_pause
= 0;
121 ctl
= phy_read(phy
, MII_BMCR
);
124 ctl
&= ~(BMCR_FULLDPLX
| BMCR_SPEED100
| BMCR_ANENABLE
);
126 /* First reset the PHY */
127 phy_write(phy
, MII_BMCR
, ctl
| BMCR_RESET
);
129 /* Select speed & duplex */
134 ctl
|= BMCR_SPEED100
;
137 ctl
|= BMCR_SPEED1000
;
142 if (fd
== DUPLEX_FULL
)
143 ctl
|= BMCR_FULLDPLX
;
144 phy_write(phy
, MII_BMCR
, ctl
);
149 static int genmii_poll_link(struct mii_phy
*phy
)
153 /* Clear latched value with dummy read */
154 phy_read(phy
, MII_BMSR
);
155 status
= phy_read(phy
, MII_BMSR
);
156 if (status
< 0 || (status
& BMSR_LSTATUS
) == 0)
158 if (phy
->autoneg
== AUTONEG_ENABLE
&& !(status
& BMSR_ANEGCOMPLETE
))
163 static int genmii_read_link(struct mii_phy
*phy
)
165 if (phy
->autoneg
== AUTONEG_ENABLE
) {
167 int lpa
= phy_read(phy
, MII_LPA
) & phy_read(phy
, MII_ADVERTISE
);
172 (SUPPORTED_1000baseT_Full
| SUPPORTED_1000baseT_Half
)) {
173 int adv
= phy_read(phy
, MII_CTRL1000
);
174 glpa
= phy_read(phy
, MII_STAT1000
);
176 if (glpa
< 0 || adv
< 0)
182 phy
->speed
= SPEED_10
;
183 phy
->duplex
= DUPLEX_HALF
;
184 phy
->pause
= phy
->asym_pause
= 0;
186 if (glpa
& (LPA_1000FULL
| LPA_1000HALF
)) {
187 phy
->speed
= SPEED_1000
;
188 if (glpa
& LPA_1000FULL
)
189 phy
->duplex
= DUPLEX_FULL
;
190 } else if (lpa
& (LPA_100FULL
| LPA_100HALF
)) {
191 phy
->speed
= SPEED_100
;
192 if (lpa
& LPA_100FULL
)
193 phy
->duplex
= DUPLEX_FULL
;
194 } else if (lpa
& LPA_10FULL
)
195 phy
->duplex
= DUPLEX_FULL
;
197 if (phy
->duplex
== DUPLEX_FULL
) {
198 phy
->pause
= lpa
& LPA_PAUSE_CAP
? 1 : 0;
199 phy
->asym_pause
= lpa
& LPA_PAUSE_ASYM
? 1 : 0;
202 int bmcr
= phy_read(phy
, MII_BMCR
);
206 if (bmcr
& BMCR_FULLDPLX
)
207 phy
->duplex
= DUPLEX_FULL
;
209 phy
->duplex
= DUPLEX_HALF
;
210 if (bmcr
& BMCR_SPEED1000
)
211 phy
->speed
= SPEED_1000
;
212 else if (bmcr
& BMCR_SPEED100
)
213 phy
->speed
= SPEED_100
;
215 phy
->speed
= SPEED_10
;
217 phy
->pause
= phy
->asym_pause
= 0;
222 /* Generic implementation for most 10/100/1000 PHYs */
223 static struct mii_phy_ops generic_phy_ops
= {
224 .setup_aneg
= genmii_setup_aneg
,
225 .setup_forced
= genmii_setup_forced
,
226 .poll_link
= genmii_poll_link
,
227 .read_link
= genmii_read_link
230 static struct mii_phy_def genmii_phy_def
= {
231 .phy_id
= 0x00000000,
232 .phy_id_mask
= 0x00000000,
233 .name
= "Generic MII",
234 .ops
= &generic_phy_ops
238 #define MII_CIS8201_10BTCSR 0x16
239 #define TENBTCSR_ECHO_DISABLE 0x2000
240 #define MII_CIS8201_EPCR 0x17
241 #define EPCR_MODE_MASK 0x3000
242 #define EPCR_GMII_MODE 0x0000
243 #define EPCR_RGMII_MODE 0x1000
244 #define EPCR_TBI_MODE 0x2000
245 #define EPCR_RTBI_MODE 0x3000
246 #define MII_CIS8201_ACSR 0x1c
247 #define ACSR_PIN_PRIO_SELECT 0x0004
249 static int cis8201_init(struct mii_phy
*phy
)
253 epcr
= phy_read(phy
, MII_CIS8201_EPCR
);
257 epcr
&= ~EPCR_MODE_MASK
;
261 epcr
|= EPCR_TBI_MODE
;
264 epcr
|= EPCR_RTBI_MODE
;
267 epcr
|= EPCR_GMII_MODE
;
271 epcr
|= EPCR_RGMII_MODE
;
274 phy_write(phy
, MII_CIS8201_EPCR
, epcr
);
276 /* MII regs override strap pins */
277 phy_write(phy
, MII_CIS8201_ACSR
,
278 phy_read(phy
, MII_CIS8201_ACSR
) | ACSR_PIN_PRIO_SELECT
);
280 /* Disable TX_EN -> CRS echo mode, otherwise 10/HDX doesn't work */
281 phy_write(phy
, MII_CIS8201_10BTCSR
,
282 phy_read(phy
, MII_CIS8201_10BTCSR
) | TENBTCSR_ECHO_DISABLE
);
287 static struct mii_phy_ops cis8201_phy_ops
= {
288 .init
= cis8201_init
,
289 .setup_aneg
= genmii_setup_aneg
,
290 .setup_forced
= genmii_setup_forced
,
291 .poll_link
= genmii_poll_link
,
292 .read_link
= genmii_read_link
295 static struct mii_phy_def cis8201_phy_def
= {
296 .phy_id
= 0x000fc410,
297 .phy_id_mask
= 0x000ffff0,
298 .name
= "CIS8201 Gigabit Ethernet",
299 .ops
= &cis8201_phy_ops
302 static struct mii_phy_def
*mii_phy_table
[] = {
308 int mii_phy_probe(struct mii_phy
*phy
, int address
)
310 struct mii_phy_def
*def
;
314 phy
->autoneg
= AUTONEG_DISABLE
;
315 phy
->advertising
= 0;
316 phy
->address
= address
;
317 phy
->speed
= SPEED_10
;
318 phy
->duplex
= DUPLEX_HALF
;
319 phy
->pause
= phy
->asym_pause
= 0;
321 /* Take PHY out of isolate mode and reset it. */
322 if (mii_reset_phy(phy
))
325 /* Read ID and find matching entry */
326 id
= (phy_read(phy
, MII_PHYSID1
) << 16) | phy_read(phy
, MII_PHYSID2
);
327 for (i
= 0; (def
= mii_phy_table
[i
]) != NULL
; i
++)
328 if ((id
& def
->phy_id_mask
) == def
->phy_id
)
330 /* Should never be NULL (we have a generic entry), but... */
336 /* Determine PHY features if needed */
337 phy
->features
= def
->features
;
338 if (!phy
->features
) {
339 u16 bmsr
= phy_read(phy
, MII_BMSR
);
340 if (bmsr
& BMSR_ANEGCAPABLE
)
341 phy
->features
|= SUPPORTED_Autoneg
;
342 if (bmsr
& BMSR_10HALF
)
343 phy
->features
|= SUPPORTED_10baseT_Half
;
344 if (bmsr
& BMSR_10FULL
)
345 phy
->features
|= SUPPORTED_10baseT_Full
;
346 if (bmsr
& BMSR_100HALF
)
347 phy
->features
|= SUPPORTED_100baseT_Half
;
348 if (bmsr
& BMSR_100FULL
)
349 phy
->features
|= SUPPORTED_100baseT_Full
;
350 if (bmsr
& BMSR_ESTATEN
) {
351 u16 esr
= phy_read(phy
, MII_ESTATUS
);
352 if (esr
& ESTATUS_1000_TFULL
)
353 phy
->features
|= SUPPORTED_1000baseT_Full
;
354 if (esr
& ESTATUS_1000_THALF
)
355 phy
->features
|= SUPPORTED_1000baseT_Half
;
357 phy
->features
|= SUPPORTED_MII
;
360 /* Setup default advertising */
361 phy
->advertising
= phy
->features
;
366 MODULE_LICENSE("GPL");