Skip to content

Commit 5e1bf5a

Browse files
ParthibanI17164kuba-moo
authored andcommitted
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). This enables ethtool to report the SQI value for OATC14 10Base-T1S 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 <[email protected]> Reviewed-by: Andrew Lunn <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 8d537e3 commit 5e1bf5a

File tree

3 files changed

+179
-0
lines changed

3 files changed

+179
-0
lines changed

drivers/net/phy/mdio-open-alliance.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
/* Advanced Diagnostic Features Capability Register*/
5757
#define MDIO_OATC14_ADFCAP 0xcc00
5858
#define OATC14_ADFCAP_HDD_CAPABILITY GENMASK(10, 8)
59+
#define OATC14_ADFCAP_SQIPLUS_CAPABILITY GENMASK(4, 1)
60+
#define OATC14_ADFCAP_SQI_CAPABILITY BIT(0)
5961

6062
/* Harness Defect Detection Register */
6163
#define MDIO_OATC14_HDD 0xcc01
@@ -65,6 +67,17 @@
6567
#define OATC14_HDD_VALID BIT(2)
6668
#define OATC14_HDD_SHORT_OPEN_STATUS GENMASK(1, 0)
6769

70+
/* Dynamic Channel Quality SQI Register */
71+
#define MDIO_OATC14_DCQ_SQI 0xcc03
72+
#define OATC14_DCQ_SQI_VALUE GENMASK(2, 0)
73+
74+
/* Dynamic Channel Quality SQI Plus Register */
75+
#define MDIO_OATC14_DCQ_SQIPLUS 0xcc04
76+
#define OATC14_DCQ_SQIPLUS_VALUE GENMASK(7, 0)
77+
78+
/* SQI is supported using 3 bits means 8 levels (0-7) */
79+
#define OATC14_SQI_MAX_LEVEL 7
80+
6881
/* Bus Short/Open Status:
6982
* 0 0 - no fault; everything is ok. (Default)
7083
* 0 1 - detected as an open or missing termination(s)

drivers/net/phy/phy-c45.c

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,3 +1695,140 @@ int genphy_c45_oatc14_cable_test_start(struct phy_device *phydev)
16951695
OATC14_HDD_START_CONTROL);
16961696
}
16971697
EXPORT_SYMBOL(genphy_c45_oatc14_cable_test_start);
1698+
1699+
/**
1700+
* oatc14_update_sqi_capability - Read and update OATC14 10Base-T1S PHY SQI/SQI+
1701+
* capability
1702+
* @phydev: Pointer to the PHY device structure
1703+
*
1704+
* This helper reads the OATC14 ADFCAP capability register to determine whether
1705+
* the PHY supports SQI or SQI+ reporting.
1706+
*
1707+
* SQI+ capability is detected first. The SQI+ field indicates the number of
1708+
* valid MSBs (3–8), corresponding to 8–256 SQI+ levels. When present, the
1709+
* function stores the number of SQI+ bits and computes the maximum SQI+ value
1710+
* as (2^bits - 1).
1711+
*
1712+
* If SQI+ is not supported, the function checks for basic SQI capability,
1713+
* which provides 0–7 SQI levels.
1714+
*
1715+
* On success, the capability information is stored in
1716+
* @phydev->oatc14_sqi_capability and marked as updated.
1717+
*
1718+
* Return:
1719+
* * 0 - capability successfully read and stored
1720+
* * -EOPNOTSUPP - SQI/SQI+ not supported by this PHY
1721+
* * Negative errno on read failure
1722+
*/
1723+
static int oatc14_update_sqi_capability(struct phy_device *phydev)
1724+
{
1725+
u8 bits;
1726+
int ret;
1727+
1728+
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MDIO_OATC14_ADFCAP);
1729+
if (ret < 0)
1730+
return ret;
1731+
1732+
/* Check for SQI+ capability
1733+
* 0 - SQI+ is not supported
1734+
* (3-8) bits for (8-256) SQI+ levels supported
1735+
*/
1736+
bits = FIELD_GET(OATC14_ADFCAP_SQIPLUS_CAPABILITY, ret);
1737+
if (bits) {
1738+
phydev->oatc14_sqi_capability.sqiplus_bits = bits;
1739+
/* Max sqi+ level supported: (2 ^ bits) - 1 */
1740+
phydev->oatc14_sqi_capability.sqi_max = BIT(bits) - 1;
1741+
goto update_done;
1742+
}
1743+
1744+
/* Check for SQI capability
1745+
* 0 - SQI is not supported
1746+
* 1 - SQI is supported (0-7 levels)
1747+
*/
1748+
if (ret & OATC14_ADFCAP_SQI_CAPABILITY) {
1749+
phydev->oatc14_sqi_capability.sqi_max = OATC14_SQI_MAX_LEVEL;
1750+
goto update_done;
1751+
}
1752+
1753+
return -EOPNOTSUPP;
1754+
1755+
update_done:
1756+
phydev->oatc14_sqi_capability.updated = true;
1757+
return 0;
1758+
}
1759+
1760+
/**
1761+
* genphy_c45_oatc14_get_sqi_max - Get maximum supported SQI or SQI+ level of
1762+
* OATC14 10Base-T1S PHY
1763+
* @phydev: pointer to the PHY device structure
1764+
*
1765+
* This function returns the maximum supported Signal Quality Indicator (SQI) or
1766+
* SQI+ level. The SQI capability is updated on first invocation if it has not
1767+
* already been updated.
1768+
*
1769+
* Return:
1770+
* * Maximum SQI/SQI+ level supported
1771+
* * Negative errno on capability read failure
1772+
*/
1773+
int genphy_c45_oatc14_get_sqi_max(struct phy_device *phydev)
1774+
{
1775+
int ret;
1776+
1777+
if (!phydev->oatc14_sqi_capability.updated) {
1778+
ret = oatc14_update_sqi_capability(phydev);
1779+
if (ret)
1780+
return ret;
1781+
}
1782+
1783+
return phydev->oatc14_sqi_capability.sqi_max;
1784+
}
1785+
EXPORT_SYMBOL(genphy_c45_oatc14_get_sqi_max);
1786+
1787+
/**
1788+
* genphy_c45_oatc14_get_sqi - Get Signal Quality Indicator (SQI) from an OATC14
1789+
* 10Base-T1S PHY
1790+
* @phydev: pointer to the PHY device structure
1791+
*
1792+
* This function reads the SQI+ or SQI value from an OATC14-compatible
1793+
* 10Base-T1S PHY. If SQI+ capability is supported, the function returns the
1794+
* extended SQI+ value; otherwise, it returns the basic SQI value. The SQI
1795+
* capability is updated on first invocation if it has not already been updated.
1796+
*
1797+
* Return:
1798+
* * SQI/SQI+ value on success
1799+
* * Negative errno on read failure
1800+
*/
1801+
int genphy_c45_oatc14_get_sqi(struct phy_device *phydev)
1802+
{
1803+
u8 shift;
1804+
int ret;
1805+
1806+
if (!phydev->oatc14_sqi_capability.updated) {
1807+
ret = oatc14_update_sqi_capability(phydev);
1808+
if (ret)
1809+
return ret;
1810+
}
1811+
1812+
/* Calculate and return SQI+ value if supported */
1813+
if (phydev->oatc14_sqi_capability.sqiplus_bits) {
1814+
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2,
1815+
MDIO_OATC14_DCQ_SQIPLUS);
1816+
if (ret < 0)
1817+
return ret;
1818+
1819+
/* SQI+ uses N MSBs out of 8 bits, left-aligned with padding 1's
1820+
* Calculate the right-shift needed to isolate the N bits.
1821+
*/
1822+
shift = 8 - phydev->oatc14_sqi_capability.sqiplus_bits;
1823+
1824+
return (ret & OATC14_DCQ_SQIPLUS_VALUE) >> shift;
1825+
}
1826+
1827+
/* Read and return SQI value if SQI+ capability is not supported */
1828+
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MDIO_OATC14_DCQ_SQI);
1829+
if (ret < 0)
1830+
return ret;
1831+
1832+
return ret & OATC14_DCQ_SQI_VALUE;
1833+
}
1834+
EXPORT_SYMBOL(genphy_c45_oatc14_get_sqi);

