1 // SPDX-License-Identifier: GPL-2.0-only
2 /****************************************************************************
3 * Driver for Solarflare network controllers and boards
4 * Copyright 2006-2011 Solarflare Communications Inc.
7 * Useful functions for working with MDIO clause 45 PHYs
9 #include <linux/types.h>
10 #include <linux/ethtool.h>
11 #include <linux/delay.h>
12 #include "net_driver.h"
14 #include "workarounds.h"
16 unsigned ef4_mdio_id_oui(u32 id
)
21 /* The bits of the OUI are designated a..x, with a=0 and b variable.
22 * In the id register c is the MSB but the OUI is conventionally
23 * written as bytes h..a, p..i, x..q. Reorder the bits accordingly. */
24 for (i
= 0; i
< 22; ++i
)
25 if (id
& (1 << (i
+ 10)))
31 int ef4_mdio_reset_mmd(struct ef4_nic
*port
, int mmd
,
32 int spins
, int spintime
)
36 /* Catch callers passing values in the wrong units (or just silly) */
37 EF4_BUG_ON_PARANOID(spins
* spintime
>= 5000);
39 ef4_mdio_write(port
, mmd
, MDIO_CTRL1
, MDIO_CTRL1_RESET
);
40 /* Wait for the reset bit to clear. */
43 ctrl
= ef4_mdio_read(port
, mmd
, MDIO_CTRL1
);
46 } while (spins
&& (ctrl
& MDIO_CTRL1_RESET
));
48 return spins
? spins
: -ETIMEDOUT
;
51 static int ef4_mdio_check_mmd(struct ef4_nic
*efx
, int mmd
)
55 if (mmd
!= MDIO_MMD_AN
) {
56 /* Read MMD STATUS2 to check it is responding. */
57 status
= ef4_mdio_read(efx
, mmd
, MDIO_STAT2
);
58 if ((status
& MDIO_STAT2_DEVPRST
) != MDIO_STAT2_DEVPRST_VAL
) {
59 netif_err(efx
, hw
, efx
->net_dev
,
60 "PHY MMD %d not responding.\n", mmd
);
68 /* This ought to be ridiculous overkill. We expect it to fail rarely */
69 #define MDIO45_RESET_TIME 1000 /* ms */
70 #define MDIO45_RESET_ITERS 100
72 int ef4_mdio_wait_reset_mmds(struct ef4_nic
*efx
, unsigned int mmd_mask
)
74 const int spintime
= MDIO45_RESET_TIME
/ MDIO45_RESET_ITERS
;
75 int tries
= MDIO45_RESET_ITERS
;
86 stat
= ef4_mdio_read(efx
, mmd
, MDIO_CTRL1
);
88 netif_err(efx
, hw
, efx
->net_dev
,
89 "failed to read status of"
93 if (stat
& MDIO_CTRL1_RESET
)
94 in_reset
|= (1 << mmd
);
105 netif_err(efx
, hw
, efx
->net_dev
,
106 "not all MMDs came out of reset in time."
107 " MMDs still in reset: %x\n", in_reset
);
113 int ef4_mdio_check_mmds(struct ef4_nic
*efx
, unsigned int mmd_mask
)
115 int mmd
= 0, probe_mmd
, devs1
, devs2
;
118 /* Historically we have probed the PHYXS to find out what devices are
119 * present,but that doesn't work so well if the PHYXS isn't expected
120 * to exist, if so just find the first item in the list supplied. */
121 probe_mmd
= (mmd_mask
& MDIO_DEVS_PHYXS
) ? MDIO_MMD_PHYXS
:
124 /* Check all the expected MMDs are present */
125 devs1
= ef4_mdio_read(efx
, probe_mmd
, MDIO_DEVS1
);
126 devs2
= ef4_mdio_read(efx
, probe_mmd
, MDIO_DEVS2
);
127 if (devs1
< 0 || devs2
< 0) {
128 netif_err(efx
, hw
, efx
->net_dev
,
129 "failed to read devices present\n");
132 devices
= devs1
| (devs2
<< 16);
133 if ((devices
& mmd_mask
) != mmd_mask
) {
134 netif_err(efx
, hw
, efx
->net_dev
,
135 "required MMDs not present: got %x, wanted %x\n",
139 netif_vdbg(efx
, hw
, efx
->net_dev
, "Devices present: %x\n", devices
);
141 /* Check all required MMDs are responding and happy. */
143 if ((mmd_mask
& 1) && ef4_mdio_check_mmd(efx
, mmd
))
145 mmd_mask
= mmd_mask
>> 1;
152 bool ef4_mdio_links_ok(struct ef4_nic
*efx
, unsigned int mmd_mask
)
154 /* If the port is in loopback, then we should only consider a subset
156 if (LOOPBACK_INTERNAL(efx
))
158 else if (LOOPBACK_MASK(efx
) & LOOPBACKS_WS
)
160 else if (ef4_phy_mode_disabled(efx
->phy_mode
))
162 else if (efx
->loopback_mode
== LOOPBACK_PHYXS
)
163 mmd_mask
&= ~(MDIO_DEVS_PHYXS
|
167 else if (efx
->loopback_mode
== LOOPBACK_PCS
)
168 mmd_mask
&= ~(MDIO_DEVS_PCS
|
171 else if (efx
->loopback_mode
== LOOPBACK_PMAPMD
)
172 mmd_mask
&= ~(MDIO_DEVS_PMAPMD
|
175 return mdio45_links_ok(&efx
->mdio
, mmd_mask
);
178 void ef4_mdio_transmit_disable(struct ef4_nic
*efx
)
180 ef4_mdio_set_flag(efx
, MDIO_MMD_PMAPMD
,
181 MDIO_PMA_TXDIS
, MDIO_PMD_TXDIS_GLOBAL
,
182 efx
->phy_mode
& PHY_MODE_TX_DISABLED
);
185 void ef4_mdio_phy_reconfigure(struct ef4_nic
*efx
)
187 ef4_mdio_set_flag(efx
, MDIO_MMD_PMAPMD
,
188 MDIO_CTRL1
, MDIO_PMA_CTRL1_LOOPBACK
,
189 efx
->loopback_mode
== LOOPBACK_PMAPMD
);
190 ef4_mdio_set_flag(efx
, MDIO_MMD_PCS
,
191 MDIO_CTRL1
, MDIO_PCS_CTRL1_LOOPBACK
,
192 efx
->loopback_mode
== LOOPBACK_PCS
);
193 ef4_mdio_set_flag(efx
, MDIO_MMD_PHYXS
,
194 MDIO_CTRL1
, MDIO_PHYXS_CTRL1_LOOPBACK
,
195 efx
->loopback_mode
== LOOPBACK_PHYXS_WS
);
198 static void ef4_mdio_set_mmd_lpower(struct ef4_nic
*efx
,
201 int stat
= ef4_mdio_read(efx
, mmd
, MDIO_STAT1
);
203 netif_vdbg(efx
, drv
, efx
->net_dev
, "Setting low power mode for MMD %d to %d\n",
206 if (stat
& MDIO_STAT1_LPOWERABLE
) {
207 ef4_mdio_set_flag(efx
, mmd
, MDIO_CTRL1
,
208 MDIO_CTRL1_LPOWER
, lpower
);
212 void ef4_mdio_set_mmds_lpower(struct ef4_nic
*efx
,
213 int low_power
, unsigned int mmd_mask
)
216 mmd_mask
&= ~MDIO_DEVS_AN
;
219 ef4_mdio_set_mmd_lpower(efx
, low_power
, mmd
);
220 mmd_mask
= (mmd_mask
>> 1);
226 * ef4_mdio_set_link_ksettings - Set (some of) the PHY settings over MDIO.
230 int ef4_mdio_set_link_ksettings(struct ef4_nic
*efx
,
231 const struct ethtool_link_ksettings
*cmd
)
233 struct ethtool_link_ksettings prev
= {
234 .base
.cmd
= ETHTOOL_GLINKSETTINGS
236 u32 prev_advertising
, advertising
;
239 efx
->phy_op
->get_link_ksettings(efx
, &prev
);
241 ethtool_convert_link_mode_to_legacy_u32(&advertising
,
242 cmd
->link_modes
.advertising
);
243 ethtool_convert_link_mode_to_legacy_u32(&prev_advertising
,
244 prev
.link_modes
.advertising
);
245 ethtool_convert_link_mode_to_legacy_u32(&prev_supported
,
246 prev
.link_modes
.supported
);
248 if (advertising
== prev_advertising
&&
249 cmd
->base
.speed
== prev
.base
.speed
&&
250 cmd
->base
.duplex
== prev
.base
.duplex
&&
251 cmd
->base
.port
== prev
.base
.port
&&
252 cmd
->base
.autoneg
== prev
.base
.autoneg
)
255 /* We can only change these settings for -T PHYs */
256 if (prev
.base
.port
!= PORT_TP
|| cmd
->base
.port
!= PORT_TP
)
259 /* Check that PHY supports these settings */
260 if (!cmd
->base
.autoneg
||
261 (advertising
| SUPPORTED_Autoneg
) & ~prev_supported
)
264 ef4_link_set_advertising(efx
, advertising
| ADVERTISED_Autoneg
);
265 ef4_mdio_an_reconfigure(efx
);
270 * ef4_mdio_an_reconfigure - Push advertising flags and restart autonegotiation
273 void ef4_mdio_an_reconfigure(struct ef4_nic
*efx
)
277 WARN_ON(!(efx
->mdio
.mmds
& MDIO_DEVS_AN
));
279 /* Set up the base page */
280 reg
= ADVERTISE_CSMA
| ADVERTISE_RESV
;
281 if (efx
->link_advertising
& ADVERTISED_Pause
)
282 reg
|= ADVERTISE_PAUSE_CAP
;
283 if (efx
->link_advertising
& ADVERTISED_Asym_Pause
)
284 reg
|= ADVERTISE_PAUSE_ASYM
;
285 ef4_mdio_write(efx
, MDIO_MMD_AN
, MDIO_AN_ADVERTISE
, reg
);
287 /* Set up the (extended) next page */
288 efx
->phy_op
->set_npage_adv(efx
, efx
->link_advertising
);
290 /* Enable and restart AN */
291 reg
= ef4_mdio_read(efx
, MDIO_MMD_AN
, MDIO_CTRL1
);
292 reg
|= MDIO_AN_CTRL1_ENABLE
| MDIO_AN_CTRL1_RESTART
| MDIO_AN_CTRL1_XNP
;
293 ef4_mdio_write(efx
, MDIO_MMD_AN
, MDIO_CTRL1
, reg
);
296 u8
ef4_mdio_get_pause(struct ef4_nic
*efx
)
298 BUILD_BUG_ON(EF4_FC_AUTO
& (EF4_FC_RX
| EF4_FC_TX
));
300 if (!(efx
->wanted_fc
& EF4_FC_AUTO
))
301 return efx
->wanted_fc
;
303 WARN_ON(!(efx
->mdio
.mmds
& MDIO_DEVS_AN
));
305 return mii_resolve_flowctrl_fdx(
306 mii_advertise_flowctrl(efx
->wanted_fc
),
307 ef4_mdio_read(efx
, MDIO_MMD_AN
, MDIO_AN_LPA
));
310 int ef4_mdio_test_alive(struct ef4_nic
*efx
)
313 int devad
= __ffs(efx
->mdio
.mmds
);
314 u16 physid1
, physid2
;
316 mutex_lock(&efx
->mac_lock
);
318 physid1
= ef4_mdio_read(efx
, devad
, MDIO_DEVID1
);
319 physid2
= ef4_mdio_read(efx
, devad
, MDIO_DEVID2
);
321 if ((physid1
== 0x0000) || (physid1
== 0xffff) ||
322 (physid2
== 0x0000) || (physid2
== 0xffff)) {
323 netif_err(efx
, hw
, efx
->net_dev
,
324 "no MDIO PHY present with ID %d\n", efx
->mdio
.prtad
);
327 rc
= ef4_mdio_check_mmds(efx
, efx
->mdio
.mmds
);
330 mutex_unlock(&efx
->mac_lock
);