Re: [PATCH v2] net: dsa: microchip: implement KSZ87xx Module 3 low-loss cable errata

From: Marek Vasut

Date: Wed Apr 08 2026 - 21:05:19 EST


On 4/8/26 1:57 PM, Fidelio Lawson wrote:
Implement the "Module 3: Equalizer fix for short cables" erratum from
Microchip document DS80000687C for KSZ87xx switches.

The issue affects short or low-loss cable links (e.g. CAT5e/CAT6),
where the PHY receiver equalizer may amplify high-amplitude signals
excessively, resulting in internal distortion and link establishment
failures.

KSZ87xx devices require a workaround for the Module 3 low-loss cable
condition, controlled through the switch TABLE_LINK_MD_V indirect
registers.

The affected registers are part of the switch address space and are not
directly accessible from the PHY driver. To keep the PHY-facing API
clean and avoid leaking switch-specific details, model this errata
control as vendor-specific Clause 22 PHY registers.

Two vendor-defined bits are introduced in PHY_REG_LOW_LOSS_CTRL,
and ksz8_r_phy() / ksz8_w_phy() translate accesses to these bits
into the appropriate indirect TABLE_LINK_MD_V accesses.

The control register defines the following modes:
bits [1:0]:
00 = workaround disabled
01 = workaround 1 (DSP EQ training adjustment, LinkMD reg 0x3c)
10 = workaround 2 (receiver LPF bandwidth, LinkMD reg 0x4c)

Workaround 1: Adjusts the DSP EQ training behavior via LinkMD register
0x3C. Widens and optimizes the DSP EQ compensation range,
and is expected to solve most short/low-loss cable issues.

Workaround 2: for the cases where Workaround 1 is not sufficient.
This one adjusts the receiver low-pass filter bandwidth, effectively
reducing the high-frequency component of the received signal

The register is accessible through standard PHY read/write operations
(e.g. phytool), without requiring any switch-specific userspace
interface. This allows robust link establishment on short or
low-loss cabling without requiring DTS properties and without
constraining hardware design choices.

The erratum affects the shared PHY analog front-end and therefore
applies globally to the switch.

Signed-off-by: Fidelio Lawson <fidelio.lawson@xxxxxxxxxx>
---
Hello,

This patch implements the “Module 3: Equalizer fix for short cables” erratum
described in Microchip document DS80000687C for KSZ87xx switches.

According to the erratum, the embedded PHY receiver in KSZ87xx switches is
tuned by default for long, high-loss Ethernet cables. When operating with
short or low-loss cables (for example CAT5e or CAT6), the PHY equalizer may
over-amplify the incoming signal, leading to internal distortion and link
establishment failures.

Microchip provides two workarounds, each requiring a write to a different
indirect PHY register access mechanism.

The workaround requires programming internal PHY/DSP registers located in the
LinkMD table, accessed through the KSZ8 indirect register mechanism. Since these
registers belong to the switch address space and are not directly accessible
from a standalone PHY driver, the erratum control is modeled as a vendor-specific
Clause 22 PHY register, virtualized by the KSZ8 DSA driver.

Reads and writes to this register are intercepted by ksz8_r_phy() /
ksz8_w_phy() and translated into the required TABLE_LINK_MD_V indirect accesses.
The erratum affects the shared PHY analog front-end and therefore applies
globally to the switch.

The register defines three modes:
- 0x0: workaround disabled
- 0x1: workaround 1 (DSP EQ training adjustment)
- 0x2: workaround 2 (receiver low-pass filter bandwidth reduction)

The register can be read and written from userspace via standard Clause 22 PHY
accesses (for example using phytool) on DSA user ports.

This series is based on Linux v7.0-rc1.
---
Changes in v2:
- Dropped the device tree approache based on review feedback
- Modeled the errata control as a vendor-specific Clause 22 PHY register
- Added KSZ87xx-specific guards and replaced magic values with named macros
- Rebased on Linux v7.0-rc1
- Link to v1: https://patch.msgid.link/20260326-ksz87xx_errata_low_loss_connections-v1-0-79a698f43626@xxxxxxxxxx
---
drivers/net/dsa/microchip/ksz8.c | 33 +++++++++++++++++++++++++++++++++
drivers/net/dsa/microchip/ksz8_reg.h | 20 +++++++++++++++++++-
drivers/net/dsa/microchip/ksz_common.h | 3 +++
3 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
index c354abdafc1b..d11da6e9ff54 100644
--- a/drivers/net/dsa/microchip/ksz8.c
+++ b/drivers/net/dsa/microchip/ksz8.c
@@ -1058,6 +1058,11 @@ int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
if (ret)
return ret;
+ break;
+ case PHY_REG_KSZ87XX_LOW_LOSS:
+ if (!ksz_is_ksz87xx(dev))
+ return -EOPNOTSUPP;
+ data = dev->low_loss_wa_mode;
break;
default:
processed = false;
@@ -1271,6 +1276,34 @@ int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
if (ret)
return ret;
break;
+ case PHY_REG_KSZ87XX_LOW_LOSS:
+ if (!ksz_is_ksz87xx(dev))
+ return -EOPNOTSUPP;
+
+ switch (val & PHY_KSZ87XX_LOW_LOSS_MASK) {
+ case PHY_LOW_LOSS_ERRATA_DISABLED:
+ ret = ksz8_ind_write8(dev, TABLE_LINK_MD, KSZ87XX_REG_EQ_TRAIN,
+ KSZ87XX_EQ_TRAIN_DEFAULT);
+ if (!ret)
+ ret = ksz8_ind_write8(dev, TABLE_LINK_MD,
+ KSZ87XX_REG_PHY_LPF,
+ KSZ87XX_PHY_LPF_DEFAULT);
+ break;
+ case KSZ87XX_LOW_LOSS_WA_EQ:
+ ret = ksz8_ind_write8(dev, TABLE_LINK_MD, KSZ87XX_REG_EQ_TRAIN,
+ KSZ87XX_EQ_TRAIN_LOW_LOSS);
+ break;
+ case KSZ87XX_LOW_LOSS_WA_LPF:
+ ret = ksz8_ind_write8(dev, TABLE_LINK_MD, KSZ87XX_REG_PHY_LPF,
+ KSZ87XX_PHY_LPF_62MHZ);

Please adjust this and make the low pass filter bandwidth actually configurable according to the values supported by the hardware, see this article:

https://microchip.my.site.com/s/article/Solution-for-Using-CAT-5E-or-CAT-6-Short-Cable-with-a-Link-Issue-for-the-KSZ8795-Family

The indirect register (0x4C) is an 8-bit register. The bits [7:6] are described in the table below.

Low pass filter bandwidth
00 = 90MHz
01 = 62MHz
10 = 55MHz
11 = 44MHz

...