include/linux/phy.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,30 @@ struct phy_c45_device_ids {
530530
struct macsec_context;
531531
struct macsec_ops;
532532

533+
/**
534+
* struct phy_oatc14_sqi_capability - SQI capability information for OATC14
535+
* 10Base-T1S PHY
536+
* @updated: Indicates whether the SQI capability fields have been updated.
537+
* @sqi_max: Maximum supported Signal Quality Indicator (SQI) level reported by
538+
* the PHY.
539+
* @sqiplus_bits: Bits for SQI+ levels supported by the PHY.
540+
* 0 - SQI+ is not supported
541+
* 3 - SQI+ is supported, using 3 bits (8 levels)
542+
* 4 - SQI+ is supported, using 4 bits (16 levels)
543+
* 5 - SQI+ is supported, using 5 bits (32 levels)
544+
* 6 - SQI+ is supported, using 6 bits (64 levels)
545+
* 7 - SQI+ is supported, using 7 bits (128 levels)
546+
* 8 - SQI+ is supported, using 8 bits (256 levels)
547+
*
548+
* This structure is used by the OATC14 10Base-T1S PHY driver to store the SQI
549+
* and SQI+ capability information retrieved from the PHY.
550+
*/
551+
struct phy_oatc14_sqi_capability {
552+
bool updated;
553+
int sqi_max;
554+
u8 sqiplus_bits;
555+
};
556+
533557
/**
534558
* struct phy_device - An instance of a PHY
535559
*
@@ -626,6 +650,7 @@ struct macsec_ops;
626650
* @link_down_events: Number of times link was lost
627651
* @shared: Pointer to private data shared by phys in one package
628652
* @priv: Pointer to driver private data
653+
* @oatc14_sqi_capability: SQI capability information for OATC14 10Base-T1S PHY
629654
*
630655
* interrupts currently only supports enabled or disabled,
631656
* but could be changed in the future to support enabling
@@ -772,6 +797,8 @@ struct phy_device {
772797
/* MACsec management functions */
773798
const struct macsec_ops *macsec_ops;
774799
#endif
800+
801+
struct phy_oatc14_sqi_capability oatc14_sqi_capability;
775802
};
776803

777804
/* Generic phy_device::dev_flags */
@@ -2257,6 +2284,8 @@ int genphy_c45_an_config_eee_aneg(struct phy_device *phydev);
22572284
int genphy_c45_oatc14_cable_test_start(struct phy_device *phydev);
22582285
int genphy_c45_oatc14_cable_test_get_status(struct phy_device *phydev,
22592286
bool *finished);
2287+
int genphy_c45_oatc14_get_sqi_max(struct phy_device *phydev);
2288+
int genphy_c45_oatc14_get_sqi(struct phy_device *phydev);
22602289

22612290
/* The gen10g_* functions are the old Clause 45 stub */
22622291
int gen10g_config_aneg(struct phy_device *phydev);

0 commit comments

Comments
 (0)