diff options
Diffstat (limited to 'drivers/net/sfc/mdio_10g.c')
-rw-r--r-- | drivers/net/sfc/mdio_10g.c | 379 |
1 files changed, 84 insertions, 295 deletions
diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c index 9f5ec3eb3418..11c231a1f875 100644 --- a/drivers/net/sfc/mdio_10g.c +++ b/drivers/net/sfc/mdio_10g.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include "boards.h" | 17 | #include "boards.h" |
18 | #include "workarounds.h" | 18 | #include "workarounds.h" |
19 | 19 | ||
20 | unsigned mdio_id_oui(u32 id) | 20 | unsigned efx_mdio_id_oui(u32 id) |
21 | { | 21 | { |
22 | unsigned oui = 0; | 22 | unsigned oui = 0; |
23 | int i; | 23 | int i; |
@@ -32,52 +32,45 @@ unsigned mdio_id_oui(u32 id) | |||
32 | return oui; | 32 | return oui; |
33 | } | 33 | } |
34 | 34 | ||
35 | int mdio_clause45_reset_mmd(struct efx_nic *port, int mmd, | 35 | int efx_mdio_reset_mmd(struct efx_nic *port, int mmd, |
36 | int spins, int spintime) | 36 | int spins, int spintime) |
37 | { | 37 | { |
38 | u32 ctrl; | 38 | u32 ctrl; |
39 | int phy_id = port->mii.phy_id; | ||
40 | 39 | ||
41 | /* Catch callers passing values in the wrong units (or just silly) */ | 40 | /* Catch callers passing values in the wrong units (or just silly) */ |
42 | EFX_BUG_ON_PARANOID(spins * spintime >= 5000); | 41 | EFX_BUG_ON_PARANOID(spins * spintime >= 5000); |
43 | 42 | ||
44 | mdio_clause45_write(port, phy_id, mmd, MDIO_MMDREG_CTRL1, | 43 | efx_mdio_write(port, mmd, MDIO_CTRL1, MDIO_CTRL1_RESET); |
45 | (1 << MDIO_MMDREG_CTRL1_RESET_LBN)); | ||
46 | /* Wait for the reset bit to clear. */ | 44 | /* Wait for the reset bit to clear. */ |
47 | do { | 45 | do { |
48 | msleep(spintime); | 46 | msleep(spintime); |
49 | ctrl = mdio_clause45_read(port, phy_id, mmd, MDIO_MMDREG_CTRL1); | 47 | ctrl = efx_mdio_read(port, mmd, MDIO_CTRL1); |
50 | spins--; | 48 | spins--; |
51 | 49 | ||
52 | } while (spins && (ctrl & (1 << MDIO_MMDREG_CTRL1_RESET_LBN))); | 50 | } while (spins && (ctrl & MDIO_CTRL1_RESET)); |
53 | 51 | ||
54 | return spins ? spins : -ETIMEDOUT; | 52 | return spins ? spins : -ETIMEDOUT; |
55 | } | 53 | } |
56 | 54 | ||
57 | static int mdio_clause45_check_mmd(struct efx_nic *efx, int mmd, | 55 | static int efx_mdio_check_mmd(struct efx_nic *efx, int mmd, int fault_fatal) |
58 | int fault_fatal) | ||
59 | { | 56 | { |
60 | int status; | 57 | int status; |
61 | int phy_id = efx->mii.phy_id; | ||
62 | 58 | ||
63 | if (LOOPBACK_INTERNAL(efx)) | 59 | if (LOOPBACK_INTERNAL(efx)) |
64 | return 0; | 60 | return 0; |
65 | 61 | ||
66 | if (mmd != MDIO_MMD_AN) { | 62 | if (mmd != MDIO_MMD_AN) { |
67 | /* Read MMD STATUS2 to check it is responding. */ | 63 | /* Read MMD STATUS2 to check it is responding. */ |
68 | status = mdio_clause45_read(efx, phy_id, mmd, | 64 | status = efx_mdio_read(efx, mmd, MDIO_STAT2); |
69 | MDIO_MMDREG_STAT2); | 65 | if ((status & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL) { |
70 | if (((status >> MDIO_MMDREG_STAT2_PRESENT_LBN) & | ||
71 | ((1 << MDIO_MMDREG_STAT2_PRESENT_WIDTH) - 1)) != | ||
72 | MDIO_MMDREG_STAT2_PRESENT_VAL) { | ||
73 | EFX_ERR(efx, "PHY MMD %d not responding.\n", mmd); | 66 | EFX_ERR(efx, "PHY MMD %d not responding.\n", mmd); |
74 | return -EIO; | 67 | return -EIO; |
75 | } | 68 | } |
76 | } | 69 | } |
77 | 70 | ||
78 | /* Read MMD STATUS 1 to check for fault. */ | 71 | /* Read MMD STATUS 1 to check for fault. */ |
79 | status = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_STAT1); | 72 | status = efx_mdio_read(efx, mmd, MDIO_STAT1); |
80 | if ((status & (1 << MDIO_MMDREG_STAT1_FAULT_LBN)) != 0) { | 73 | if (status & MDIO_STAT1_FAULT) { |
81 | if (fault_fatal) { | 74 | if (fault_fatal) { |
82 | EFX_ERR(efx, "PHY MMD %d reporting fatal" | 75 | EFX_ERR(efx, "PHY MMD %d reporting fatal" |
83 | " fault: status %x\n", mmd, status); | 76 | " fault: status %x\n", mmd, status); |
@@ -94,8 +87,7 @@ static int mdio_clause45_check_mmd(struct efx_nic *efx, int mmd, | |||
94 | #define MDIO45_RESET_TIME 1000 /* ms */ | 87 | #define MDIO45_RESET_TIME 1000 /* ms */ |
95 | #define MDIO45_RESET_ITERS 100 | 88 | #define MDIO45_RESET_ITERS 100 |
96 | 89 | ||
97 | int mdio_clause45_wait_reset_mmds(struct efx_nic *efx, | 90 | int efx_mdio_wait_reset_mmds(struct efx_nic *efx, unsigned int mmd_mask) |
98 | unsigned int mmd_mask) | ||
99 | { | 91 | { |
100 | const int spintime = MDIO45_RESET_TIME / MDIO45_RESET_ITERS; | 92 | const int spintime = MDIO45_RESET_TIME / MDIO45_RESET_ITERS; |
101 | int tries = MDIO45_RESET_ITERS; | 93 | int tries = MDIO45_RESET_ITERS; |
@@ -109,16 +101,13 @@ int mdio_clause45_wait_reset_mmds(struct efx_nic *efx, | |||
109 | in_reset = 0; | 101 | in_reset = 0; |
110 | while (mask) { | 102 | while (mask) { |
111 | if (mask & 1) { | 103 | if (mask & 1) { |
112 | stat = mdio_clause45_read(efx, | 104 | stat = efx_mdio_read(efx, mmd, MDIO_CTRL1); |
113 | efx->mii.phy_id, | ||
114 | mmd, | ||
115 | MDIO_MMDREG_CTRL1); | ||
116 | if (stat < 0) { | 105 | if (stat < 0) { |
117 | EFX_ERR(efx, "failed to read status of" | 106 | EFX_ERR(efx, "failed to read status of" |
118 | " MMD %d\n", mmd); | 107 | " MMD %d\n", mmd); |
119 | return -EIO; | 108 | return -EIO; |
120 | } | 109 | } |
121 | if (stat & (1 << MDIO_MMDREG_CTRL1_RESET_LBN)) | 110 | if (stat & MDIO_CTRL1_RESET) |
122 | in_reset |= (1 << mmd); | 111 | in_reset |= (1 << mmd); |
123 | } | 112 | } |
124 | mask = mask >> 1; | 113 | mask = mask >> 1; |
@@ -137,28 +126,26 @@ int mdio_clause45_wait_reset_mmds(struct efx_nic *efx, | |||
137 | return rc; | 126 | return rc; |
138 | } | 127 | } |
139 | 128 | ||
140 | int mdio_clause45_check_mmds(struct efx_nic *efx, | 129 | int efx_mdio_check_mmds(struct efx_nic *efx, |
141 | unsigned int mmd_mask, unsigned int fatal_mask) | 130 | unsigned int mmd_mask, unsigned int fatal_mask) |
142 | { | 131 | { |
143 | int mmd = 0, probe_mmd, devs0, devs1; | 132 | int mmd = 0, probe_mmd, devs1, devs2; |
144 | u32 devices; | 133 | u32 devices; |
145 | 134 | ||
146 | /* Historically we have probed the PHYXS to find out what devices are | 135 | /* Historically we have probed the PHYXS to find out what devices are |
147 | * present,but that doesn't work so well if the PHYXS isn't expected | 136 | * present,but that doesn't work so well if the PHYXS isn't expected |
148 | * to exist, if so just find the first item in the list supplied. */ | 137 | * to exist, if so just find the first item in the list supplied. */ |
149 | probe_mmd = (mmd_mask & MDIO_MMDREG_DEVS_PHYXS) ? MDIO_MMD_PHYXS : | 138 | probe_mmd = (mmd_mask & MDIO_DEVS_PHYXS) ? MDIO_MMD_PHYXS : |
150 | __ffs(mmd_mask); | 139 | __ffs(mmd_mask); |
151 | 140 | ||
152 | /* Check all the expected MMDs are present */ | 141 | /* Check all the expected MMDs are present */ |
153 | devs0 = mdio_clause45_read(efx, efx->mii.phy_id, | 142 | devs1 = efx_mdio_read(efx, probe_mmd, MDIO_DEVS1); |
154 | probe_mmd, MDIO_MMDREG_DEVS0); | 143 | devs2 = efx_mdio_read(efx, probe_mmd, MDIO_DEVS2); |
155 | devs1 = mdio_clause45_read(efx, efx->mii.phy_id, | 144 | if (devs1 < 0 || devs2 < 0) { |
156 | probe_mmd, MDIO_MMDREG_DEVS1); | ||
157 | if (devs0 < 0 || devs1 < 0) { | ||
158 | EFX_ERR(efx, "failed to read devices present\n"); | 145 | EFX_ERR(efx, "failed to read devices present\n"); |
159 | return -EIO; | 146 | return -EIO; |
160 | } | 147 | } |
161 | devices = devs0 | (devs1 << 16); | 148 | devices = devs1 | (devs2 << 16); |
162 | if ((devices & mmd_mask) != mmd_mask) { | 149 | if ((devices & mmd_mask) != mmd_mask) { |
163 | EFX_ERR(efx, "required MMDs not present: got %x, " | 150 | EFX_ERR(efx, "required MMDs not present: got %x, " |
164 | "wanted %x\n", devices, mmd_mask); | 151 | "wanted %x\n", devices, mmd_mask); |
@@ -170,7 +157,7 @@ int mdio_clause45_check_mmds(struct efx_nic *efx, | |||
170 | while (mmd_mask) { | 157 | while (mmd_mask) { |
171 | if (mmd_mask & 1) { | 158 | if (mmd_mask & 1) { |
172 | int fault_fatal = fatal_mask & 1; | 159 | int fault_fatal = fatal_mask & 1; |
173 | if (mdio_clause45_check_mmd(efx, mmd, fault_fatal)) | 160 | if (efx_mdio_check_mmd(efx, mmd, fault_fatal)) |
174 | return -EIO; | 161 | return -EIO; |
175 | } | 162 | } |
176 | mmd_mask = mmd_mask >> 1; | 163 | mmd_mask = mmd_mask >> 1; |
@@ -181,13 +168,8 @@ int mdio_clause45_check_mmds(struct efx_nic *efx, | |||
181 | return 0; | 168 | return 0; |
182 | } | 169 | } |
183 | 170 | ||
184 | bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask) | 171 | bool efx_mdio_links_ok(struct efx_nic *efx, unsigned int mmd_mask) |
185 | { | 172 | { |
186 | int phy_id = efx->mii.phy_id; | ||
187 | u32 reg; | ||
188 | bool ok = true; | ||
189 | int mmd = 0; | ||
190 | |||
191 | /* If the port is in loopback, then we should only consider a subset | 173 | /* If the port is in loopback, then we should only consider a subset |
192 | * of mmd's */ | 174 | * of mmd's */ |
193 | if (LOOPBACK_INTERNAL(efx)) | 175 | if (LOOPBACK_INTERNAL(efx)) |
@@ -197,241 +179,75 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask) | |||
197 | else if (efx_phy_mode_disabled(efx->phy_mode)) | 179 | else if (efx_phy_mode_disabled(efx->phy_mode)) |
198 | return false; | 180 | return false; |
199 | else if (efx->loopback_mode == LOOPBACK_PHYXS) | 181 | else if (efx->loopback_mode == LOOPBACK_PHYXS) |
200 | mmd_mask &= ~(MDIO_MMDREG_DEVS_PHYXS | | 182 | mmd_mask &= ~(MDIO_DEVS_PHYXS | |
201 | MDIO_MMDREG_DEVS_PCS | | 183 | MDIO_DEVS_PCS | |
202 | MDIO_MMDREG_DEVS_PMAPMD | | 184 | MDIO_DEVS_PMAPMD | |
203 | MDIO_MMDREG_DEVS_AN); | 185 | MDIO_DEVS_AN); |
204 | else if (efx->loopback_mode == LOOPBACK_PCS) | 186 | else if (efx->loopback_mode == LOOPBACK_PCS) |
205 | mmd_mask &= ~(MDIO_MMDREG_DEVS_PCS | | 187 | mmd_mask &= ~(MDIO_DEVS_PCS | |
206 | MDIO_MMDREG_DEVS_PMAPMD | | 188 | MDIO_DEVS_PMAPMD | |
207 | MDIO_MMDREG_DEVS_AN); | 189 | MDIO_DEVS_AN); |
208 | else if (efx->loopback_mode == LOOPBACK_PMAPMD) | 190 | else if (efx->loopback_mode == LOOPBACK_PMAPMD) |
209 | mmd_mask &= ~(MDIO_MMDREG_DEVS_PMAPMD | | 191 | mmd_mask &= ~(MDIO_DEVS_PMAPMD | |
210 | MDIO_MMDREG_DEVS_AN); | 192 | MDIO_DEVS_AN); |
211 | |||
212 | if (!mmd_mask) { | ||
213 | /* Use presence of XGMII faults in leui of link state */ | ||
214 | reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS, | ||
215 | MDIO_PHYXS_STATUS2); | ||
216 | return !(reg & (1 << MDIO_PHYXS_STATUS2_RX_FAULT_LBN)); | ||
217 | } | ||
218 | 193 | ||
219 | while (mmd_mask) { | 194 | return mdio45_links_ok(&efx->mdio, mmd_mask); |
220 | if (mmd_mask & 1) { | ||
221 | /* Double reads because link state is latched, and a | ||
222 | * read moves the current state into the register */ | ||
223 | reg = mdio_clause45_read(efx, phy_id, | ||
224 | mmd, MDIO_MMDREG_STAT1); | ||
225 | reg = mdio_clause45_read(efx, phy_id, | ||
226 | mmd, MDIO_MMDREG_STAT1); | ||
227 | ok = ok && (reg & (1 << MDIO_MMDREG_STAT1_LINK_LBN)); | ||
228 | } | ||
229 | mmd_mask = (mmd_mask >> 1); | ||
230 | mmd++; | ||
231 | } | ||
232 | return ok; | ||
233 | } | 195 | } |
234 | 196 | ||
235 | void mdio_clause45_transmit_disable(struct efx_nic *efx) | 197 | void efx_mdio_transmit_disable(struct efx_nic *efx) |
236 | { | 198 | { |
237 | mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, | 199 | efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, |
238 | MDIO_MMDREG_TXDIS, MDIO_MMDREG_TXDIS_GLOBAL_LBN, | 200 | MDIO_PMA_TXDIS, MDIO_PMD_TXDIS_GLOBAL, |
239 | efx->phy_mode & PHY_MODE_TX_DISABLED); | 201 | efx->phy_mode & PHY_MODE_TX_DISABLED); |
240 | } | 202 | } |
241 | 203 | ||
242 | void mdio_clause45_phy_reconfigure(struct efx_nic *efx) | 204 | void efx_mdio_phy_reconfigure(struct efx_nic *efx) |
243 | { | 205 | { |
244 | int phy_id = efx->mii.phy_id; | 206 | efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, |
245 | 207 | MDIO_CTRL1, MDIO_PMA_CTRL1_LOOPBACK, | |
246 | mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PMAPMD, | 208 | efx->loopback_mode == LOOPBACK_PMAPMD); |
247 | MDIO_MMDREG_CTRL1, MDIO_PMAPMD_CTRL1_LBACK_LBN, | 209 | efx_mdio_set_flag(efx, MDIO_MMD_PCS, |
248 | efx->loopback_mode == LOOPBACK_PMAPMD); | 210 | MDIO_CTRL1, MDIO_PCS_CTRL1_LOOPBACK, |
249 | mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PCS, | 211 | efx->loopback_mode == LOOPBACK_PCS); |
250 | MDIO_MMDREG_CTRL1, MDIO_MMDREG_CTRL1_LBACK_LBN, | 212 | efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, |
251 | efx->loopback_mode == LOOPBACK_PCS); | 213 | MDIO_CTRL1, MDIO_PHYXS_CTRL1_LOOPBACK, |
252 | mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PHYXS, | 214 | efx->loopback_mode == LOOPBACK_NETWORK); |
253 | MDIO_MMDREG_CTRL1, MDIO_MMDREG_CTRL1_LBACK_LBN, | ||
254 | efx->loopback_mode == LOOPBACK_NETWORK); | ||
255 | } | 215 | } |
256 | 216 | ||
257 | static void mdio_clause45_set_mmd_lpower(struct efx_nic *efx, | 217 | static void efx_mdio_set_mmd_lpower(struct efx_nic *efx, |
258 | int lpower, int mmd) | 218 | int lpower, int mmd) |
259 | { | 219 | { |
260 | int phy = efx->mii.phy_id; | 220 | int stat = efx_mdio_read(efx, mmd, MDIO_STAT1); |
261 | int stat = mdio_clause45_read(efx, phy, mmd, MDIO_MMDREG_STAT1); | ||
262 | 221 | ||
263 | EFX_TRACE(efx, "Setting low power mode for MMD %d to %d\n", | 222 | EFX_TRACE(efx, "Setting low power mode for MMD %d to %d\n", |
264 | mmd, lpower); | 223 | mmd, lpower); |
265 | 224 | ||
266 | if (stat & (1 << MDIO_MMDREG_STAT1_LPABLE_LBN)) { | 225 | if (stat & MDIO_STAT1_LPOWERABLE) { |
267 | mdio_clause45_set_flag(efx, phy, mmd, MDIO_MMDREG_CTRL1, | 226 | efx_mdio_set_flag(efx, mmd, MDIO_CTRL1, |
268 | MDIO_MMDREG_CTRL1_LPOWER_LBN, lpower); | 227 | MDIO_CTRL1_LPOWER, lpower); |
269 | } | 228 | } |
270 | } | 229 | } |
271 | 230 | ||
272 | void mdio_clause45_set_mmds_lpower(struct efx_nic *efx, | 231 | void efx_mdio_set_mmds_lpower(struct efx_nic *efx, |
273 | int low_power, unsigned int mmd_mask) | 232 | int low_power, unsigned int mmd_mask) |
274 | { | 233 | { |
275 | int mmd = 0; | 234 | int mmd = 0; |
276 | mmd_mask &= ~MDIO_MMDREG_DEVS_AN; | 235 | mmd_mask &= ~MDIO_DEVS_AN; |
277 | while (mmd_mask) { | 236 | while (mmd_mask) { |
278 | if (mmd_mask & 1) | 237 | if (mmd_mask & 1) |
279 | mdio_clause45_set_mmd_lpower(efx, low_power, mmd); | 238 | efx_mdio_set_mmd_lpower(efx, low_power, mmd); |
280 | mmd_mask = (mmd_mask >> 1); | 239 | mmd_mask = (mmd_mask >> 1); |
281 | mmd++; | 240 | mmd++; |
282 | } | 241 | } |
283 | } | 242 | } |
284 | 243 | ||
285 | static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr) | ||
286 | { | ||
287 | int phy_id = efx->mii.phy_id; | ||
288 | u32 result = 0; | ||
289 | int reg; | ||
290 | |||
291 | reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, addr); | ||
292 | if (reg & ADVERTISE_10HALF) | ||
293 | result |= ADVERTISED_10baseT_Half; | ||
294 | if (reg & ADVERTISE_10FULL) | ||
295 | result |= ADVERTISED_10baseT_Full; | ||
296 | if (reg & ADVERTISE_100HALF) | ||
297 | result |= ADVERTISED_100baseT_Half; | ||
298 | if (reg & ADVERTISE_100FULL) | ||
299 | result |= ADVERTISED_100baseT_Full; | ||
300 | return result; | ||
301 | } | ||
302 | |||
303 | /** | ||
304 | * mdio_clause45_get_settings - Read (some of) the PHY settings over MDIO. | ||
305 | * @efx: Efx NIC | ||
306 | * @ecmd: Buffer for settings | ||
307 | * | ||
308 | * On return the 'port', 'speed', 'supported' and 'advertising' fields of | ||
309 | * ecmd have been filled out. | ||
310 | */ | ||
311 | void mdio_clause45_get_settings(struct efx_nic *efx, | ||
312 | struct ethtool_cmd *ecmd) | ||
313 | { | ||
314 | mdio_clause45_get_settings_ext(efx, ecmd, 0, 0); | ||
315 | } | ||
316 | |||
317 | /** | 244 | /** |
318 | * mdio_clause45_get_settings_ext - Read (some of) the PHY settings over MDIO. | 245 | * efx_mdio_set_settings - Set (some of) the PHY settings over MDIO. |
319 | * @efx: Efx NIC | ||
320 | * @ecmd: Buffer for settings | ||
321 | * @xnp: Advertised Extended Next Page state | ||
322 | * @xnp_lpa: Link Partner's advertised XNP state | ||
323 | * | ||
324 | * On return the 'port', 'speed', 'supported' and 'advertising' fields of | ||
325 | * ecmd have been filled out. | ||
326 | */ | ||
327 | void mdio_clause45_get_settings_ext(struct efx_nic *efx, | ||
328 | struct ethtool_cmd *ecmd, | ||
329 | u32 npage_adv, u32 npage_lpa) | ||
330 | { | ||
331 | int phy_id = efx->mii.phy_id; | ||
332 | int reg; | ||
333 | |||
334 | ecmd->transceiver = XCVR_INTERNAL; | ||
335 | ecmd->phy_address = phy_id; | ||
336 | |||
337 | reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, | ||
338 | MDIO_MMDREG_CTRL2); | ||
339 | switch (reg & MDIO_PMAPMD_CTRL2_TYPE_MASK) { | ||
340 | case MDIO_PMAPMD_CTRL2_10G_BT: | ||
341 | case MDIO_PMAPMD_CTRL2_1G_BT: | ||
342 | case MDIO_PMAPMD_CTRL2_100_BT: | ||
343 | case MDIO_PMAPMD_CTRL2_10_BT: | ||
344 | ecmd->port = PORT_TP; | ||
345 | ecmd->supported = SUPPORTED_TP; | ||
346 | reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, | ||
347 | MDIO_MMDREG_SPEED); | ||
348 | if (reg & (1 << MDIO_MMDREG_SPEED_10G_LBN)) | ||
349 | ecmd->supported |= SUPPORTED_10000baseT_Full; | ||
350 | if (reg & (1 << MDIO_MMDREG_SPEED_1000M_LBN)) | ||
351 | ecmd->supported |= (SUPPORTED_1000baseT_Full | | ||
352 | SUPPORTED_1000baseT_Half); | ||
353 | if (reg & (1 << MDIO_MMDREG_SPEED_100M_LBN)) | ||
354 | ecmd->supported |= (SUPPORTED_100baseT_Full | | ||
355 | SUPPORTED_100baseT_Half); | ||
356 | if (reg & (1 << MDIO_MMDREG_SPEED_10M_LBN)) | ||
357 | ecmd->supported |= (SUPPORTED_10baseT_Full | | ||
358 | SUPPORTED_10baseT_Half); | ||
359 | ecmd->advertising = ADVERTISED_TP; | ||
360 | break; | ||
361 | |||
362 | /* We represent CX4 as fibre in the absence of anything better */ | ||
363 | case MDIO_PMAPMD_CTRL2_10G_CX4: | ||
364 | /* All the other defined modes are flavours of optical */ | ||
365 | default: | ||
366 | ecmd->port = PORT_FIBRE; | ||
367 | ecmd->supported = SUPPORTED_FIBRE; | ||
368 | ecmd->advertising = ADVERTISED_FIBRE; | ||
369 | break; | ||
370 | } | ||
371 | |||
372 | if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) { | ||
373 | ecmd->supported |= SUPPORTED_Autoneg; | ||
374 | reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, | ||
375 | MDIO_MMDREG_CTRL1); | ||
376 | if (reg & BMCR_ANENABLE) { | ||
377 | ecmd->autoneg = AUTONEG_ENABLE; | ||
378 | ecmd->advertising |= | ||
379 | ADVERTISED_Autoneg | | ||
380 | mdio_clause45_get_an(efx, MDIO_AN_ADVERTISE) | | ||
381 | npage_adv; | ||
382 | } else | ||
383 | ecmd->autoneg = AUTONEG_DISABLE; | ||
384 | } else | ||
385 | ecmd->autoneg = AUTONEG_DISABLE; | ||
386 | |||
387 | if (ecmd->autoneg) { | ||
388 | /* If AN is complete, report best common mode, | ||
389 | * otherwise report best advertised mode. */ | ||
390 | u32 modes = 0; | ||
391 | if (mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, | ||
392 | MDIO_MMDREG_STAT1) & | ||
393 | (1 << MDIO_AN_STATUS_AN_DONE_LBN)) | ||
394 | modes = (ecmd->advertising & | ||
395 | (mdio_clause45_get_an(efx, MDIO_AN_LPA) | | ||
396 | npage_lpa)); | ||
397 | if (modes == 0) | ||
398 | modes = ecmd->advertising; | ||
399 | |||
400 | if (modes & ADVERTISED_10000baseT_Full) { | ||
401 | ecmd->speed = SPEED_10000; | ||
402 | ecmd->duplex = DUPLEX_FULL; | ||
403 | } else if (modes & (ADVERTISED_1000baseT_Full | | ||
404 | ADVERTISED_1000baseT_Half)) { | ||
405 | ecmd->speed = SPEED_1000; | ||
406 | ecmd->duplex = !!(modes & ADVERTISED_1000baseT_Full); | ||
407 | } else if (modes & (ADVERTISED_100baseT_Full | | ||
408 | ADVERTISED_100baseT_Half)) { | ||
409 | ecmd->speed = SPEED_100; | ||
410 | ecmd->duplex = !!(modes & ADVERTISED_100baseT_Full); | ||
411 | } else { | ||
412 | ecmd->speed = SPEED_10; | ||
413 | ecmd->duplex = !!(modes & ADVERTISED_10baseT_Full); | ||
414 | } | ||
415 | } else { | ||
416 | /* Report forced settings */ | ||
417 | reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, | ||
418 | MDIO_MMDREG_CTRL1); | ||
419 | ecmd->speed = (((reg & BMCR_SPEED1000) ? 100 : 1) * | ||
420 | ((reg & BMCR_SPEED100) ? 100 : 10)); | ||
421 | ecmd->duplex = (reg & BMCR_FULLDPLX || | ||
422 | ecmd->speed == SPEED_10000); | ||
423 | } | ||
424 | } | ||
425 | |||
426 | /** | ||
427 | * mdio_clause45_set_settings - Set (some of) the PHY settings over MDIO. | ||
428 | * @efx: Efx NIC | 246 | * @efx: Efx NIC |
429 | * @ecmd: New settings | 247 | * @ecmd: New settings |
430 | */ | 248 | */ |
431 | int mdio_clause45_set_settings(struct efx_nic *efx, | 249 | int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) |
432 | struct ethtool_cmd *ecmd) | ||
433 | { | 250 | { |
434 | int phy_id = efx->mii.phy_id; | ||
435 | struct ethtool_cmd prev; | 251 | struct ethtool_cmd prev; |
436 | u32 required; | 252 | u32 required; |
437 | int reg; | 253 | int reg; |
@@ -489,94 +305,67 @@ int mdio_clause45_set_settings(struct efx_nic *efx, | |||
489 | ADVERTISED_1000baseT_Full)) | 305 | ADVERTISED_1000baseT_Full)) |
490 | reg |= ADVERTISE_NPAGE; | 306 | reg |= ADVERTISE_NPAGE; |
491 | reg |= efx_fc_advertise(efx->wanted_fc); | 307 | reg |= efx_fc_advertise(efx->wanted_fc); |
492 | mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, | 308 | efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg); |
493 | MDIO_AN_ADVERTISE, reg); | ||
494 | 309 | ||
495 | /* Set up the (extended) next page if necessary */ | 310 | /* Set up the (extended) next page if necessary */ |
496 | if (efx->phy_op->set_npage_adv) | 311 | if (efx->phy_op->set_npage_adv) |
497 | efx->phy_op->set_npage_adv(efx, ecmd->advertising); | 312 | efx->phy_op->set_npage_adv(efx, ecmd->advertising); |
498 | 313 | ||
499 | /* Enable and restart AN */ | 314 | /* Enable and restart AN */ |
500 | reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, | 315 | reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1); |
501 | MDIO_MMDREG_CTRL1); | 316 | reg |= MDIO_AN_CTRL1_ENABLE; |
502 | reg |= BMCR_ANENABLE; | ||
503 | if (!(EFX_WORKAROUND_15195(efx) && | 317 | if (!(EFX_WORKAROUND_15195(efx) && |
504 | LOOPBACK_MASK(efx) & efx->phy_op->loopbacks)) | 318 | LOOPBACK_MASK(efx) & efx->phy_op->loopbacks)) |
505 | reg |= BMCR_ANRESTART; | 319 | reg |= MDIO_AN_CTRL1_RESTART; |
506 | if (xnp) | 320 | if (xnp) |
507 | reg |= 1 << MDIO_AN_CTRL_XNP_LBN; | 321 | reg |= MDIO_AN_CTRL1_XNP; |
508 | else | 322 | else |
509 | reg &= ~(1 << MDIO_AN_CTRL_XNP_LBN); | 323 | reg &= ~MDIO_AN_CTRL1_XNP; |
510 | mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, | 324 | efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg); |
511 | MDIO_MMDREG_CTRL1, reg); | ||
512 | } else { | 325 | } else { |
513 | /* Disable AN */ | 326 | /* Disable AN */ |
514 | mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN, | 327 | efx_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_CTRL1, |
515 | MDIO_MMDREG_CTRL1, | 328 | MDIO_AN_CTRL1_ENABLE, false); |
516 | __ffs(BMCR_ANENABLE), false); | ||
517 | 329 | ||
518 | /* Set the basic control bits */ | 330 | /* Set the basic control bits */ |
519 | reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, | 331 | reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1); |
520 | MDIO_MMDREG_CTRL1); | 332 | reg &= ~(MDIO_CTRL1_SPEEDSEL | MDIO_CTRL1_FULLDPLX); |
521 | reg &= ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX | | ||
522 | 0x003c); | ||
523 | if (ecmd->speed == SPEED_100) | 333 | if (ecmd->speed == SPEED_100) |
524 | reg |= BMCR_SPEED100; | 334 | reg |= MDIO_PMA_CTRL1_SPEED100; |
525 | if (ecmd->duplex) | 335 | if (ecmd->duplex) |
526 | reg |= BMCR_FULLDPLX; | 336 | reg |= MDIO_CTRL1_FULLDPLX; |
527 | mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, | 337 | efx_mdio_write(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1, reg); |
528 | MDIO_MMDREG_CTRL1, reg); | ||
529 | } | 338 | } |
530 | 339 | ||
531 | return 0; | 340 | return 0; |
532 | } | 341 | } |
533 | 342 | ||
534 | void mdio_clause45_set_pause(struct efx_nic *efx) | 343 | void efx_mdio_set_pause(struct efx_nic *efx) |
535 | { | 344 | { |
536 | int phy_id = efx->mii.phy_id; | ||
537 | int reg; | 345 | int reg; |
538 | 346 | ||
539 | if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) { | 347 | if (efx->phy_op->mmds & MDIO_DEVS_AN) { |
540 | /* Set pause capability advertising */ | 348 | /* Set pause capability advertising */ |
541 | reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, | 349 | reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE); |
542 | MDIO_AN_ADVERTISE); | ||
543 | reg &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); | 350 | reg &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); |
544 | reg |= efx_fc_advertise(efx->wanted_fc); | 351 | reg |= efx_fc_advertise(efx->wanted_fc); |
545 | mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, | 352 | efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg); |
546 | MDIO_AN_ADVERTISE, reg); | ||
547 | 353 | ||
548 | /* Restart auto-negotiation */ | 354 | /* Restart auto-negotiation */ |
549 | reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, | 355 | reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1); |
550 | MDIO_MMDREG_CTRL1); | 356 | if (reg & MDIO_AN_CTRL1_ENABLE) { |
551 | if (reg & BMCR_ANENABLE) { | 357 | reg |= MDIO_AN_CTRL1_RESTART; |
552 | reg |= BMCR_ANRESTART; | 358 | efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg); |
553 | mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, | ||
554 | MDIO_MMDREG_CTRL1, reg); | ||
555 | } | 359 | } |
556 | } | 360 | } |
557 | } | 361 | } |
558 | 362 | ||
559 | enum efx_fc_type mdio_clause45_get_pause(struct efx_nic *efx) | 363 | enum efx_fc_type efx_mdio_get_pause(struct efx_nic *efx) |
560 | { | 364 | { |
561 | int phy_id = efx->mii.phy_id; | ||
562 | int lpa; | 365 | int lpa; |
563 | 366 | ||
564 | if (!(efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN))) | 367 | if (!(efx->phy_op->mmds & MDIO_DEVS_AN)) |
565 | return efx->wanted_fc; | 368 | return efx->wanted_fc; |
566 | lpa = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, MDIO_AN_LPA); | 369 | lpa = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_LPA); |
567 | return efx_fc_resolve(efx->wanted_fc, lpa); | 370 | return efx_fc_resolve(efx->wanted_fc, lpa); |
568 | } | 371 | } |
569 | |||
570 | void mdio_clause45_set_flag(struct efx_nic *efx, u8 prt, u8 dev, | ||
571 | u16 addr, int bit, bool sense) | ||
572 | { | ||
573 | int old_val = mdio_clause45_read(efx, prt, dev, addr); | ||
574 | int new_val; | ||
575 | |||
576 | if (sense) | ||
577 | new_val = old_val | (1 << bit); | ||
578 | else | ||
579 | new_val = old_val & ~(1 << bit); | ||
580 | if (old_val != new_val) | ||
581 | mdio_clause45_write(efx, prt, dev, addr, new_val); | ||
582 | } | ||