[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251113115206.140339-2-parthiban.veerasooran@microchip.com>
Date: Thu, 13 Nov 2025 17:22:05 +0530
From: Parthiban Veerasooran <parthiban.veerasooran@...rochip.com>
To: <Parthiban.Veerasooran@...rochip.com>, <piergiorgio.beruto@...il.com>,
<andrew@...n.ch>, <hkallweit1@...il.com>, <linux@...linux.org.uk>,
<davem@...emloft.net>, <edumazet@...gle.com>, <kuba@...nel.org>,
<pabeni@...hat.com>
CC: <netdev@...r.kernel.org>, <linux-kernel@...r.kernel.org>, "Parthiban
Veerasooran" <parthiban.veerasooran@...rochip.com>
Subject: [PATCH net-next 1/2] net: phy: phy-c45: add SQI and SQI+ support for OATC14 10Base-T1S PHYs
Add support for reading Signal Quality Indicator (SQI) and enhanced SQI+
from OATC14 10Base-T1S PHYs.
- Introduce MDIO register definitions for DCQ_SQI and DCQ_SQIPLUS.
- Add `genphy_c45_oatc14_get_sqi_max()` to return the maximum supported
SQI/SQI+ level.
- Add `genphy_c45_oatc14_get_sqi()` to return the current SQI or SQI+
value.
- Update `include/linux/phy.h` to expose the new APIs.
SQI+ capability is read from the Advanced Diagnostic Features Capability
register (ADFCAP). If SQI+ is supported, the driver calculates the value
from the MSBs of the DCQ_SQIPLUS register; otherwise, it falls back to
basic SQI (0-7 levels).
These changes allow higher-layer drivers and diagnostic tools to assess
link quality more accurately for OATC14 PHYs.
Open Alliance TC14 10BASE-T1S Advanced Diagnostic PHY Features
Specification ref:
https://opensig.org/wp-content/uploads/2025/06/OPEN_Alliance_10BASE-T1S_Advanced_PHY_features_for-automotive_Ethernet_V2.1b.pdf
Signed-off-by: Parthiban Veerasooran <parthiban.veerasooran@...rochip.com>
---
drivers/net/phy/mdio-open-alliance.h | 14 +++++
drivers/net/phy/phy-c45.c | 94 ++++++++++++++++++++++++++++
include/linux/phy.h | 2 +
3 files changed, 110 insertions(+)
diff --git a/drivers/net/phy/mdio-open-alliance.h b/drivers/net/phy/mdio-open-alliance.h
index 6850a3f0b31e..dcf7b685da5c 100644
--- a/drivers/net/phy/mdio-open-alliance.h
+++ b/drivers/net/phy/mdio-open-alliance.h
@@ -56,6 +56,8 @@
/* Advanced Diagnostic Features Capability Register*/
#define MDIO_OATC14_ADFCAP 0xcc00
#define OATC14_ADFCAP_HDD_CAPABILITY GENMASK(10, 8)
+#define OATC14_ADFCAP_SQIPLUS_CAPABILITY GENMASK(4, 1)
+#define OATC14_ADFCAP_SQI_CAPABILITY BIT(0)
/* Harness Defect Detection Register */
#define MDIO_OATC14_HDD 0xcc01
@@ -65,6 +67,18 @@
#define OATC14_HDD_VALID BIT(2)
#define OATC14_HDD_SHORT_OPEN_STATUS GENMASK(1, 0)
+/* Dynamic Channel Quality SQI Register */
+#define MDIO_OATC14_DCQ_SQI 0xcc03
+#define OATC14_DCQ_SQI_UPDATE BIT(15)
+#define OATC14_DCQ_SQI_VALUE GENMASK(2, 0)
+
+/* Dynamic Channel Quality SQI Plus Register */
+#define MDIO_OATC14_DCQ_SQIPLUS 0xcc04
+#define OATC14_DCQ_SQIPLUS_VALUE GENMASK(7, 0)
+
+/* SQI is supported using 3 bits means 8 levels (0-7) */
+#define OATC14_SQI_MAX_LEVEL 7
+
/* Bus Short/Open Status:
* 0 0 - no fault; everything is ok. (Default)
* 0 1 - detected as an open or missing termination(s)
diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
index e8e5be4684ab..47854c8fb9da 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -1695,3 +1695,97 @@ int genphy_c45_oatc14_cable_test_start(struct phy_device *phydev)
OATC14_HDD_START_CONTROL);
}
EXPORT_SYMBOL(genphy_c45_oatc14_cable_test_start);
+
+/**
+ * genphy_c45_oatc14_get_sqi_max - Get maximum supported SQI or SQI+ level of
+ OATC14 10Base-T1S PHY
+ * @phydev: pointer to the PHY device structure
+ *
+ * Reads the Signal Quality Indicator (SQI) or enhanced SQI+ capability and
+ * returns the highest supported level.
+ *
+ * Return:
+ * * Maximum SQI/SQI+ level (≥0)
+ * * -EOPNOTSUPP if not supported
+ * * Negative errno on read failure
+ */
+int genphy_c45_oatc14_get_sqi_max(struct phy_device *phydev)
+{
+ int bits;
+ int ret;
+
+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MDIO_OATC14_ADFCAP);
+ if (ret < 0)
+ return ret;
+
+ /* SQI+ capability
+ * 0 - SQI+ is not supported
+ * X - SQI+ is supported using X bits (0-255 levels)
+ */
+ bits = FIELD_GET(OATC14_ADFCAP_SQIPLUS_CAPABILITY, ret);
+ if (bits)
+ /* Max sqi+ level supported: (2 ^ bits) - 1 */
+ return BIT(bits) - 1;
+
+ /* SQI capability
+ * 0 – SQI is not supported
+ * 1 – SQI is supported (0-7 levels)
+ */
+ if (ret & OATC14_ADFCAP_SQI_CAPABILITY)
+ return OATC14_SQI_MAX_LEVEL;
+
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(genphy_c45_oatc14_get_sqi_max);
+
+/**
+ * genphy_c45_oatc14_get_sqi - Get Signal Quality Indicator (SQI) from an OATC14
+ 10Base-T1S PHY
+ * @phydev: pointer to the PHY device structure
+ *
+ * Reads the SQI or SQI+ value from an OATC14-compatible 10Base-T1S PHY. If SQI+
+ * capability is supported, the function returns the extended SQI+ value;
+ * otherwise, it returns the basic SQI value.
+ *
+ * Return:
+ * * Positive SQI/SQI+ value on success
+ * * 0 if SQI update is not available
+ * * Negative errno on failure
+ */
+int genphy_c45_oatc14_get_sqi(struct phy_device *phydev)
+{
+ u8 shift;
+ int ret;
+
+ /* Read SQI value */
+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MDIO_OATC14_DCQ_SQI);
+ if (ret < 0)
+ return ret;
+
+ /* Check for SQI update */
+ if (!(ret & OATC14_DCQ_SQI_UPDATE))
+ return 0;
+
+ /* Read SQI capability */
+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MDIO_OATC14_ADFCAP);
+ if (ret < 0)
+ return ret;
+
+ /* Calculate and return SQI+ value if supported */
+ if (ret & OATC14_ADFCAP_SQIPLUS_CAPABILITY) {
+ /* SQI+ uses N MSBs out of 8 bits, left-aligned with padding 1's
+ * Calculate the right-shift needed to isolate the N bits.
+ */
+ shift = 8 - FIELD_GET(OATC14_ADFCAP_SQIPLUS_CAPABILITY, ret);
+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND2,
+ MDIO_OATC14_DCQ_SQIPLUS);
+ if (ret < 0)
+ return ret;
+
+ return (ret & OATC14_DCQ_SQIPLUS_VALUE) >> shift;
+ }
+
+ /* Return SQI value if SQI+ capability is not supported */
+ return ret & OATC14_DCQ_SQI_VALUE;
+}
+EXPORT_SYMBOL(genphy_c45_oatc14_get_sqi);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index bf5457341ca8..a3a8ff099f94 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -2254,6 +2254,8 @@ int genphy_c45_an_config_eee_aneg(struct phy_device *phydev);
int genphy_c45_oatc14_cable_test_start(struct phy_device *phydev);
int genphy_c45_oatc14_cable_test_get_status(struct phy_device *phydev,
bool *finished);
+int genphy_c45_oatc14_get_sqi_max(struct phy_device *phydev);
+int genphy_c45_oatc14_get_sqi(struct phy_device *phydev);
/* The gen10g_* functions are the old Clause 45 stub */
int gen10g_config_aneg(struct phy_device *phydev);
--
2.34.1
Powered by blists - more mailing lists