From 02473bbb25e99eec01f24f07df7869ec27696176 Mon Sep 17 00:00:00 2001 From: Evgeny Boger Date: Fri, 10 Jul 2026 03:24:30 +0300 Subject: [PATCH 1/4] dt-bindings: phy: sun8i-r40-usb-phy: add TX tune properties The PHYs on Allwinner SoCs have a 5-bit TX tune field controlling the TX amplitude (2 bits) and slew rate (3 bits) of the line driver. The driver currently hardcodes the value inherited from the Allwinner BSP (minimum amplitude, slew rate 5), which on some boards results in a high-speed TX signal too weak for the link partner: on Wiren Board 7 (A40i/R40) devices the USB gadget fails to enumerate at high speed on several tested hosts and bulk data gets corrupted under load. Add optional per-PHY properties to tune the TX amplitude and slew rate. Signed-off-by: Evgeny Boger Co-Authored-By: Claude Fable 5 --- .../phy/allwinner,sun8i-r40-usb-phy.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun8i-r40-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun8i-r40-usb-phy.yaml index 7e578e9f3b754..0555de23383f6 100644 --- a/Documentation/devicetree/bindings/phy/allwinner,sun8i-r40-usb-phy.yaml +++ b/Documentation/devicetree/bindings/phy/allwinner,sun8i-r40-usb-phy.yaml @@ -98,6 +98,25 @@ properties: wirenboard,mux-on-id-pin: description: On Wiren Board 7 USB0 is muxed between USB-A connector for host mode and USB-C connector for peripheral mode. The mux is controller by voltage on perihperal connector. The same signal is used as USB ID. +patternProperties: + "^allwinner,usb[0-2]-tx-amplitude$": + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 3 + default: 0 + description: + TX amplitude tune value for the given PHY. The default (0, the + minimum) may result in a high-speed TX signal too weak for some + link partners to receive. + + "^allwinner,usb[0-2]-tx-slew-rate$": + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 7 + default: 5 + description: + TX slew rate tune value for the given PHY. + required: - "#phy-cells" - compatible From 61b7800e0e18a7ed09a470aca10e7787fb5ba5df Mon Sep 17 00:00:00 2001 From: Evgeny Boger Date: Fri, 10 Jul 2026 03:24:30 +0300 Subject: [PATCH 2/4] phy: sun4i-usb: allow tuning of the PHY TX settings via DT The driver programs the PHY TX tune field (registers 0x20-0x24) with a fixed value of 0x14, inherited from the Allwinner BSP: TX amplitude tune 0 (the minimum) and slew rate tune 5. The minimum TX amplitude turns out to be insufficient for some host/device combinations at high speed. On Wiren Board 7 (A40i/R40) devices the USB gadget reliably fails to enumerate when connected directly to several tested laptop root ports: the HS chirp handshake succeeds and host SETUP packets are decoded fine, but the host never accepts the IN data stage, so enumeration retries forever while musb logs "SetupEnd came in a wrong ep0stage". With the amplitude raised to the maximum (3) enumeration succeeds, but bulk IN data still gets corrupted under load (>100 packet errors per second on the host side) until the slew rate tune is raised as well; with amplitude 3 and slew rate 7 the link is error-free over minutes-long saturated transfers. Add optional per-PHY devicetree properties to set the two TX tune fields, keeping the current values as defaults. Signed-off-by: Evgeny Boger Co-Authored-By: Claude Fable 5 --- drivers/phy/allwinner/phy-sun4i-usb.c | 40 ++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index 3e9fd7badfcef..1002c956a9021 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -12,6 +12,7 @@ * Author: Sylwester Nawrocki */ +#include #include #include #include @@ -78,6 +79,17 @@ #define PHY_DISCON_TH_SEL 0x2a #define PHY_SQUELCH_DETECT 0x3c +/* + * TX tune field layout, written as 5 bits starting at + * PHY_TX_AMPLITUDE_TUNE. The default is inherited from the + * Allwinner BSP: amplitude 0 (minimum), slew rate 5. + */ +#define PHY_TX_AMPLITUDE_MASK GENMASK(1, 0) +#define PHY_TX_AMPLITUDE_MAX 3 +#define PHY_TX_SLEWRATE_MASK GENMASK(4, 2) +#define PHY_TX_SLEWRATE_MAX 7 +#define PHY_TX_TUNE_DEFAULT 0x14 + /* A83T specific control bits for PHY0 */ #define PHY_CTL_VBUSVLDEXT BIT(5) #define PHY_CTL_SIDDQ BIT(3) @@ -127,6 +139,7 @@ struct sun4i_usb_phy_data { struct clk *clk2; bool regulator_on; int index; + u32 tx_tune; } phys[MAX_PHYS]; /* phy0 / otg related variables */ struct extcon_dev *extcon; @@ -394,7 +407,7 @@ static int sun4i_usb_phy_init(struct phy *_phy) sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1); /* Adjust PHY's magnitude and rate */ - sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5); + sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, phy->tx_tune, 5); /* Disconnect threshold adjustment */ sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, @@ -915,6 +928,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) for (i = 0; i < MAX_PHYS; i++) { struct sun4i_usb_phy *phy = data->phys + i; char name[32]; + u32 val; if (data->cfg->missing_phys & BIT(i)) continue; @@ -928,6 +942,30 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) return PTR_ERR(phy->reset); } + phy->tx_tune = PHY_TX_TUNE_DEFAULT; + + snprintf(name, sizeof(name), "allwinner,usb%d-tx-amplitude", i); + if (!of_property_read_u32(np, name, &val)) { + if (val > PHY_TX_AMPLITUDE_MAX) { + dev_warn(dev, "%s out of range, clamping to %d\n", + name, PHY_TX_AMPLITUDE_MAX); + val = PHY_TX_AMPLITUDE_MAX; + } + phy->tx_tune &= ~PHY_TX_AMPLITUDE_MASK; + phy->tx_tune |= FIELD_PREP(PHY_TX_AMPLITUDE_MASK, val); + } + + snprintf(name, sizeof(name), "allwinner,usb%d-tx-slew-rate", i); + if (!of_property_read_u32(np, name, &val)) { + if (val > PHY_TX_SLEWRATE_MAX) { + dev_warn(dev, "%s out of range, clamping to %d\n", + name, PHY_TX_SLEWRATE_MAX); + val = PHY_TX_SLEWRATE_MAX; + } + phy->tx_tune &= ~PHY_TX_SLEWRATE_MASK; + phy->tx_tune |= FIELD_PREP(PHY_TX_SLEWRATE_MASK, val); + } + snprintf(name, sizeof(name), "usb%d_vbus", i); phy->vbus = devm_regulator_get_optional(dev, name); if (IS_ERR(phy->vbus)) { From 89956814164517b355e1cd3fe8eba81c3d7764db Mon Sep 17 00:00:00 2001 From: Evgeny Boger Date: Fri, 10 Jul 2026 03:24:30 +0300 Subject: [PATCH 3/4] ARM: dts: wirenboard7: raise USB0 PHY TX amplitude and slew rate With the default TX tune (minimum amplitude, slew rate 5) the USB gadget fails to enumerate at high speed on several tested hosts when connected directly (without a hub): the host never receives the ep0 IN data stage. Even when enumeration succeeds, bulk IN data gets corrupted under load. Set both tune fields to maximum: validated error-free on WB 7.4.2 with 60+ s of saturated bidirectional iperf traffic. Also change the (currently unparsed) usb_otg maximum-speed cap from full-speed to high-speed to document that the FS workaround from #122 is no longer wanted. Signed-off-by: Evgeny Boger Co-Authored-By: Claude Fable 5 --- arch/arm/boot/dts/allwinner/sun8i-r40-wirenboard72x.dtsi | 8 +++++++- arch/arm/boot/dts/allwinner/sun8i-r40-wirenboard74x.dtsi | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/allwinner/sun8i-r40-wirenboard72x.dtsi b/arch/arm/boot/dts/allwinner/sun8i-r40-wirenboard72x.dtsi index 05531e205128d..3743271d8a263 100644 --- a/arch/arm/boot/dts/allwinner/sun8i-r40-wirenboard72x.dtsi +++ b/arch/arm/boot/dts/allwinner/sun8i-r40-wirenboard72x.dtsi @@ -706,6 +706,12 @@ dr_mode = "otg"; wirenboard,mux-on-id-pin; + /* Maximum TX amplitude and slew rate: with the default TX tuning + * (minimum amplitude) some hosts fail to receive high-speed data + * from us: gadget enumeration fails and bulk data gets corrupted */ + allwinner,usb0-tx-amplitude = <3>; + allwinner,usb0-tx-slew-rate = <7>; + status = "okay"; }; @@ -980,7 +986,7 @@ &usb_otg { dr_mode = "peripheral"; status = "okay"; - maximum-speed = "full-speed"; + maximum-speed = "high-speed"; }; /* CPU RTC is useless since it doesn't have separate power supply. However we must keep it on to get proper LOSC for the rest of SoC.*/ diff --git a/arch/arm/boot/dts/allwinner/sun8i-r40-wirenboard74x.dtsi b/arch/arm/boot/dts/allwinner/sun8i-r40-wirenboard74x.dtsi index 508fc00c10a47..17235ce9ecbec 100644 --- a/arch/arm/boot/dts/allwinner/sun8i-r40-wirenboard74x.dtsi +++ b/arch/arm/boot/dts/allwinner/sun8i-r40-wirenboard74x.dtsi @@ -837,6 +837,12 @@ dr_mode = "otg"; wirenboard,mux-on-id-pin; + /* Maximum TX amplitude and slew rate: with the default TX tuning + * (minimum amplitude) some hosts fail to receive high-speed data + * from us: gadget enumeration fails and bulk data gets corrupted */ + allwinner,usb0-tx-amplitude = <3>; + allwinner,usb0-tx-slew-rate = <7>; + status = "okay"; }; From 9fbcfa881a2aabeec66253d4e08895dbdf12cc5c Mon Sep 17 00:00:00 2001 From: Evgeny Boger Date: Fri, 10 Jul 2026 03:24:31 +0300 Subject: [PATCH 4/4] Bump version Co-Authored-By: Claude Fable 5 --- debian/changelog | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/debian/changelog b/debian/changelog index f22248623dde7..8c3ab3f4ef35f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +linux-wb (6.18.22-wb7) stable; urgency=medium + + * phy-sun4i-usb: allow tuning PHY TX amplitude/slew rate via DT; + set both to maximum on Wiren Board 7 USB0: fixes high-speed gadget + enumeration failures and bulk data corruption on some hosts + + -- Evgeny Boger Fri, 10 Jul 2026 03:24:30 +0300 + linux-wb (6.18.22-wb6) stable; urgency=medium * scripts: fix wb6x-bootlet build