2 * drivers/net/ibm_newemac/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 * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
12 * <benh@kernel.crashing.org>
14 * Based on the arch/ppc version of the driver:
16 * (c) 2003, Benjamin Herrenscmidt (benh@kernel.crashing.org)
17 * (c) 2004-2005, Eugene Surovegin <ebs@ebshome.net>
20 #include <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/types.h>
23 #include <linux/netdevice.h>
24 #include <linux/mii.h>
25 #include <linux/ethtool.h>
26 #include <linux/delay.h>
31 static inline int phy_read(struct mii_phy
*phy
, int reg
)
33 return phy
->mdio_read(phy
->dev
, phy
->address
, reg
);
36 static inline void phy_write(struct mii_phy
*phy
, int reg
, int val
)
38 phy
->mdio_write(phy
->dev
, phy
->address
, reg
, val
);
41 int emac_mii_reset_phy(struct mii_phy
*phy
)
46 val
= phy_read(phy
, MII_BMCR
);
47 val
&= ~(BMCR_ISOLATE
| BMCR_ANENABLE
);
49 phy_write(phy
, MII_BMCR
, val
);
54 val
= phy_read(phy
, MII_BMCR
);
55 if (val
>= 0 && (val
& BMCR_RESET
) == 0)
59 if ((val
& BMCR_ISOLATE
) && limit
> 0)
60 phy_write(phy
, MII_BMCR
, val
& ~BMCR_ISOLATE
);
65 static int genmii_setup_aneg(struct mii_phy
*phy
, u32 advertise
)
69 phy
->autoneg
= AUTONEG_ENABLE
;
70 phy
->speed
= SPEED_10
;
71 phy
->duplex
= DUPLEX_HALF
;
72 phy
->pause
= phy
->asym_pause
= 0;
73 phy
->advertising
= advertise
;
75 ctl
= phy_read(phy
, MII_BMCR
);
78 ctl
&= ~(BMCR_FULLDPLX
| BMCR_SPEED100
| BMCR_SPEED1000
| BMCR_ANENABLE
);
80 /* First clear the PHY */
81 phy_write(phy
, MII_BMCR
, ctl
);
83 /* Setup standard advertise */
84 adv
= phy_read(phy
, MII_ADVERTISE
);
87 adv
&= ~(ADVERTISE_ALL
| ADVERTISE_100BASE4
| ADVERTISE_PAUSE_CAP
|
88 ADVERTISE_PAUSE_ASYM
);
89 if (advertise
& ADVERTISED_10baseT_Half
)
90 adv
|= ADVERTISE_10HALF
;
91 if (advertise
& ADVERTISED_10baseT_Full
)
92 adv
|= ADVERTISE_10FULL
;
93 if (advertise
& ADVERTISED_100baseT_Half
)
94 adv
|= ADVERTISE_100HALF
;
95 if (advertise
& ADVERTISED_100baseT_Full
)
96 adv
|= ADVERTISE_100FULL
;
97 if (advertise
& ADVERTISED_Pause
)
98 adv
|= ADVERTISE_PAUSE_CAP
;
99 if (advertise
& ADVERTISED_Asym_Pause
)
100 adv
|= ADVERTISE_PAUSE_ASYM
;
101 phy_write(phy
, MII_ADVERTISE
, adv
);
104 (SUPPORTED_1000baseT_Full
| SUPPORTED_1000baseT_Half
)) {
105 adv
= phy_read(phy
, MII_CTRL1000
);
108 adv
&= ~(ADVERTISE_1000FULL
| ADVERTISE_1000HALF
);
109 if (advertise
& ADVERTISED_1000baseT_Full
)
110 adv
|= ADVERTISE_1000FULL
;
111 if (advertise
& ADVERTISED_1000baseT_Half
)
112 adv
|= ADVERTISE_1000HALF
;
113 phy_write(phy
, MII_CTRL1000
, adv
);
116 /* Start/Restart aneg */
117 ctl
= phy_read(phy
, MII_BMCR
);
118 ctl
|= (BMCR_ANENABLE
| BMCR_ANRESTART
);
119 phy_write(phy
, MII_BMCR
, ctl
);
124 static int genmii_setup_forced(struct mii_phy
*phy
, int speed
, int fd
)
128 phy
->autoneg
= AUTONEG_DISABLE
;
131 phy
->pause
= phy
->asym_pause
= 0;
133 ctl
= phy_read(phy
, MII_BMCR
);
136 ctl
&= ~(BMCR_FULLDPLX
| BMCR_SPEED100
| BMCR_SPEED1000
| BMCR_ANENABLE
);
138 /* First clear the PHY */
139 phy_write(phy
, MII_BMCR
, ctl
| BMCR_RESET
);
141 /* Select speed & duplex */
146 ctl
|= BMCR_SPEED100
;
149 ctl
|= BMCR_SPEED1000
;
154 if (fd
== DUPLEX_FULL
)
155 ctl
|= BMCR_FULLDPLX
;
156 phy_write(phy
, MII_BMCR
, ctl
);
161 static int genmii_poll_link(struct mii_phy
*phy
)
165 /* Clear latched value with dummy read */
166 phy_read(phy
, MII_BMSR
);
167 status
= phy_read(phy
, MII_BMSR
);
168 if (status
< 0 || (status
& BMSR_LSTATUS
) == 0)
170 if (phy
->autoneg
== AUTONEG_ENABLE
&& !(status
& BMSR_ANEGCOMPLETE
))
175 static int genmii_read_link(struct mii_phy
*phy
)
177 if (phy
->autoneg
== AUTONEG_ENABLE
) {
179 int lpa
= phy_read(phy
, MII_LPA
) & phy_read(phy
, MII_ADVERTISE
);
184 (SUPPORTED_1000baseT_Full
| SUPPORTED_1000baseT_Half
)) {
185 int adv
= phy_read(phy
, MII_CTRL1000
);
186 glpa
= phy_read(phy
, MII_STAT1000
);
188 if (glpa
< 0 || adv
< 0)
194 phy
->speed
= SPEED_10
;
195 phy
->duplex
= DUPLEX_HALF
;
196 phy
->pause
= phy
->asym_pause
= 0;
198 if (glpa
& (LPA_1000FULL
| LPA_1000HALF
)) {
199 phy
->speed
= SPEED_1000
;
200 if (glpa
& LPA_1000FULL
)
201 phy
->duplex
= DUPLEX_FULL
;
202 } else if (lpa
& (LPA_100FULL
| LPA_100HALF
)) {
203 phy
->speed
= SPEED_100
;
204 if (lpa
& LPA_100FULL
)
205 phy
->duplex
= DUPLEX_FULL
;
206 } else if (lpa
& LPA_10FULL
)
207 phy
->duplex
= DUPLEX_FULL
;
209 if (phy
->duplex
== DUPLEX_FULL
) {
210 phy
->pause
= lpa
& LPA_PAUSE_CAP
? 1 : 0;
211 phy
->asym_pause
= lpa
& LPA_PAUSE_ASYM
? 1 : 0;
214 int bmcr
= phy_read(phy
, MII_BMCR
);
218 if (bmcr
& BMCR_FULLDPLX
)
219 phy
->duplex
= DUPLEX_FULL
;
221 phy
->duplex
= DUPLEX_HALF
;
222 if (bmcr
& BMCR_SPEED1000
)
223 phy
->speed
= SPEED_1000
;
224 else if (bmcr
& BMCR_SPEED100
)
225 phy
->speed
= SPEED_100
;
227 phy
->speed
= SPEED_10
;
229 phy
->pause
= phy
->asym_pause
= 0;
234 /* Generic implementation for most 10/100/1000 PHYs */
235 static struct mii_phy_ops generic_phy_ops
= {
236 .setup_aneg
= genmii_setup_aneg
,
237 .setup_forced
= genmii_setup_forced
,
238 .poll_link
= genmii_poll_link
,
239 .read_link
= genmii_read_link
242 static struct mii_phy_def genmii_phy_def
= {
243 .phy_id
= 0x00000000,
244 .phy_id_mask
= 0x00000000,
245 .name
= "Generic MII",
246 .ops
= &generic_phy_ops
250 #define MII_CIS8201_10BTCSR 0x16
251 #define TENBTCSR_ECHO_DISABLE 0x2000
252 #define MII_CIS8201_EPCR 0x17
253 #define EPCR_MODE_MASK 0x3000
254 #define EPCR_GMII_MODE 0x0000
255 #define EPCR_RGMII_MODE 0x1000
256 #define EPCR_TBI_MODE 0x2000
257 #define EPCR_RTBI_MODE 0x3000
258 #define MII_CIS8201_ACSR 0x1c
259 #define ACSR_PIN_PRIO_SELECT 0x0004
261 static int cis8201_init(struct mii_phy
*phy
)
265 epcr
= phy_read(phy
, MII_CIS8201_EPCR
);
269 epcr
&= ~EPCR_MODE_MASK
;
273 epcr
|= EPCR_TBI_MODE
;
276 epcr
|= EPCR_RTBI_MODE
;
279 epcr
|= EPCR_GMII_MODE
;
283 epcr
|= EPCR_RGMII_MODE
;
286 phy_write(phy
, MII_CIS8201_EPCR
, epcr
);
288 /* MII regs override strap pins */
289 phy_write(phy
, MII_CIS8201_ACSR
,
290 phy_read(phy
, MII_CIS8201_ACSR
) | ACSR_PIN_PRIO_SELECT
);
292 /* Disable TX_EN -> CRS echo mode, otherwise 10/HDX doesn't work */
293 phy_write(phy
, MII_CIS8201_10BTCSR
,
294 phy_read(phy
, MII_CIS8201_10BTCSR
) | TENBTCSR_ECHO_DISABLE
);
299 static struct mii_phy_ops cis8201_phy_ops
= {
300 .init
= cis8201_init
,
301 .setup_aneg
= genmii_setup_aneg
,
302 .setup_forced
= genmii_setup_forced
,
303 .poll_link
= genmii_poll_link
,
304 .read_link
= genmii_read_link
307 static struct mii_phy_def cis8201_phy_def
= {
308 .phy_id
= 0x000fc410,
309 .phy_id_mask
= 0x000ffff0,
310 .name
= "CIS8201 Gigabit Ethernet",
311 .ops
= &cis8201_phy_ops
314 static struct mii_phy_def bcm5248_phy_def
= {
316 .phy_id
= 0x0143bc00,
317 .phy_id_mask
= 0x0ffffff0,
318 .name
= "BCM5248 10/100 SMII Ethernet",
319 .ops
= &generic_phy_ops
322 static int m88e1111_init(struct mii_phy
*phy
)
324 pr_debug("%s: Marvell 88E1111 Ethernet\n", __FUNCTION__
);
325 phy_write(phy
, 0x14, 0x0ce3);
326 phy_write(phy
, 0x18, 0x4101);
327 phy_write(phy
, 0x09, 0x0e00);
328 phy_write(phy
, 0x04, 0x01e1);
329 phy_write(phy
, 0x00, 0x9140);
330 phy_write(phy
, 0x00, 0x1140);
335 static int et1011c_init(struct mii_phy
*phy
)
339 reg_short
= (u16
)(phy_read(phy
, 0x16));
341 reg_short
|= 0x6; /* RGMII Trace Delay*/
342 phy_write(phy
, 0x16, reg_short
);
344 reg_short
= (u16
)(phy_read(phy
, 0x17));
345 reg_short
&= ~(0x40);
346 phy_write(phy
, 0x17, reg_short
);
348 phy_write(phy
, 0x1c, 0x74f0);
352 static struct mii_phy_ops et1011c_phy_ops
= {
353 .init
= et1011c_init
,
354 .setup_aneg
= genmii_setup_aneg
,
355 .setup_forced
= genmii_setup_forced
,
356 .poll_link
= genmii_poll_link
,
357 .read_link
= genmii_read_link
360 static struct mii_phy_def et1011c_phy_def
= {
361 .phy_id
= 0x0282f000,
362 .phy_id_mask
= 0x0fffff00,
363 .name
= "ET1011C Gigabit Ethernet",
364 .ops
= &et1011c_phy_ops
371 static struct mii_phy_ops m88e1111_phy_ops
= {
372 .init
= m88e1111_init
,
373 .setup_aneg
= genmii_setup_aneg
,
374 .setup_forced
= genmii_setup_forced
,
375 .poll_link
= genmii_poll_link
,
376 .read_link
= genmii_read_link
379 static struct mii_phy_def m88e1111_phy_def
= {
381 .phy_id
= 0x01410CC0,
382 .phy_id_mask
= 0x0ffffff0,
383 .name
= "Marvell 88E1111 Ethernet",
384 .ops
= &m88e1111_phy_ops
,
387 static struct mii_phy_def
*mii_phy_table
[] = {
396 int emac_mii_phy_probe(struct mii_phy
*phy
, int address
)
398 struct mii_phy_def
*def
;
402 phy
->autoneg
= AUTONEG_DISABLE
;
403 phy
->advertising
= 0;
404 phy
->address
= address
;
405 phy
->speed
= SPEED_10
;
406 phy
->duplex
= DUPLEX_HALF
;
407 phy
->pause
= phy
->asym_pause
= 0;
409 /* Take PHY out of isolate mode and reset it. */
410 if (emac_mii_reset_phy(phy
))
413 /* Read ID and find matching entry */
414 id
= (phy_read(phy
, MII_PHYSID1
) << 16) | phy_read(phy
, MII_PHYSID2
);
415 for (i
= 0; (def
= mii_phy_table
[i
]) != NULL
; i
++)
416 if ((id
& def
->phy_id_mask
) == def
->phy_id
)
418 /* Should never be NULL (we have a generic entry), but... */
424 /* Determine PHY features if needed */
425 phy
->features
= def
->features
;
426 if (!phy
->features
) {
427 u16 bmsr
= phy_read(phy
, MII_BMSR
);
428 if (bmsr
& BMSR_ANEGCAPABLE
)
429 phy
->features
|= SUPPORTED_Autoneg
;
430 if (bmsr
& BMSR_10HALF
)
431 phy
->features
|= SUPPORTED_10baseT_Half
;
432 if (bmsr
& BMSR_10FULL
)
433 phy
->features
|= SUPPORTED_10baseT_Full
;
434 if (bmsr
& BMSR_100HALF
)
435 phy
->features
|= SUPPORTED_100baseT_Half
;
436 if (bmsr
& BMSR_100FULL
)
437 phy
->features
|= SUPPORTED_100baseT_Full
;
438 if (bmsr
& BMSR_ESTATEN
) {
439 u16 esr
= phy_read(phy
, MII_ESTATUS
);
440 if (esr
& ESTATUS_1000_TFULL
)
441 phy
->features
|= SUPPORTED_1000baseT_Full
;
442 if (esr
& ESTATUS_1000_THALF
)
443 phy
->features
|= SUPPORTED_1000baseT_Half
;
445 phy
->features
|= SUPPORTED_MII
;
448 /* Setup default advertising */
449 phy
->advertising
= phy
->features
;
454 MODULE_LICENSE("GPL");