4 * PHY drivers for the ibm ocp ethernet driver. Borrowed
5 * 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)
15 #include <linux/config.h>
17 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/sched.h>
21 #include <linux/types.h>
22 #include <linux/netdevice.h>
23 #include <linux/etherdevice.h>
24 #include <linux/mii.h>
25 #include <linux/ethtool.h>
26 #include <linux/delay.h>
28 #include "ibm_emac_phy.h"
30 static int reset_one_mii_phy(struct mii_phy
*phy
, int phy_id
)
35 val
= __phy_read(phy
, phy_id
, MII_BMCR
);
38 __phy_write(phy
, phy_id
, MII_BMCR
, val
);
43 val
= __phy_read(phy
, phy_id
, MII_BMCR
);
44 if ((val
& BMCR_RESET
) == 0)
48 if ((val
& BMCR_ISOLATE
) && limit
> 0)
49 __phy_write(phy
, phy_id
, MII_BMCR
, val
& ~BMCR_ISOLATE
);
54 static int cis8201_init(struct mii_phy
*phy
)
58 epcr
= phy_read(phy
, MII_CIS8201_EPCR
);
59 epcr
&= ~EPCR_MODE_MASK
;
63 epcr
|= EPCR_TBI_MODE
;
66 epcr
|= EPCR_RTBI_MODE
;
69 epcr
|= EPCR_GMII_MODE
;
73 epcr
|= EPCR_RGMII_MODE
;
76 phy_write(phy
, MII_CIS8201_EPCR
, epcr
);
81 static int genmii_setup_aneg(struct mii_phy
*phy
, u32 advertise
)
86 phy
->speed
= SPEED_10
;
87 phy
->duplex
= DUPLEX_HALF
;
89 phy
->advertising
= advertise
;
91 /* Setup standard advertise */
92 adv
= phy_read(phy
, MII_ADVERTISE
);
93 adv
&= ~(ADVERTISE_ALL
| ADVERTISE_100BASE4
);
94 if (advertise
& ADVERTISED_10baseT_Half
)
95 adv
|= ADVERTISE_10HALF
;
96 if (advertise
& ADVERTISED_10baseT_Full
)
97 adv
|= ADVERTISE_10FULL
;
98 if (advertise
& ADVERTISED_100baseT_Half
)
99 adv
|= ADVERTISE_100HALF
;
100 if (advertise
& ADVERTISED_100baseT_Full
)
101 adv
|= ADVERTISE_100FULL
;
102 phy_write(phy
, MII_ADVERTISE
, 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
)
121 ctl
= phy_read(phy
, MII_BMCR
);
122 ctl
&= ~(BMCR_FULLDPLX
| BMCR_SPEED100
| BMCR_ANENABLE
);
124 /* First reset the PHY */
125 phy_write(phy
, MII_BMCR
, ctl
| BMCR_RESET
);
127 /* Select speed & duplex */
132 ctl
|= BMCR_SPEED100
;
138 if (fd
== DUPLEX_FULL
)
139 ctl
|= BMCR_FULLDPLX
;
140 phy_write(phy
, MII_BMCR
, ctl
);
145 static int genmii_poll_link(struct mii_phy
*phy
)
149 (void)phy_read(phy
, MII_BMSR
);
150 status
= phy_read(phy
, MII_BMSR
);
151 if ((status
& BMSR_LSTATUS
) == 0)
153 if (phy
->autoneg
&& !(status
& BMSR_ANEGCOMPLETE
))
158 #define MII_CIS8201_ACSR 0x1c
159 #define ACSR_DUPLEX_STATUS 0x0020
160 #define ACSR_SPEED_1000BASET 0x0010
161 #define ACSR_SPEED_100BASET 0x0008
163 static int cis8201_read_link(struct mii_phy
*phy
)
168 acsr
= phy_read(phy
, MII_CIS8201_ACSR
);
170 if (acsr
& ACSR_DUPLEX_STATUS
)
171 phy
->duplex
= DUPLEX_FULL
;
173 phy
->duplex
= DUPLEX_HALF
;
174 if (acsr
& ACSR_SPEED_1000BASET
) {
175 phy
->speed
= SPEED_1000
;
176 } else if (acsr
& ACSR_SPEED_100BASET
)
177 phy
->speed
= SPEED_100
;
179 phy
->speed
= SPEED_10
;
182 /* On non-aneg, we assume what we put in BMCR is the speed,
183 * though magic-aneg shouldn't prevent this case from occurring
189 static int genmii_read_link(struct mii_phy
*phy
)
194 lpa
= phy_read(phy
, MII_LPA
) & phy_read(phy
, MII_ADVERTISE
);
196 phy
->speed
= SPEED_10
;
197 phy
->duplex
= DUPLEX_HALF
;
200 if (lpa
& (LPA_100FULL
| LPA_100HALF
)) {
201 phy
->speed
= SPEED_100
;
202 if (lpa
& LPA_100FULL
)
203 phy
->duplex
= DUPLEX_FULL
;
204 } else if (lpa
& LPA_10FULL
)
205 phy
->duplex
= DUPLEX_FULL
;
207 /* On non-aneg, we assume what we put in BMCR is the speed,
208 * though magic-aneg shouldn't prevent this case from occurring
214 #define MII_BASIC_FEATURES (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
215 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
216 SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII)
217 #define MII_GBIT_FEATURES (MII_BASIC_FEATURES | \
218 SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
220 /* CIS8201 phy ops */
221 static struct mii_phy_ops cis8201_phy_ops
= {
223 setup_aneg
:genmii_setup_aneg
,
224 setup_forced
:genmii_setup_forced
,
225 poll_link
:genmii_poll_link
,
226 read_link
:cis8201_read_link
229 /* Generic implementation for most 10/100 PHYs */
230 static struct mii_phy_ops generic_phy_ops
= {
231 setup_aneg
:genmii_setup_aneg
,
232 setup_forced
:genmii_setup_forced
,
233 poll_link
:genmii_poll_link
,
234 read_link
:genmii_read_link
237 static struct mii_phy_def cis8201_phy_def
= {
239 phy_id_mask
:0x000ffff0,
240 name
:"CIS8201 Gigabit Ethernet",
241 features
:MII_GBIT_FEATURES
,
246 static struct mii_phy_def genmii_phy_def
= {
248 phy_id_mask
:0x00000000,
250 features
:MII_BASIC_FEATURES
,
255 static struct mii_phy_def
*mii_phy_table
[] = {
261 int mii_phy_probe(struct mii_phy
*phy
, int mii_id
)
265 struct mii_phy_def
*def
;
269 phy
->advertising
= 0;
270 phy
->mii_id
= mii_id
;
275 /* Take PHY out of isloate mode and reset it. */
276 rc
= reset_one_mii_phy(phy
, mii_id
);
280 /* Read ID and find matching entry */
281 id
= (phy_read(phy
, MII_PHYSID1
) << 16 | phy_read(phy
, MII_PHYSID2
))
283 for (i
= 0; (def
= mii_phy_table
[i
]) != NULL
; i
++)
284 if ((id
& def
->phy_id_mask
) == def
->phy_id
)
286 /* Should never be NULL (we have a generic entry), but... */
292 /* Setup default advertising */
293 phy
->advertising
= def
->features
;
298 MODULE_LICENSE("GPL");