1 /****************************************************************************
2 * Driver for Solarflare Solarstorm network controllers and boards
3 * Copyright 2006-2008 Solarflare Communications Inc.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published
7 * by the Free Software Foundation, incorporated herein by reference.
10 * Useful functions for working with MDIO clause 45 PHYs
12 #include <linux/types.h>
13 #include <linux/ethtool.h>
14 #include <linux/delay.h>
15 #include "net_driver.h"
19 int mdio_clause45_reset_mmd(struct efx_nic
*port
, int mmd
,
20 int spins
, int spintime
)
23 int phy_id
= port
->mii
.phy_id
;
25 /* Catch callers passing values in the wrong units (or just silly) */
26 EFX_BUG_ON_PARANOID(spins
* spintime
>= 5000);
28 mdio_clause45_write(port
, phy_id
, mmd
, MDIO_MMDREG_CTRL1
,
29 (1 << MDIO_MMDREG_CTRL1_RESET_LBN
));
30 /* Wait for the reset bit to clear. */
33 ctrl
= mdio_clause45_read(port
, phy_id
, mmd
, MDIO_MMDREG_CTRL1
);
36 } while (spins
&& (ctrl
& (1 << MDIO_MMDREG_CTRL1_RESET_LBN
)));
38 return spins
? spins
: -ETIMEDOUT
;
41 static int mdio_clause45_check_mmd(struct efx_nic
*efx
, int mmd
,
45 int phy_id
= efx
->mii
.phy_id
;
47 /* Read MMD STATUS2 to check it is responding. */
48 status
= mdio_clause45_read(efx
, phy_id
, mmd
, MDIO_MMDREG_STAT2
);
49 if (((status
>> MDIO_MMDREG_STAT2_PRESENT_LBN
) &
50 ((1 << MDIO_MMDREG_STAT2_PRESENT_WIDTH
) - 1)) !=
51 MDIO_MMDREG_STAT2_PRESENT_VAL
) {
52 EFX_ERR(efx
, "PHY MMD %d not responding.\n", mmd
);
56 /* Read MMD STATUS 1 to check for fault. */
57 status
= mdio_clause45_read(efx
, phy_id
, mmd
, MDIO_MMDREG_STAT1
);
58 if ((status
& (1 << MDIO_MMDREG_STAT1_FAULT_LBN
)) != 0) {
60 EFX_ERR(efx
, "PHY MMD %d reporting fatal"
61 " fault: status %x\n", mmd
, status
);
64 EFX_LOG(efx
, "PHY MMD %d reporting status"
65 " %x (expected)\n", mmd
, status
);
71 /* This ought to be ridiculous overkill. We expect it to fail rarely */
72 #define MDIO45_RESET_TIME 1000 /* ms */
73 #define MDIO45_RESET_ITERS 100
75 int mdio_clause45_wait_reset_mmds(struct efx_nic
*efx
,
76 unsigned int mmd_mask
)
78 const int spintime
= MDIO45_RESET_TIME
/ MDIO45_RESET_ITERS
;
79 int tries
= MDIO45_RESET_ITERS
;
90 stat
= mdio_clause45_read(efx
,
95 EFX_ERR(efx
, "failed to read status of"
99 if (stat
& (1 << MDIO_MMDREG_CTRL1_RESET_LBN
))
100 in_reset
|= (1 << mmd
);
111 EFX_ERR(efx
, "not all MMDs came out of reset in time."
112 " MMDs still in reset: %x\n", in_reset
);
118 int mdio_clause45_check_mmds(struct efx_nic
*efx
,
119 unsigned int mmd_mask
, unsigned int fatal_mask
)
121 int devices
, mmd
= 0;
124 /* Historically we have probed the PHYXS to find out what devices are
125 * present,but that doesn't work so well if the PHYXS isn't expected
126 * to exist, if so just find the first item in the list supplied. */
127 probe_mmd
= (mmd_mask
& MDIO_MMDREG_DEVS0_PHYXS
) ? MDIO_MMD_PHYXS
:
129 devices
= mdio_clause45_read(efx
, efx
->mii
.phy_id
,
130 probe_mmd
, MDIO_MMDREG_DEVS0
);
132 /* Check all the expected MMDs are present */
134 EFX_ERR(efx
, "failed to read devices present\n");
137 if ((devices
& mmd_mask
) != mmd_mask
) {
138 EFX_ERR(efx
, "required MMDs not present: got %x, "
139 "wanted %x\n", devices
, mmd_mask
);
142 EFX_TRACE(efx
, "Devices present: %x\n", devices
);
144 /* Check all required MMDs are responding and happy. */
147 int fault_fatal
= fatal_mask
& 1;
148 if (mdio_clause45_check_mmd(efx
, mmd
, fault_fatal
))
151 mmd_mask
= mmd_mask
>> 1;
152 fatal_mask
= fatal_mask
>> 1;
159 int mdio_clause45_links_ok(struct efx_nic
*efx
, unsigned int mmd_mask
)
161 int phy_id
= efx
->mii
.phy_id
;
169 /* Double reads because link state is latched, and a
170 * read moves the current state into the register */
171 status
= mdio_clause45_read(efx
, phy_id
,
172 mmd
, MDIO_MMDREG_STAT1
);
173 status
= mdio_clause45_read(efx
, phy_id
,
174 mmd
, MDIO_MMDREG_STAT1
);
176 good
= status
& (1 << MDIO_MMDREG_STAT1_LINK_LBN
);
179 mmd_mask
= (mmd_mask
>> 1);
186 * mdio_clause45_get_settings - Read (some of) the PHY settings over MDIO.
188 * @ecmd: Buffer for settings
190 * On return the 'port', 'speed', 'supported' and 'advertising' fields of
191 * ecmd have been filled out based on the PMA type.
193 void mdio_clause45_get_settings(struct efx_nic
*efx
,
194 struct ethtool_cmd
*ecmd
)
198 /* If no PMA is present we are presumably talking something XAUI-ish
199 * like CX4. Which we report as FIBRE (see below) */
200 if ((efx
->phy_op
->mmds
& DEV_PRESENT_BIT(MDIO_MMD_PMAPMD
)) == 0) {
201 ecmd
->speed
= SPEED_10000
;
202 ecmd
->port
= PORT_FIBRE
;
203 ecmd
->supported
= SUPPORTED_FIBRE
;
204 ecmd
->advertising
= ADVERTISED_FIBRE
;
208 pma_type
= mdio_clause45_read(efx
, efx
->mii
.phy_id
,
209 MDIO_MMD_PMAPMD
, MDIO_MMDREG_CTRL2
);
210 pma_type
&= MDIO_PMAPMD_CTRL2_TYPE_MASK
;
213 /* We represent CX4 as fibre in the absence of anything
215 case MDIO_PMAPMD_CTRL2_10G_CX4
:
216 ecmd
->speed
= SPEED_10000
;
217 ecmd
->port
= PORT_FIBRE
;
218 ecmd
->supported
= SUPPORTED_FIBRE
;
219 ecmd
->advertising
= ADVERTISED_FIBRE
;
222 case MDIO_PMAPMD_CTRL2_10G_BT
:
223 ecmd
->speed
= SPEED_10000
;
224 ecmd
->port
= PORT_TP
;
225 ecmd
->supported
= SUPPORTED_TP
| SUPPORTED_10000baseT_Full
;
226 ecmd
->advertising
= (ADVERTISED_FIBRE
227 | ADVERTISED_10000baseT_Full
);
229 case MDIO_PMAPMD_CTRL2_1G_BT
:
230 ecmd
->speed
= SPEED_1000
;
231 ecmd
->port
= PORT_TP
;
232 ecmd
->supported
= SUPPORTED_TP
| SUPPORTED_1000baseT_Full
;
233 ecmd
->advertising
= (ADVERTISED_FIBRE
234 | ADVERTISED_1000baseT_Full
);
236 case MDIO_PMAPMD_CTRL2_100_BT
:
237 ecmd
->speed
= SPEED_100
;
238 ecmd
->port
= PORT_TP
;
239 ecmd
->supported
= SUPPORTED_TP
| SUPPORTED_100baseT_Full
;
240 ecmd
->advertising
= (ADVERTISED_FIBRE
241 | ADVERTISED_100baseT_Full
);
243 case MDIO_PMAPMD_CTRL2_10_BT
:
244 ecmd
->speed
= SPEED_10
;
245 ecmd
->port
= PORT_TP
;
246 ecmd
->supported
= SUPPORTED_TP
| SUPPORTED_10baseT_Full
;
247 ecmd
->advertising
= ADVERTISED_FIBRE
| ADVERTISED_10baseT_Full
;
249 /* All the other defined modes are flavours of
252 ecmd
->speed
= SPEED_10000
;
253 ecmd
->port
= PORT_FIBRE
;
254 ecmd
->supported
= SUPPORTED_FIBRE
;
255 ecmd
->advertising
= ADVERTISED_FIBRE
;
261 * mdio_clause45_set_settings - Set (some of) the PHY settings over MDIO.
263 * @ecmd: New settings
265 * Currently this just enforces that we are _not_ changing the
266 * 'port', 'speed', 'supported' or 'advertising' settings as these
267 * cannot be changed on any currently supported PHY.
269 int mdio_clause45_set_settings(struct efx_nic
*efx
,
270 struct ethtool_cmd
*ecmd
)
272 struct ethtool_cmd tmpcmd
;
273 mdio_clause45_get_settings(efx
, &tmpcmd
);
274 /* None of the current PHYs support more than one mode
275 * of operation (and only 10GBT ever will), so keep things
277 if ((ecmd
->speed
== tmpcmd
.speed
) && (ecmd
->port
== tmpcmd
.port
) &&
278 (ecmd
->supported
== tmpcmd
.supported
) &&
279 (ecmd
->advertising
== tmpcmd
.advertising
))