blob: fcd1fee4d8967620da94d504620166f95fd10d46 [file] [log] [blame]
diff --git a/drivers/net/phy/aquantia.h b/drivers/net/phy/aquantia.h
index f46d95f..135b103 100644
--- a/drivers/net/phy/aquantia.h
+++ b/drivers/net/phy/aquantia.h
@@ -81,6 +81,8 @@ struct aqr107_priv {
int aqr107_set_downshift(struct phy_device *phydev, u8 cnt);
void aqr107_chip_info(struct phy_device *phydev);
int aqr107_config_mdi(struct phy_device *phydev);
+int aqr107_config_usx_aneg_en(struct phy_device *phydev);
+int aqr107_config_led(struct phy_device *phydev);
#if IS_REACHABLE(CONFIG_HWMON)
int aqr_hwmon_probe(struct phy_device *phydev);
diff --git a/drivers/net/phy/aquantia_firmware.c b/drivers/net/phy/aquantia_firmware.c
index b4ce32f..f37bee1 100644
--- a/drivers/net/phy/aquantia_firmware.c
+++ b/drivers/net/phy/aquantia_firmware.c
@@ -973,6 +973,14 @@ retry:
aqr107_chip_info(phydevs[i]);
+ ret = aqr107_config_usx_aneg_en(phydevs[i]);
+ if (ret)
+ dev_err(dev, "USX autonegotiation disabled, ret: %d\n", ret);
+
+ ret = aqr107_config_led(phydevs[i]);
+ if (ret)
+ dev_err(dev, "LED configuration failed, ret: %d\n", ret);
+
aqr107_config_mdi(phydevs[i]);
aqr107_set_downshift(phydevs[i],
diff --git a/drivers/net/phy/aquantia_main.c b/drivers/net/phy/aquantia_main.c
index e545b28..f445ef9 100644
--- a/drivers/net/phy/aquantia_main.c
+++ b/drivers/net/phy/aquantia_main.c
@@ -25,6 +25,7 @@
#define PHY_ID_AQCS109 0x03a1b5c2
#define PHY_ID_AQR405 0x03a1b4b0
#define PHY_ID_AQR113C 0x31c31c12
+#define PHY_ID_CUX3410 0x31c31dd3
#define MDIO_PHYXS_VEND_IF_STATUS 0xe812
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3)
@@ -34,6 +35,9 @@
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII 6
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII 10
+#define MDIO_PHYXS_TX_RSVD_VEND_PROV2 0xc441
+#define MDIO_PHYXS_TX_RSVD_VEND_PROV2_ANEG BIT(3)
+
#define MDIO_AN_VEND_PROV 0xc400
#define MDIO_AN_VEND_PROV_1000BASET_FULL BIT(15)
#define MDIO_AN_VEND_PROV_1000BASET_HALF BIT(14)
@@ -113,6 +117,16 @@
#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1)
#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0)
+#define VEND1_GLOBAL_LED_PROV(x) (0xc430 + (x - 1))
+#define VEND1_GLOBAL_LED_5000_LINK_EST BIT(15)
+#define VEND1_GLOBAL_LED_2500_LINK_EST BIT(14)
+#define VEND1_GLOBAL_LED_10G_LINK_EST BIT(7)
+#define VEND1_GLOBAL_LED_1000_LINK_EST BIT(6)
+#define VEND1_GLOBAL_LED_100_LINK_EST BIT(5)
+#define VEND1_GLOBAL_LED_PROV_RX_ACT BIT(3)
+#define VEND1_GLOBAL_LED_PROV_TX_ACT BIT(2)
+#define VEND1_GLOBAL_LED_PROV_ACT_STRETCH_MASK GENMASK(1, 0)
+
static int aqr107_get_sset_count(struct phy_device *phydev)
{
return AQR107_SGMII_STAT_SZ;
@@ -170,6 +184,40 @@ static void aqr107_get_stats(struct phy_device *phydev,
}
}
+int aqr107_config_led(struct phy_device *phydev)
+{
+ u16 val;
+ int err;
+
+ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_LED_PROV(1));
+ val |= VEND1_GLOBAL_LED_10G_LINK_EST;
+ err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_LED_PROV(1), val);
+ if (err < 0)
+ return err;
+
+ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_LED_PROV(2));
+ val |= VEND1_GLOBAL_LED_100_LINK_EST | VEND1_GLOBAL_LED_1000_LINK_EST |
+ VEND1_GLOBAL_LED_2500_LINK_EST | VEND1_GLOBAL_LED_5000_LINK_EST;
+ err = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_LED_PROV(2), val);
+ if (err < 0)
+ return err;
+
+ val = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_LED_PROV(3));
+ val |= VEND1_GLOBAL_LED_PROV_ACT_STRETCH_MASK |
+ VEND1_GLOBAL_LED_PROV_TX_ACT | VEND1_GLOBAL_LED_PROV_RX_ACT;
+ return phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_LED_PROV(3), val);
+}
+
+int aqr107_config_usx_aneg_en(struct phy_device *phydev)
+{
+ u16 val;
+
+ val = phy_read_mmd(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_TX_RSVD_VEND_PROV2);
+ val |= MDIO_PHYXS_TX_RSVD_VEND_PROV2_ANEG;
+
+ return phy_write_mmd(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_TX_RSVD_VEND_PROV2, val);
+}
+
static int aqr_config_aneg(struct phy_device *phydev)
{
bool changed = false;
@@ -483,6 +531,14 @@ static int aqr107_config_init(struct phy_device *phydev)
return aqr_firmware_download(phydev);
#endif
+ ret = aqr107_config_usx_aneg_en(phydev);
+ if (ret)
+ dev_err(&phydev->mdio.dev, "USX autonegotiation disabled, ret: %d\n", ret);
+
+ ret = aqr107_config_led(phydev);
+ if (ret)
+ dev_err(&phydev->mdio.dev, "LED configuration failed, ret: %d\n", ret);
+
aqr107_config_mdi(phydev);
return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT);
@@ -711,6 +767,24 @@ static struct phy_driver aqr_driver[] = {
.get_stats = aqr107_get_stats,
.link_change_notify = aqr107_link_change_notify,
},
+{
+ PHY_ID_MATCH_MODEL(PHY_ID_CUX3410),
+ .name = "Aquantia CUX3410",
+ .probe = aqr107_probe,
+ .config_init = aqr107_config_init,
+ .config_aneg = aqr_config_aneg,
+ .config_intr = aqr_config_intr,
+ .ack_interrupt = aqr_ack_interrupt,
+ .read_status = aqr107_read_status,
+ .get_tunable = aqr107_get_tunable,
+ .set_tunable = aqr107_set_tunable,
+ .suspend = aqr107_suspend,
+ .resume = aqr107_resume,
+ .get_sset_count = aqr107_get_sset_count,
+ .get_strings = aqr107_get_strings,
+ .get_stats = aqr107_get_stats,
+ .link_change_notify = aqr107_link_change_notify,
+},
};
module_phy_driver(aqr_driver);
@@ -724,6 +798,7 @@ static struct mdio_device_id __maybe_unused aqr_tbl[] = {
{ PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR405) },
{ PHY_ID_MATCH_MODEL(PHY_ID_AQR113C) },
+ { PHY_ID_MATCH_MODEL(PHY_ID_CUX3410) },
{ }
};