This patch series add the qca8081 ethernet phy driver support, which
improve the wol feature, leverage at803x phy driver and add the fast
retrain, master/slave seed and CDT feature.
Changes in v7:
* update Reviewed-by tags.
Changes in v6:
* add Reviewed-by tags on the applicable patches.
Changes in v5:
* rebase the patches on net-next/master.
Changes in v4:
* handle other interrupts in set_wol.
* add genphy_c45_fast_retrain.
Changes in v3:
* correct a typo "excpet".
* remove the suffix "PHY" from phy name.
Changes in v2:
* add definitions of fast retrain related registers in mdio.h.
* break up the patch into small patches.
* improve the at803x legacy code.
Changes in v1:
* merge qca8081 phy driver into at803x.
* add cdt feature.
* leverage at803x phy driver helpers.
Luo Jie (14):
net: phy: at803x: replace AT803X_DEVICE_ADDR with MDIO_MMD_PCS
net: phy: at803x: use phy_modify()
net: phy: at803x: improve the WOL feature
net: phy: at803x: use GENMASK() for speed status
net: phy: add qca8081 ethernet phy driver
net: phy: add qca8081 read_status
net: phy: add qca8081 get_features
net: phy: add qca8081 config_aneg
net: phy: add constants for fast retrain related register
net: phy: add genphy_c45_fast_retrain
net: phy: add qca8081 config_init
net: phy: add qca8081 soft_reset and enable master/slave seed
net: phy: adjust qca8081 master/slave seed value if link down
net: phy: add qca8081 cdt feature
drivers/net/phy/at803x.c | 580 +++++++++++++++++++++++++++++++++++---
drivers/net/phy/phy-c45.c | 34 +++
include/linux/phy.h | 1 +
include/uapi/linux/mdio.h | 9 +
4 files changed, 577 insertions(+), 47 deletions(-)
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
Add the constants for 2.5G fast retrain capability
in 10G AN control register, fast retrain status and
control register and THP bypass register into mdio.h.
Signed-off-by: Luo Jie <[email protected]>
---
include/uapi/linux/mdio.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/include/uapi/linux/mdio.h b/include/uapi/linux/mdio.h
index bdf77dffa5a4..c54e6eae5366 100644
--- a/include/uapi/linux/mdio.h
+++ b/include/uapi/linux/mdio.h
@@ -53,12 +53,14 @@
#define MDIO_AN_EEE_LPABLE 61 /* EEE link partner ability */
#define MDIO_AN_EEE_ADV2 62 /* EEE advertisement 2 */
#define MDIO_AN_EEE_LPABLE2 63 /* EEE link partner ability 2 */
+#define MDIO_AN_CTRL2 64 /* AN THP bypass request control */
/* Media-dependent registers. */
#define MDIO_PMA_10GBT_SWAPPOL 130 /* 10GBASE-T pair swap & polarity */
#define MDIO_PMA_10GBT_TXPWR 131 /* 10GBASE-T TX power control */
#define MDIO_PMA_10GBT_SNR 133 /* 10GBASE-T SNR margin, lane A.
* Lanes B-D are numbered 134-136. */
+#define MDIO_PMA_10GBR_FSRT_CSR 147 /* 10GBASE-R fast retrain status and control */
#define MDIO_PMA_10GBR_FECABLE 170 /* 10GBASE-R FEC ability */
#define MDIO_PCS_10GBX_STAT1 24 /* 10GBASE-X PCS status 1 */
#define MDIO_PCS_10GBRT_STAT1 32 /* 10GBASE-R/-T PCS status 1 */
@@ -239,6 +241,9 @@
#define MDIO_PMA_10GBR_FECABLE_ABLE 0x0001 /* FEC ability */
#define MDIO_PMA_10GBR_FECABLE_ERRABLE 0x0002 /* FEC error indic. ability */
+/* PMA 10GBASE-R Fast Retrain status and control register. */
+#define MDIO_PMA_10GBR_FSRT_ENABLE 0x0001 /* Fast retrain enable */
+
/* PCS 10GBASE-R/-T status register 1. */
#define MDIO_PCS_10GBRT_STAT1_BLKLK 0x0001 /* Block lock attained */
@@ -247,6 +252,7 @@
#define MDIO_PCS_10GBRT_STAT2_BER 0x3f00
/* AN 10GBASE-T control register. */
+#define MDIO_AN_10GBT_CTRL_ADVFSRT2_5G 0x0020 /* Advertise 2.5GBASE-T fast retrain */
#define MDIO_AN_10GBT_CTRL_ADV2_5G 0x0080 /* Advertise 2.5GBASE-T */
#define MDIO_AN_10GBT_CTRL_ADV5G 0x0100 /* Advertise 5GBASE-T */
#define MDIO_AN_10GBT_CTRL_ADV10G 0x1000 /* Advertise 10GBASE-T */
@@ -289,6 +295,9 @@
#define MDIO_EEE_2_5GT 0x0001 /* 2.5GT EEE cap */
#define MDIO_EEE_5GT 0x0002 /* 5GT EEE cap */
+/* AN MultiGBASE-T AN control 2 */
+#define MDIO_AN_THP_BP2_5GT 0x0008 /* 2.5GT THP bypass request */
+
/* 2.5G/5G Extended abilities register. */
#define MDIO_PMA_NG_EXTABLE_2_5GBT 0x0001 /* 2.5GBASET ability */
#define MDIO_PMA_NG_EXTABLE_5GBT 0x0002 /* 5GBASET ability */
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
Add generic fast retrain auto-negotiation function for C45 PHYs.
Signed-off-by: Luo Jie <[email protected]>
---
drivers/net/phy/phy-c45.c | 34 ++++++++++++++++++++++++++++++++++
include/linux/phy.h | 1 +
2 files changed, 35 insertions(+)
diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
index c617dbcad6ea..b01180e1f578 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -611,6 +611,40 @@ int genphy_c45_loopback(struct phy_device *phydev, bool enable)
}
EXPORT_SYMBOL_GPL(genphy_c45_loopback);
+/**
+ * genphy_c45_fast_retrain - configure fast retrain registers
+ * @phydev: target phy_device struct
+ *
+ * Description: If fast-retrain is enabled, we configure PHY as
+ * advertising fast retrain capable and THP Bypass Request, then
+ * enable fast retrain. If it is not enabled, we configure fast
+ * retrain disabled.
+ */
+int genphy_c45_fast_retrain(struct phy_device *phydev, bool enable)
+{
+ int ret;
+
+ if (!enable)
+ return phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FSRT_CSR,
+ MDIO_PMA_10GBR_FSRT_ENABLE);
+
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported)) {
+ ret = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
+ MDIO_AN_10GBT_CTRL_ADVFSRT2_5G);
+ if (ret)
+ return ret;
+
+ ret = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MDIO_AN_CTRL2,
+ MDIO_AN_THP_BP2_5GT);
+ if (ret)
+ return ret;
+ }
+
+ return phy_set_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FSRT_CSR,
+ MDIO_PMA_10GBR_FSRT_ENABLE);
+}
+EXPORT_SYMBOL_GPL(genphy_c45_fast_retrain);
+
struct phy_driver genphy_c45_driver = {
.phy_id = 0xffffffff,
.phy_id_mask = 0xffffffff,
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 736e1d1a47c4..04e90423fa88 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1584,6 +1584,7 @@ int genphy_c45_config_aneg(struct phy_device *phydev);
int genphy_c45_loopback(struct phy_device *phydev, bool enable);
int genphy_c45_pma_resume(struct phy_device *phydev);
int genphy_c45_pma_suspend(struct phy_device *phydev);
+int genphy_c45_fast_retrain(struct phy_device *phydev, bool enable);
/* Generic C45 PHY driver */
extern struct phy_driver genphy_c45_driver;
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
Use GENMASK() for the current speed value.
Signed-off-by: Luo Jie <[email protected]>
Reviewed-by: Andrew Lunn <[email protected]>
---
drivers/net/phy/at803x.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 1363f12ba659..3465f2bb6356 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -33,10 +33,10 @@
#define AT803X_SFC_DISABLE_JABBER BIT(0)
#define AT803X_SPECIFIC_STATUS 0x11
-#define AT803X_SS_SPEED_MASK (3 << 14)
-#define AT803X_SS_SPEED_1000 (2 << 14)
-#define AT803X_SS_SPEED_100 (1 << 14)
-#define AT803X_SS_SPEED_10 (0 << 14)
+#define AT803X_SS_SPEED_MASK GENMASK(15, 14)
+#define AT803X_SS_SPEED_1000 2
+#define AT803X_SS_SPEED_100 1
+#define AT803X_SS_SPEED_10 0
#define AT803X_SS_DUPLEX BIT(13)
#define AT803X_SS_SPEED_DUPLEX_RESOLVED BIT(11)
#define AT803X_SS_MDIX BIT(6)
@@ -994,7 +994,7 @@ static int at803x_read_status(struct phy_device *phydev)
if (sfc < 0)
return sfc;
- switch (ss & AT803X_SS_SPEED_MASK) {
+ switch (FIELD_GET(AT803X_SS_SPEED_MASK, ss)) {
case AT803X_SS_SPEED_10:
phydev->speed = SPEED_10;
break;
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
1. The master/slave seed needs to be updated when the link can't
be created.
2. The case where two qca8081 PHYs are connected each other and
master/slave seed is generated as the same value also needs
to be considered, so adding this code change into read_status
instead of link_change_notify.
Signed-off-by: Luo Jie <[email protected]>
---
drivers/net/phy/at803x.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 1418db4f2091..00733badcda5 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -1655,6 +1655,22 @@ static int qca808x_read_status(struct phy_device *phydev)
else
phydev->interface = PHY_INTERFACE_MODE_SMII;
+ /* generate seed as a lower random value to make PHY linked as SLAVE easily,
+ * except for master/slave configuration fault detected.
+ * the reason for not putting this code into the function link_change_notify is
+ * the corner case where the link partner is also the qca8081 PHY and the seed
+ * value is configured as the same value, the link can't be up and no link change
+ * occurs.
+ */
+ if (!phydev->link) {
+ if (phydev->master_slave_state == MASTER_SLAVE_STATE_ERR) {
+ qca808x_phy_ms_seed_enable(phydev, false);
+ } else {
+ qca808x_phy_ms_random_seed_set(phydev);
+ qca808x_phy_ms_seed_enable(phydev, true);
+ }
+ }
+
return 0;
}
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
qca8081 phy is a single port phy, configure
phy the lower seed value to make it linked as slave
mode easier.
Signed-off-by: Luo Jie <[email protected]>
---
drivers/net/phy/at803x.c | 48 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index da710523b7c4..1418db4f2091 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -223,6 +223,12 @@
#define QCA808X_PHY_MMD3_DEBUG_6 0xa011
#define QCA808X_MMD3_DEBUG_6_VALUE 0x5f85
+/* master/slave seed config */
+#define QCA808X_PHY_DEBUG_LOCAL_SEED 9
+#define QCA808X_MASTER_SLAVE_SEED_ENABLE BIT(1)
+#define QCA808X_MASTER_SLAVE_SEED_CFG GENMASK(12, 2)
+#define QCA808X_MASTER_SLAVE_SEED_RANGE 0x32
+
MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver");
MODULE_AUTHOR("Matus Ujhelyi");
MODULE_LICENSE("GPL");
@@ -1569,6 +1575,26 @@ static int qca808x_phy_fast_retrain_config(struct phy_device *phydev)
return 0;
}
+static int qca808x_phy_ms_random_seed_set(struct phy_device *phydev)
+{
+ u16 seed_value = (prandom_u32() % QCA808X_MASTER_SLAVE_SEED_RANGE);
+
+ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED,
+ QCA808X_MASTER_SLAVE_SEED_CFG,
+ FIELD_PREP(QCA808X_MASTER_SLAVE_SEED_CFG, seed_value));
+}
+
+static int qca808x_phy_ms_seed_enable(struct phy_device *phydev, bool enable)
+{
+ u16 seed_enable = 0;
+
+ if (enable)
+ seed_enable = QCA808X_MASTER_SLAVE_SEED_ENABLE;
+
+ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_LOCAL_SEED,
+ QCA808X_MASTER_SLAVE_SEED_ENABLE, seed_enable);
+}
+
static int qca808x_config_init(struct phy_device *phydev)
{
int ret;
@@ -1590,6 +1616,16 @@ static int qca808x_config_init(struct phy_device *phydev)
if (ret)
return ret;
+ /* Configure lower ramdom seed to make phy linked as slave mode */
+ ret = qca808x_phy_ms_random_seed_set(phydev);
+ if (ret)
+ return ret;
+
+ /* Enable seed */
+ ret = qca808x_phy_ms_seed_enable(phydev, true);
+ if (ret)
+ return ret;
+
/* Configure adc threshold as 100mv for the link 10M */
return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD,
QCA808X_ADC_THRESHOLD_MASK, QCA808X_ADC_THRESHOLD_100MV);
@@ -1622,6 +1658,17 @@ static int qca808x_read_status(struct phy_device *phydev)
return 0;
}
+static int qca808x_soft_reset(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = genphy_soft_reset(phydev);
+ if (ret < 0)
+ return ret;
+
+ return qca808x_phy_ms_seed_enable(phydev, true);
+}
+
static struct phy_driver at803x_driver[] = {
{
/* Qualcomm Atheros AR8035 */
@@ -1797,6 +1844,7 @@ static struct phy_driver at803x_driver[] = {
.resume = genphy_resume,
.read_status = qca808x_read_status,
.config_init = qca808x_config_init,
+ .soft_reset = qca808x_soft_reset,
}, };
module_phy_driver(at803x_driver);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
Reuse at803x phy driver config_aneg excepting
adding 2500M auto-negotiation.
Signed-off-by: Luo Jie <[email protected]>
---
drivers/net/phy/at803x.c | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index c4b7ac03cd35..70c1025e8e5d 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -1109,7 +1109,30 @@ static int at803x_config_aneg(struct phy_device *phydev)
return ret;
}
- return genphy_config_aneg(phydev);
+ /* Do not restart auto-negotiation by setting ret to 0 defautly,
+ * when calling __genphy_config_aneg later.
+ */
+ ret = 0;
+
+ if (phydev->drv->phy_id == QCA8081_PHY_ID) {
+ int phy_ctrl = 0;
+
+ /* The reg MII_BMCR also needs to be configured for force mode, the
+ * genphy_config_aneg is also needed.
+ */
+ if (phydev->autoneg == AUTONEG_DISABLE)
+ genphy_c45_pma_setup_forced(phydev);
+
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->advertising))
+ phy_ctrl = MDIO_AN_10GBT_CTRL_ADV2_5G;
+
+ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
+ MDIO_AN_10GBT_CTRL_ADV2_5G, phy_ctrl);
+ if (ret < 0)
+ return ret;
+ }
+
+ return __genphy_config_aneg(phydev, ret);
}
static int at803x_get_downshift(struct phy_device *phydev, u8 *d)
@@ -1663,6 +1686,7 @@ static struct phy_driver at803x_driver[] = {
.set_wol = at803x_set_wol,
.get_wol = at803x_get_wol,
.get_features = at803x_get_features,
+ .config_aneg = at803x_config_aneg,
.suspend = genphy_suspend,
.resume = genphy_resume,
.read_status = qca808x_read_status,
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
Add the qca8081 phy driver config_init function, which includes:
1. Enable fast restrain.
2. Add 802.3az configurations.
3. Initialize ADC threshold as 100mv.
Signed-off-by: Luo Jie <[email protected]>
---
drivers/net/phy/at803x.c | 107 +++++++++++++++++++++++++++++++++++++++
1 file changed, 107 insertions(+)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 70c1025e8e5d..da710523b7c4 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -178,6 +178,51 @@
#define AT803X_KEEP_PLL_ENABLED BIT(0)
#define AT803X_DISABLE_SMARTEEE BIT(1)
+/* ADC threshold */
+#define QCA808X_PHY_DEBUG_ADC_THRESHOLD 0x2c80
+#define QCA808X_ADC_THRESHOLD_MASK GENMASK(7, 0)
+#define QCA808X_ADC_THRESHOLD_80MV 0
+#define QCA808X_ADC_THRESHOLD_100MV 0xf0
+#define QCA808X_ADC_THRESHOLD_200MV 0x0f
+#define QCA808X_ADC_THRESHOLD_300MV 0xff
+
+/* CLD control */
+#define QCA808X_PHY_MMD3_ADDR_CLD_CTRL7 0x8007
+#define QCA808X_8023AZ_AFE_CTRL_MASK GENMASK(8, 4)
+#define QCA808X_8023AZ_AFE_EN 0x90
+
+/* AZ control */
+#define QCA808X_PHY_MMD3_AZ_TRAINING_CTRL 0x8008
+#define QCA808X_MMD3_AZ_TRAINING_VAL 0x1c32
+
+#define QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB 0x8014
+#define QCA808X_MSE_THRESHOLD_20DB_VALUE 0x529
+
+#define QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB 0x800E
+#define QCA808X_MSE_THRESHOLD_17DB_VALUE 0x341
+
+#define QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB 0x801E
+#define QCA808X_MSE_THRESHOLD_27DB_VALUE 0x419
+
+#define QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB 0x8020
+#define QCA808X_MSE_THRESHOLD_28DB_VALUE 0x341
+
+#define QCA808X_PHY_MMD7_TOP_OPTION1 0x901c
+#define QCA808X_TOP_OPTION1_DATA 0x0
+
+#define QCA808X_PHY_MMD3_DEBUG_1 0xa100
+#define QCA808X_MMD3_DEBUG_1_VALUE 0x9203
+#define QCA808X_PHY_MMD3_DEBUG_2 0xa101
+#define QCA808X_MMD3_DEBUG_2_VALUE 0x48ad
+#define QCA808X_PHY_MMD3_DEBUG_3 0xa103
+#define QCA808X_MMD3_DEBUG_3_VALUE 0x1698
+#define QCA808X_PHY_MMD3_DEBUG_4 0xa105
+#define QCA808X_MMD3_DEBUG_4_VALUE 0x8001
+#define QCA808X_PHY_MMD3_DEBUG_5 0xa106
+#define QCA808X_MMD3_DEBUG_5_VALUE 0x1111
+#define QCA808X_PHY_MMD3_DEBUG_6 0xa011
+#define QCA808X_MMD3_DEBUG_6_VALUE 0x5f85
+
MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver");
MODULE_AUTHOR("Matus Ujhelyi");
MODULE_LICENSE("GPL");
@@ -1489,6 +1534,67 @@ static int qca83xx_suspend(struct phy_device *phydev)
return 0;
}
+static int qca808x_phy_fast_retrain_config(struct phy_device *phydev)
+{
+ int ret;
+
+ /* Enable fast retrain */
+ ret = genphy_c45_fast_retrain(phydev, true);
+ if (ret)
+ return ret;
+
+ phy_write_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_TOP_OPTION1,
+ QCA808X_TOP_OPTION1_DATA);
+ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_20DB,
+ QCA808X_MSE_THRESHOLD_20DB_VALUE);
+ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_17DB,
+ QCA808X_MSE_THRESHOLD_17DB_VALUE);
+ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_27DB,
+ QCA808X_MSE_THRESHOLD_27DB_VALUE);
+ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, QCA808X_PHY_MMD1_MSE_THRESHOLD_28DB,
+ QCA808X_MSE_THRESHOLD_28DB_VALUE);
+ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_1,
+ QCA808X_MMD3_DEBUG_1_VALUE);
+ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_4,
+ QCA808X_MMD3_DEBUG_4_VALUE);
+ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_5,
+ QCA808X_MMD3_DEBUG_5_VALUE);
+ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_3,
+ QCA808X_MMD3_DEBUG_3_VALUE);
+ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_6,
+ QCA808X_MMD3_DEBUG_6_VALUE);
+ phy_write_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_DEBUG_2,
+ QCA808X_MMD3_DEBUG_2_VALUE);
+
+ return 0;
+}
+
+static int qca808x_config_init(struct phy_device *phydev)
+{
+ int ret;
+
+ /* Active adc&vga on 802.3az for the link 1000M and 100M */
+ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, QCA808X_PHY_MMD3_ADDR_CLD_CTRL7,
+ QCA808X_8023AZ_AFE_CTRL_MASK, QCA808X_8023AZ_AFE_EN);
+ if (ret)
+ return ret;
+
+ /* Adjust the threshold on 802.3az for the link 1000M */
+ ret = phy_write_mmd(phydev, MDIO_MMD_PCS,
+ QCA808X_PHY_MMD3_AZ_TRAINING_CTRL, QCA808X_MMD3_AZ_TRAINING_VAL);
+ if (ret)
+ return ret;
+
+ /* Config the fast retrain for the link 2500M */
+ ret = qca808x_phy_fast_retrain_config(phydev);
+ if (ret)
+ return ret;
+
+ /* Configure adc threshold as 100mv for the link 10M */
+ return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD,
+ QCA808X_ADC_THRESHOLD_MASK, QCA808X_ADC_THRESHOLD_100MV);
+}
+
static int qca808x_read_status(struct phy_device *phydev)
{
int ret;
@@ -1690,6 +1796,7 @@ static struct phy_driver at803x_driver[] = {
.suspend = genphy_suspend,
.resume = genphy_resume,
.read_status = qca808x_read_status,
+ .config_init = qca808x_config_init,
}, };
module_phy_driver(at803x_driver);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
To perform CDT of qca8081 phy:
1. disable hibernation.
2. force phy working in MDI mode.
3. force phy working in 1000BASE-T mode.
4. configure the related thresholds.
Signed-off-by: Luo Jie <[email protected]>
---
drivers/net/phy/at803x.c | 194 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 191 insertions(+), 3 deletions(-)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 00733badcda5..f1cbe1f6ddec 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -229,6 +229,32 @@
#define QCA808X_MASTER_SLAVE_SEED_CFG GENMASK(12, 2)
#define QCA808X_MASTER_SLAVE_SEED_RANGE 0x32
+/* Hibernation yields lower power consumpiton in contrast with normal operation mode.
+ * when the copper cable is unplugged, the PHY enters into hibernation mode in about 10s.
+ */
+#define QCA808X_DBG_AN_TEST 0xb
+#define QCA808X_HIBERNATION_EN BIT(15)
+
+#define QCA808X_CDT_ENABLE_TEST BIT(15)
+#define QCA808X_CDT_INTER_CHECK_DIS BIT(13)
+#define QCA808X_CDT_LENGTH_UNIT BIT(10)
+
+#define QCA808X_MMD3_CDT_STATUS 0x8064
+#define QCA808X_MMD3_CDT_DIAG_PAIR_A 0x8065
+#define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066
+#define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067
+#define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068
+#define QCA808X_CDT_DIAG_LENGTH GENMASK(7, 0)
+
+#define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12)
+#define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8)
+#define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4)
+#define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0)
+#define QCA808X_CDT_STATUS_STAT_FAIL 0
+#define QCA808X_CDT_STATUS_STAT_NORMAL 1
+#define QCA808X_CDT_STATUS_STAT_OPEN 2
+#define QCA808X_CDT_STATUS_STAT_SHORT 3
+
MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver");
MODULE_AUTHOR("Matus Ujhelyi");
MODULE_LICENSE("GPL");
@@ -1319,8 +1345,14 @@ static int at803x_cdt_start(struct phy_device *phydev, int pair)
{
u16 cdt;
- cdt = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) |
- AT803X_CDT_ENABLE_TEST;
+ /* qca8081 takes the different bit 15 to enable CDT test */
+ if (phydev->drv->phy_id == QCA8081_PHY_ID)
+ cdt = QCA808X_CDT_ENABLE_TEST |
+ QCA808X_CDT_LENGTH_UNIT |
+ QCA808X_CDT_INTER_CHECK_DIS;
+ else
+ cdt = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) |
+ AT803X_CDT_ENABLE_TEST;
return phy_write(phydev, AT803X_CDT, cdt);
}
@@ -1328,10 +1360,16 @@ static int at803x_cdt_start(struct phy_device *phydev, int pair)
static int at803x_cdt_wait_for_completion(struct phy_device *phydev)
{
int val, ret;
+ u16 cdt_en;
+
+ if (phydev->drv->phy_id == QCA8081_PHY_ID)
+ cdt_en = QCA808X_CDT_ENABLE_TEST;
+ else
+ cdt_en = AT803X_CDT_ENABLE_TEST;
/* One test run takes about 25ms */
ret = phy_read_poll_timeout(phydev, AT803X_CDT, val,
- !(val & AT803X_CDT_ENABLE_TEST),
+ !(val & cdt_en),
30000, 100000, true);
return ret < 0 ? ret : 0;
@@ -1685,6 +1723,153 @@ static int qca808x_soft_reset(struct phy_device *phydev)
return qca808x_phy_ms_seed_enable(phydev, true);
}
+static bool qca808x_cdt_fault_length_valid(int cdt_code)
+{
+ switch (cdt_code) {
+ case QCA808X_CDT_STATUS_STAT_SHORT:
+ case QCA808X_CDT_STATUS_STAT_OPEN:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static int qca808x_cable_test_result_trans(int cdt_code)
+{
+ switch (cdt_code) {
+ case QCA808X_CDT_STATUS_STAT_NORMAL:
+ return ETHTOOL_A_CABLE_RESULT_CODE_OK;
+ case QCA808X_CDT_STATUS_STAT_SHORT:
+ return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT;
+ case QCA808X_CDT_STATUS_STAT_OPEN:
+ return ETHTOOL_A_CABLE_RESULT_CODE_OPEN;
+ case QCA808X_CDT_STATUS_STAT_FAIL:
+ default:
+ return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC;
+ }
+}
+
+static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair)
+{
+ int val;
+ u32 cdt_length_reg = 0;
+
+ switch (pair) {
+ case ETHTOOL_A_CABLE_PAIR_A:
+ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_A;
+ break;
+ case ETHTOOL_A_CABLE_PAIR_B:
+ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_B;
+ break;
+ case ETHTOOL_A_CABLE_PAIR_C:
+ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_C;
+ break;
+ case ETHTOOL_A_CABLE_PAIR_D:
+ cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_D;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ val = phy_read_mmd(phydev, MDIO_MMD_PCS, cdt_length_reg);
+ if (val < 0)
+ return val;
+
+ return (FIELD_GET(QCA808X_CDT_DIAG_LENGTH, val) * 824) / 10;
+}
+
+static int qca808x_cable_test_start(struct phy_device *phydev)
+{
+ int ret;
+
+ /* perform CDT with the following configs:
+ * 1. disable hibernation.
+ * 2. force PHY working in MDI mode.
+ * 3. for PHY working in 1000BaseT.
+ * 4. configure the threshold.
+ */
+
+ ret = at803x_debug_reg_mask(phydev, QCA808X_DBG_AN_TEST, QCA808X_HIBERNATION_EN, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = at803x_config_mdix(phydev, ETH_TP_MDI);
+ if (ret < 0)
+ return ret;
+
+ /* Force 1000base-T needs to configure PMA/PMD and MII_BMCR */
+ phydev->duplex = DUPLEX_FULL;
+ phydev->speed = SPEED_1000;
+ ret = genphy_c45_pma_setup_forced(phydev);
+ if (ret < 0)
+ return ret;
+
+ ret = genphy_setup_forced(phydev);
+ if (ret < 0)
+ return ret;
+
+ /* configure the thresholds for open, short, pair ok test */
+ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8074, 0xc040);
+ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8076, 0xc040);
+ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8077, 0xa060);
+ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8078, 0xc050);
+ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807a, 0xc060);
+ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807e, 0xb060);
+
+ return 0;
+}
+
+static int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished)
+{
+ int ret, val;
+ int pair_a, pair_b, pair_c, pair_d;
+
+ *finished = false;
+
+ ret = at803x_cdt_start(phydev, 0);
+ if (ret)
+ return ret;
+
+ ret = at803x_cdt_wait_for_completion(phydev);
+ if (ret)
+ return ret;
+
+ val = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA808X_MMD3_CDT_STATUS);
+ if (val < 0)
+ return val;
+
+ pair_a = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, val);
+ pair_b = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, val);
+ pair_c = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, val);
+ pair_d = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, val);
+
+ ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
+ qca808x_cable_test_result_trans(pair_a));
+ ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_B,
+ qca808x_cable_test_result_trans(pair_b));
+ ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_C,
+ qca808x_cable_test_result_trans(pair_c));
+ ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_D,
+ qca808x_cable_test_result_trans(pair_d));
+
+ if (qca808x_cdt_fault_length_valid(pair_a))
+ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A,
+ qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_A));
+ if (qca808x_cdt_fault_length_valid(pair_b))
+ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B,
+ qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_B));
+ if (qca808x_cdt_fault_length_valid(pair_c))
+ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C,
+ qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_C));
+ if (qca808x_cdt_fault_length_valid(pair_d))
+ ethnl_cable_test_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D,
+ qca808x_cdt_fault_length(phydev, ETHTOOL_A_CABLE_PAIR_D));
+
+ *finished = true;
+
+ return 0;
+}
+
static struct phy_driver at803x_driver[] = {
{
/* Qualcomm Atheros AR8035 */
@@ -1848,6 +2033,7 @@ static struct phy_driver at803x_driver[] = {
/* Qualcomm QCA8081 */
PHY_ID_MATCH_EXACT(QCA8081_PHY_ID),
.name = "Qualcomm QCA8081",
+ .flags = PHY_POLL_CABLE_TEST,
.config_intr = at803x_config_intr,
.handle_interrupt = at803x_handle_interrupt,
.get_tunable = at803x_get_tunable,
@@ -1861,6 +2047,8 @@ static struct phy_driver at803x_driver[] = {
.read_status = qca808x_read_status,
.config_init = qca808x_config_init,
.soft_reset = qca808x_soft_reset,
+ .cable_test_start = qca808x_cable_test_start,
+ .cable_test_get_status = qca808x_cable_test_get_status,
}, };
module_phy_driver(at803x_driver);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
On Sun, Oct 24, 2021 at 04:27:33PM +0800, Luo Jie wrote:
> Add the constants for 2.5G fast retrain capability
> in 10G AN control register, fast retrain status and
> control register and THP bypass register into mdio.h.
>
> Signed-off-by: Luo Jie <[email protected]>
Reviewed-by: Andrew Lunn <[email protected]>
Andrew
On Sun, Oct 24, 2021 at 04:27:32PM +0800, Luo Jie wrote:
> Reuse at803x phy driver config_aneg excepting
> adding 2500M auto-negotiation.
>
> Signed-off-by: Luo Jie <[email protected]>
Reviewed-by: Andrew Lunn <[email protected]>
Andrew
On Sun, Oct 24, 2021 at 04:27:34PM +0800, Luo Jie wrote:
> Add generic fast retrain auto-negotiation function for C45 PHYs.
>
> Signed-off-by: Luo Jie <[email protected]>
Reviewed-by: Andrew Lunn <[email protected]>
Andrew
On Sun, Oct 24, 2021 at 04:27:35PM +0800, Luo Jie wrote:
> Add the qca8081 phy driver config_init function, which includes:
> 1. Enable fast restrain.
> 2. Add 802.3az configurations.
> 3. Initialize ADC threshold as 100mv.
>
> Signed-off-by: Luo Jie <[email protected]>
Reviewed-by: Andrew Lunn <[email protected]>
Andrew
On Sun, Oct 24, 2021 at 04:27:36PM +0800, Luo Jie wrote:
> qca8081 phy is a single port phy, configure
> phy the lower seed value to make it linked as slave
> mode easier.
>
> Signed-off-by: Luo Jie <[email protected]>
Reviewed-by: Andrew Lunn <[email protected]>
Andrew
On Sun, Oct 24, 2021 at 04:27:37PM +0800, Luo Jie wrote:
> 1. The master/slave seed needs to be updated when the link can't
> be created.
>
> 2. The case where two qca8081 PHYs are connected each other and
> master/slave seed is generated as the same value also needs
> to be considered, so adding this code change into read_status
> instead of link_change_notify.
>
> Signed-off-by: Luo Jie <[email protected]>
Reviewed-by: Andrew Lunn <[email protected]>
Andrew
On Sun, Oct 24, 2021 at 04:27:38PM +0800, Luo Jie wrote:
> To perform CDT of qca8081 phy:
> 1. disable hibernation.
> 2. force phy working in MDI mode.
> 3. force phy working in 1000BASE-T mode.
> 4. configure the related thresholds.
>
> Signed-off-by: Luo Jie <[email protected]>
Reviewed-by: Andrew Lunn <[email protected]>
Andrew
Hello:
This series was applied to netdev/net-next.git (master)
by David S. Miller <[email protected]>:
On Sun, 24 Oct 2021 16:27:24 +0800 you wrote:
> This patch series add the qca8081 ethernet phy driver support, which
> improve the wol feature, leverage at803x phy driver and add the fast
> retrain, master/slave seed and CDT feature.
>
> Changes in v7:
> * update Reviewed-by tags.
>
> [...]
Here is the summary with links:
- [v7,01/14] net: phy: at803x: replace AT803X_DEVICE_ADDR with MDIO_MMD_PCS
https://git.kernel.org/netdev/net-next/c/c0f0b563f8c0
- [v7,02/14] net: phy: at803x: use phy_modify()
https://git.kernel.org/netdev/net-next/c/2d4284e88a59
- [v7,03/14] net: phy: at803x: improve the WOL feature
https://git.kernel.org/netdev/net-next/c/7beecaf7d507
- [v7,04/14] net: phy: at803x: use GENMASK() for speed status
https://git.kernel.org/netdev/net-next/c/9540cdda9113
- [v7,05/14] net: phy: add qca8081 ethernet phy driver
https://git.kernel.org/netdev/net-next/c/daf61732a49a
- [v7,06/14] net: phy: add qca8081 read_status
https://git.kernel.org/netdev/net-next/c/79c7bc052154
- [v7,07/14] net: phy: add qca8081 get_features
https://git.kernel.org/netdev/net-next/c/765c22aad157
- [v7,08/14] net: phy: add qca8081 config_aneg
https://git.kernel.org/netdev/net-next/c/f884d449bf28
- [v7,09/14] net: phy: add constants for fast retrain related register
https://git.kernel.org/netdev/net-next/c/1cf4e9a6fbdb
- [v7,10/14] net: phy: add genphy_c45_fast_retrain
https://git.kernel.org/netdev/net-next/c/63c67f526db8
- [v7,11/14] net: phy: add qca8081 config_init
https://git.kernel.org/netdev/net-next/c/2acdd43fe009
- [v7,12/14] net: phy: add qca8081 soft_reset and enable master/slave seed
https://git.kernel.org/netdev/net-next/c/9d4dae29624f
- [v7,13/14] net: phy: adjust qca8081 master/slave seed value if link down
https://git.kernel.org/netdev/net-next/c/8bc1c5430c4b
- [v7,14/14] net: phy: add qca8081 cdt feature
https://git.kernel.org/netdev/net-next/c/8c84d7528d8d
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html