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/config.h>
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/types.h>
19 #include <linux/netdevice.h>
20 #include <linux/mii.h>
21 #include <linux/ethtool.h>
22 #include <linux/delay.h>
26 #include "ibm_emac_phy.h"
28 static inline int phy_read(struct mii_phy
*phy
, int reg
)
30 return phy
->mdio_read(phy
->dev
, phy
->address
, reg
);
33 static inline void phy_write(struct mii_phy
*phy
, int reg
, int val
)
35 phy
->mdio_write(phy
->dev
, phy
->address
, reg
, val
);
38 int mii_reset_phy(struct mii_phy
*phy
)
43 val
= phy_read(phy
, MII_BMCR
);
46 phy_write(phy
, MII_BMCR
, val
);
51 val
= phy_read(phy
, MII_BMCR
);
52 if (val
>= 0 && (val
& BMCR_RESET
) == 0)
56 if ((val
& BMCR_ISOLATE
) && limit
> 0)
57 phy_write(phy
, MII_BMCR
, val
& ~BMCR_ISOLATE
);
62 static int genmii_setup_aneg(struct mii_phy
*phy
, u32 advertise
)
66 phy
->autoneg
= AUTONEG_ENABLE
;
67 phy
->speed
= SPEED_10
;
68 phy
->duplex
= DUPLEX_HALF
;
69 phy
->pause
= phy
->asym_pause
= 0;
70 phy
->advertising
= advertise
;
72 /* Setup standard advertise */
73 adv
= phy_read(phy
, MII_ADVERTISE
);
76 adv
&= ~(ADVERTISE_ALL
| ADVERTISE_100BASE4
| ADVERTISE_PAUSE_CAP
|
77 ADVERTISE_PAUSE_ASYM
);
78 if (advertise
& ADVERTISED_10baseT_Half
)
79 adv
|= ADVERTISE_10HALF
;
80 if (advertise
& ADVERTISED_10baseT_Full
)
81 adv
|= ADVERTISE_10FULL
;
82 if (advertise
& ADVERTISED_100baseT_Half
)
83 adv
|= ADVERTISE_100HALF
;
84 if (advertise
& ADVERTISED_100baseT_Full
)
85 adv
|= ADVERTISE_100FULL
;
86 if (advertise
& ADVERTISED_Pause
)
87 adv
|= ADVERTISE_PAUSE_CAP
;
88 if (advertise
& ADVERTISED_Asym_Pause
)
89 adv
|= ADVERTISE_PAUSE_ASYM
;
90 phy_write(phy
, MII_ADVERTISE
, adv
);
93 (SUPPORTED_1000baseT_Full
| SUPPORTED_1000baseT_Half
)) {
94 adv
= phy_read(phy
, MII_CTRL1000
);
97 adv
&= ~(ADVERTISE_1000FULL
| ADVERTISE_1000HALF
);
98 if (advertise
& ADVERTISED_1000baseT_Full
)
99 adv
|= ADVERTISE_1000FULL
;
100 if (advertise
& ADVERTISED_1000baseT_Half
)
101 adv
|= ADVERTISE_1000HALF
;
102 phy_write(phy
, MII_CTRL1000
, adv
);
105 /* Start/Restart aneg */
106 ctl
= phy_read(phy
, MII_BMCR
);
107 ctl
|= (BMCR_ANENABLE
| BMCR_ANRESTART
);
108 phy_write(phy
, MII_BMCR
, ctl
);
113 static int genmii_setup_forced(struct mii_phy
*phy
, int speed
, int fd
)
117 phy
->autoneg
= AUTONEG_DISABLE
;
120 phy
->pause
= phy
->asym_pause
= 0;
122 ctl
= phy_read(phy
, MII_BMCR
);
125 ctl
&= ~(BMCR_FULLDPLX
| BMCR_SPEED100
| BMCR_ANENABLE
);
127 /* First reset the PHY */
128 phy_write(phy
, MII_BMCR
, ctl
| BMCR_RESET
);
130 /* Select speed & duplex */
135 ctl
|= BMCR_SPEED100
;
138 ctl
|= BMCR_SPEED1000
;
143 if (fd
== DUPLEX_FULL
)
144 ctl
|= BMCR_FULLDPLX
;
145 phy_write(phy
, MII_BMCR
, ctl
);
150 static int genmii_poll_link(struct mii_phy
*phy
)
154 /* Clear latched value with dummy read */
155 phy_read(phy
, MII_BMSR
);
156 status
= phy_read(phy
, MII_BMSR
);
157 if (status
< 0 || (status
& BMSR_LSTATUS
) == 0)
159 if (phy
->autoneg
== AUTONEG_ENABLE
&& !(status
& BMSR_ANEGCOMPLETE
))
164 static int genmii_read_link(struct mii_phy
*phy
)
166 if (phy
->autoneg
== AUTONEG_ENABLE
) {
168 int lpa
= phy_read(phy
, MII_LPA
) & phy_read(phy
, MII_ADVERTISE
);
173 (SUPPORTED_1000baseT_Full
| SUPPORTED_1000baseT_Half
)) {
174 int adv
= phy_read(phy
, MII_CTRL1000
);
175 glpa
= phy_read(phy
, MII_STAT1000
);
177 if (glpa
< 0 || adv
< 0)
183 phy
->speed
= SPEED_10
;
184 phy
->duplex
= DUPLEX_HALF
;
185 phy
->pause
= phy
->asym_pause
= 0;
187 if (glpa
& (LPA_1000FULL
| LPA_1000HALF
)) {
188 phy
->speed
= SPEED_1000
;
189 if (glpa
& LPA_1000FULL
)
190 phy
->duplex
= DUPLEX_FULL
;
191 } else if (lpa
& (LPA_100FULL
| LPA_100HALF
)) {
192 phy
->speed
= SPEED_100
;
193 if (lpa
& LPA_100FULL
)
194 phy
->duplex
= DUPLEX_FULL
;
195 } else if (lpa
& LPA_10FULL
)
196 phy
->duplex
= DUPLEX_FULL
;
198 if (phy
->duplex
== DUPLEX_FULL
) {
199 phy
->pause
= lpa
& LPA_PAUSE_CAP
? 1 : 0;
200 phy
->asym_pause
= lpa
& LPA_PAUSE_ASYM
? 1 : 0;
203 int bmcr
= phy_read(phy
, MII_BMCR
);
207 if (bmcr
& BMCR_FULLDPLX
)
208 phy
->duplex
= DUPLEX_FULL
;
210 phy
->duplex
= DUPLEX_HALF
;
211 if (bmcr
& BMCR_SPEED1000
)
212 phy
->speed
= SPEED_1000
;
213 else if (bmcr
& BMCR_SPEED100
)
214 phy
->speed
= SPEED_100
;
216 phy
->speed
= SPEED_10
;
218 phy
->pause
= phy
->asym_pause
= 0;
223 /* Generic implementation for most 10/100/1000 PHYs */
224 static struct mii_phy_ops generic_phy_ops
= {
225 .setup_aneg
= genmii_setup_aneg
,
226 .setup_forced
= genmii_setup_forced
,
227 .poll_link
= genmii_poll_link
,
228 .read_link
= genmii_read_link
231 static struct mii_phy_def genmii_phy_def
= {
232 .phy_id
= 0x00000000,
233 .phy_id_mask
= 0x00000000,
234 .name
= "Generic MII",
235 .ops
= &generic_phy_ops
239 #define MII_CIS8201_10BTCSR 0x16
240 #define TENBTCSR_ECHO_DISABLE 0x2000
241 #define MII_CIS8201_EPCR 0x17
242 #define EPCR_MODE_MASK 0x3000
243 #define EPCR_GMII_MODE 0x0000
244 #define EPCR_RGMII_MODE 0x1000
245 #define EPCR_TBI_MODE 0x2000
246 #define EPCR_RTBI_MODE 0x3000
247 #define MII_CIS8201_ACSR 0x1c
248 #define ACSR_PIN_PRIO_SELECT 0x0004
250 static int cis8201_init(struct mii_phy
*phy
)
254 epcr
= phy_read(phy
, MII_CIS8201_EPCR
);
258 epcr
&= ~EPCR_MODE_MASK
;
262 epcr
|= EPCR_TBI_MODE
;
265 epcr
|= EPCR_RTBI_MODE
;
268 epcr
|= EPCR_GMII_MODE
;
272 epcr
|= EPCR_RGMII_MODE
;
275 phy_write(phy
, MII_CIS8201_EPCR
, epcr
);
277 /* MII regs override strap pins */
278 phy_write(phy
, MII_CIS8201_ACSR
,
279 phy_read(phy
, MII_CIS8201_ACSR
) | ACSR_PIN_PRIO_SELECT
);
281 /* Disable TX_EN -> CRS echo mode, otherwise 10/HDX doesn't work */
282 phy_write(phy
, MII_CIS8201_10BTCSR
,
283 phy_read(phy
, MII_CIS8201_10BTCSR
) | TENBTCSR_ECHO_DISABLE
);
288 static struct mii_phy_ops cis8201_phy_ops
= {
289 .init
= cis8201_init
,
290 .setup_aneg
= genmii_setup_aneg
,
291 .setup_forced
= genmii_setup_forced
,
292 .poll_link
= genmii_poll_link
,
293 .read_link
= genmii_read_link
296 static struct mii_phy_def cis8201_phy_def
= {
297 .phy_id
= 0x000fc410,
298 .phy_id_mask
= 0x000ffff0,
299 .name
= "CIS8201 Gigabit Ethernet",
300 .ops
= &cis8201_phy_ops
303 static struct mii_phy_def
*mii_phy_table
[] = {
309 int mii_phy_probe(struct mii_phy
*phy
, int address
)
311 struct mii_phy_def
*def
;
315 phy
->autoneg
= AUTONEG_DISABLE
;
316 phy
->advertising
= 0;
317 phy
->address
= address
;
318 phy
->speed
= SPEED_10
;
319 phy
->duplex
= DUPLEX_HALF
;
320 phy
->pause
= phy
->asym_pause
= 0;
322 /* Take PHY out of isolate mode and reset it. */
323 if (mii_reset_phy(phy
))
326 /* Read ID and find matching entry */
327 id
= (phy_read(phy
, MII_PHYSID1
) << 16) | phy_read(phy
, MII_PHYSID2
);
328 for (i
= 0; (def
= mii_phy_table
[i
]) != NULL
; i
++)
329 if ((id
& def
->phy_id_mask
) == def
->phy_id
)
331 /* Should never be NULL (we have a generic entry), but... */
337 /* Determine PHY features if needed */
338 phy
->features
= def
->features
;
339 if (!phy
->features
) {
340 u16 bmsr
= phy_read(phy
, MII_BMSR
);
341 if (bmsr
& BMSR_ANEGCAPABLE
)
342 phy
->features
|= SUPPORTED_Autoneg
;
343 if (bmsr
& BMSR_10HALF
)
344 phy
->features
|= SUPPORTED_10baseT_Half
;
345 if (bmsr
& BMSR_10FULL
)
346 phy
->features
|= SUPPORTED_10baseT_Full
;
347 if (bmsr
& BMSR_100HALF
)
348 phy
->features
|= SUPPORTED_100baseT_Half
;
349 if (bmsr
& BMSR_100FULL
)
350 phy
->features
|= SUPPORTED_100baseT_Full
;
351 if (bmsr
& BMSR_ESTATEN
) {
352 u16 esr
= phy_read(phy
, MII_ESTATUS
);
353 if (esr
& ESTATUS_1000_TFULL
)
354 phy
->features
|= SUPPORTED_1000baseT_Full
;
355 if (esr
& ESTATUS_1000_THALF
)
356 phy
->features
|= SUPPORTED_1000baseT_Half
;
358 phy
->features
|= SUPPORTED_MII
;
361 /* Setup default advertising */
362 phy
->advertising
= phy
->features
;
367 MODULE_LICENSE("GPL");