* [PATCH v2] net: dsa: microchip: implement KSZ87xx Module 3 low-loss cable errata
@ 2026-04-08 11:57 Fidelio Lawson
2026-04-08 12:43 ` Andrew Lunn
2026-04-08 12:49 ` Andrew Lunn
0 siblings, 2 replies; 4+ messages in thread
From: Fidelio Lawson @ 2026-04-08 11:57 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Marek Vasut,
Maxime Chevallier
Cc: Woojung Huh, netdev, devicetree, linux-kernel, Fidelio Lawson
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@exotec.com>
---
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@exotec.com
---
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);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (!ret)
+ dev->low_loss_wa_mode = val & PHY_KSZ87XX_LOW_LOSS_MASK;
+ return ret;
default:
break;
}
diff --git a/drivers/net/dsa/microchip/ksz8_reg.h b/drivers/net/dsa/microchip/ksz8_reg.h
index 332408567b47..cd1092aa0eaf 100644
--- a/drivers/net/dsa/microchip/ksz8_reg.h
+++ b/drivers/net/dsa/microchip/ksz8_reg.h
@@ -202,6 +202,10 @@
#define REG_PORT_3_STATUS_0 0x38
#define REG_PORT_4_STATUS_0 0x48
+/* KSZ87xx LinkMD registers (TABLE_LINK_MD_V) */
+#define KSZ87XX_REG_EQ_TRAIN 0x3C
+#define KSZ87XX_REG_PHY_LPF 0x4C
+
/* For KSZ8765. */
#define PORT_REMOTE_ASYM_PAUSE BIT(5)
#define PORT_REMOTE_SYM_PAUSE BIT(4)
@@ -342,7 +346,7 @@
#define TABLE_EEE (TABLE_EEE_V << TABLE_EXT_SELECT_S)
#define TABLE_ACL (TABLE_ACL_V << TABLE_EXT_SELECT_S)
#define TABLE_PME (TABLE_PME_V << TABLE_EXT_SELECT_S)
-#define TABLE_LINK_MD (TABLE_LINK_MD << TABLE_EXT_SELECT_S)
+#define TABLE_LINK_MD (TABLE_LINK_MD_V << TABLE_EXT_SELECT_S)
#define TABLE_READ BIT(4)
#define TABLE_SELECT_S 2
#define TABLE_STATIC_MAC_V 0
@@ -729,6 +733,20 @@
#define PHY_POWER_SAVING_ENABLE BIT(2)
#define PHY_REMOTE_LOOPBACK BIT(1)
+/* Equalizer low-loss workaround */
+/* bits [1:0]: 00 = disabled, 01 = workaround 1, 10 = workaround 2 */
+#define PHY_REG_KSZ87XX_LOW_LOSS 0x1C
+#define PHY_KSZ87XX_LOW_LOSS_MASK GENMASK(1, 0)
+
+#define PHY_LOW_LOSS_ERRATA_DISABLED 0
+#define KSZ87XX_LOW_LOSS_WA_EQ 1
+#define KSZ87XX_LOW_LOSS_WA_LPF 2
+
+#define KSZ87XX_EQ_TRAIN_DEFAULT 0x0A
+#define KSZ87XX_EQ_TRAIN_LOW_LOSS 0x15
+#define KSZ87XX_PHY_LPF_DEFAULT 0x00
+#define KSZ87XX_PHY_LPF_62MHZ 0x40
+
/* KSZ8463 specific registers. */
#define P1MBCR 0x4C
#define P1MBSR 0x4E
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 929aff4c55de..729996c7160c 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -219,6 +219,9 @@ struct ksz_device {
* the switch’s internal PHYs, bypassing the main SPI interface.
*/
struct mii_bus *parent_mdio_bus;
+
+ /* Equalizer low-loss workaround tunable */
+ u8 low_loss_wa_mode; /* bits [1:0]: 00 = disabled, 01 = workaround 1, 10 = workaround 2 */
};
/* List of supported models */
---
base-commit: 2d1373e4246da3b58e1df058374ed6b101804e07
change-id: 20260323-ksz87xx_errata_low_loss_connections-b65e76e2b403
Best regards,
--
Fidelio Lawson <fidelio.lawson@exotec.com>
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH v2] net: dsa: microchip: implement KSZ87xx Module 3 low-loss cable errata
2026-04-08 11:57 [PATCH v2] net: dsa: microchip: implement KSZ87xx Module 3 low-loss cable errata Fidelio Lawson
@ 2026-04-08 12:43 ` Andrew Lunn
2026-04-08 15:25 ` Fidelio LAWSON
2026-04-08 12:49 ` Andrew Lunn
1 sibling, 1 reply; 4+ messages in thread
From: Andrew Lunn @ 2026-04-08 12:43 UTC (permalink / raw)
To: Fidelio Lawson
Cc: Woojung Huh, UNGLinuxDriver, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Marek Vasut, Maxime Chevallier,
netdev, devicetree, linux-kernel, Fidelio Lawson
> 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)
There was a comment, which i only read after making the suggestion to
use two bits, of exposing the different low pass filter bandwidths,
rather than just picking one value. How useful is that?
Andrew
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH v2] net: dsa: microchip: implement KSZ87xx Module 3 low-loss cable errata
2026-04-08 12:43 ` Andrew Lunn
@ 2026-04-08 15:25 ` Fidelio LAWSON
0 siblings, 0 replies; 4+ messages in thread
From: Fidelio LAWSON @ 2026-04-08 15:25 UTC (permalink / raw)
To: Andrew Lunn
Cc: Woojung Huh, UNGLinuxDriver, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Marek Vasut, Maxime Chevallier,
netdev, devicetree, linux-kernel, Fidelio Lawson
On 4/8/26 14:43, Andrew Lunn wrote:
>> 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)
>
> There was a comment, which i only read after making the suggestion to
> use two bits, of exposing the different low pass filter bandwidths,
> rather than just picking one value. How useful is that?
>
> Andrew
Initially I limited the LPF setting to the single bandwidth explicitly
recommended by the errata (62MHz).
But I’ll extend the implementation to expose all documented LPF
bandwidth options so the interface is more flexible for users.
Best regards,
Fidelio
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] net: dsa: microchip: implement KSZ87xx Module 3 low-loss cable errata
2026-04-08 11:57 [PATCH v2] net: dsa: microchip: implement KSZ87xx Module 3 low-loss cable errata Fidelio Lawson
2026-04-08 12:43 ` Andrew Lunn
@ 2026-04-08 12:49 ` Andrew Lunn
1 sibling, 0 replies; 4+ messages in thread
From: Andrew Lunn @ 2026-04-08 12:49 UTC (permalink / raw)
To: Fidelio Lawson
Cc: Woojung Huh, UNGLinuxDriver, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Marek Vasut, Maxime Chevallier,
netdev, devicetree, linux-kernel, Fidelio Lawson
> The register can be read and written from userspace via standard Clause 22 PHY
> accesses (for example using phytool) on DSA user ports.
Please add a phy tunable. .get_tunable/.set_tunable.
Andrew
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-04-08 15:25 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-08 11:57 [PATCH v2] net: dsa: microchip: implement KSZ87xx Module 3 low-loss cable errata Fidelio Lawson
2026-04-08 12:43 ` Andrew Lunn
2026-04-08 15:25 ` Fidelio LAWSON
2026-04-08 12:49 ` Andrew Lunn
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox