With SGMII, the MAC and the PHY can negotiate the link speed between
themselves, without the host needing to mediate between them.
Linux recognises this, and will call phylink's mac_config with the speed
member set to SPEED_UNKNOWN (-1).
Currently the axienet driver will bail out and complain about an
unsupported link speed.
Teach axienet's mac_config callback to leave the MAC's speed setting
alone if the requested speed is SPEED_UNKNOWN.
This fixes axienet operation when the hardware is using SGMII.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
.../net/ethernet/xilinx/xilinx_axienet_main.c | 21 ++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 8d2b67cbecf9..e83c7b005f50 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -1512,20 +1512,21 @@ static void axienet_mac_config(struct phylink_config *config, unsigned int mode,
{
struct net_device *ndev = to_net_dev(config->dev);
struct axienet_local *lp = netdev_priv(ndev);
- u32 emmc_reg, fcc_reg;
+ u32 fcc_reg, speed_reg = ~0;
- emmc_reg = axienet_ior(lp, XAE_EMMC_OFFSET);
- emmc_reg &= ~XAE_EMMC_LINKSPEED_MASK;
switch (state->speed) {
+ case SPEED_UNKNOWN:
+ /* Keep the current MAC speed setting. Used for SGMII. */
+ break;
case SPEED_1000:
- emmc_reg |= XAE_EMMC_LINKSPD_1000;
+ speed_reg = XAE_EMMC_LINKSPD_1000;
break;
case SPEED_100:
- emmc_reg |= XAE_EMMC_LINKSPD_100;
+ speed_reg = XAE_EMMC_LINKSPD_100;
break;
case SPEED_10:
- emmc_reg |= XAE_EMMC_LINKSPD_10;
+ speed_reg = XAE_EMMC_LINKSPD_10;
break;
default:
dev_err(&ndev->dev,@@ -1533,7 +1534,13 @@ static void axienet_mac_config(struct phylink_config *config, unsigned int mode,
break;
}
- axienet_iow(lp, XAE_EMMC_OFFSET, emmc_reg);
+ if (speed_reg != ~0) {
+ u32 emmc_reg = axienet_ior(lp, XAE_EMMC_OFFSET);
+
+ emmc_reg &= ~XAE_EMMC_LINKSPEED_MASK;
+ emmc_reg |= speed_reg;
+ axienet_iow(lp, XAE_EMMC_OFFSET, emmc_reg);
+ }
fcc_reg = axienet_ior(lp, XAE_FCC_OFFSET);
if (state->pause & MLO_PAUSE_TX)--
2.17.1