Files
openipc-builder/devices/ssc338q_fpv_openipc-urllc-aio/USB-HS-INVESTIGATION.md
T

25 KiB
Raw Blame History

RTL8812EU enumerating at 12 Mbit/s on Sstar-ehci-1 — investigation record

Device: ssc338q_fpv_openipc-urllc-aio (HiLink URLLC, SSC338Q / infinity6e). Radio: Realtek RTL8812EU, USB ID 0bda:a81a, directly attached to the SSC338Q USB 2.0 EHCI port (Sstar-ehci-1).

Fixed observations (treated as inputs, not re-derived here)

  • The radio repeatedly enumerates at 12 Mbit/s (full speed) after USB unbind/rebind cycles.
  • The active device tree reports dpdm_swap = <0> and power-enable-pad = <PAD_UNKNOWN> (0xffff).
  • Verified on hardware (2026-10, Piotr): the full soc:Sstar-ehci-1 platform-driver unbind/bind cycle (step 5 below) was performed over Ethernet, waited out, and /sys/bus/usb/devices/1-1/speed still returned 12. A complete HCD/UTMI re-initialization therefore does not restore high-speed negotiation on this board.
  • Verified on hardware (2026-10, Piotr): changing the input supply capacity did not improve negotiation. Supply-headroom tuning is ruled out.
  • Verified on hardware (2026-10, Piotr): the radio is a custom carrier/module assembly, not a drop-in USB dongle: a four-wire host harness/pad connection, two RF pigtails, and visible local regulation on the carrier.
  • Verified on hardware (2026-10, Piotr): 5.13 V measured directly at the module input, inside the common 4.75–5.25 V input range. The earlier "3.3 V fed into the 5 V input" hypothesis is therefore ruled out at module ingress (upstream of the carrier's local regulation).
  • Verified on hardware (2026-10, Piotr): each USB data net was physically traced as SSC338Q-side -> approximately 100 ohm series resistor -> RTL8812EU-module D+ or D-; each component measured about 100 ohm across its own endpoints with all power removed. These are two separate per-line series resistors, not one 100-ohm differential termination.
  • RF/FEC configuration is not a USB fix and is out of scope for this issue.
  • This document contains no credentials, pairing or RF-access material.

Conclusion (current fault-domain classification)

Combined with the exact vendor EHCI/UTMI source audit below (which found no HiLink-specific software discrepancy in anything this overlay or the shipped kernel build controls), the verified on-hardware results above eliminate the remaining software-adjacent candidates that are cheap to test:

  • Ruled out: wifibroadcast/OpenIPC configuration, RF/FEC settings, ordinary userspace timing, a simple USB-device rebind, a full HCD/UTMI re-initialization (done on hardware, no change), input-supply-capacity tuning (done on hardware, no change), and wrong-voltage-at-module-ingress (measured 5.13 V at the input, within the 4.75–5.25 V range).
  • Remaining fault domain: the USB high-speed physical path / signal integrity / rework — D+/D− routing and symmetry across the carrier, harness/pads and intervening components, controlled impedance and stubs, series/ESD/common-mode components on the pair, connector and solder integrity, or PHY-side / device-side silicon-level hardware — exactly the boundary detailed in the hardware section below. The supply findings above rule out only those two specific points: power quality downstream of the measured input — supply noise/ripple and the carrier's local regulator output — remains untested and stays inside this open fault domain.

Two caveats stay attached to this classification: it does not prove that every conceivable undocumented analog register in the vendor PHY block is irrelevant (the audited paths cover what the shipped source programs, not the full register space), and it does not claim any high-speed success — the fault is unresolved; only its domain is now sharply bounded.

First concrete physical candidate: the traced per-line ~100 ohm series resistors (see the hardware section below). FS signaling at 12 Mbit/s is edge-slow and tolerant, while HS chirp/negotiation is amplitude- and timing-critical, so excessive series damping on both lines is consistent with exactly this failure signature — FS survives, HS chirp is missed. This is a hypothesis with a matching signature, not a proven root cause, and the commonly seen external USB 2.0 series damping practice (roughly 15-33 ohm) is not a substitute for the exact SSC338Q PHY/reference-design requirement, which is not documented in this repository.

Operating posture while the fault stands: keep the existing 4096 kbit/s limit appropriate to full-speed operation; do not raise it on the assumption of high-speed throughput until HS is actually demonstrated.

Audited sources

Audited 2026-10-02. Everything the firmware ships is stock upstream of this builder overlay — the per-device delta in this repository carries no USB configuration at all. Exact provenance used for the audit:

Artifact Source Ref
Kernel github.com/openipc/linux, branch sigmastar-infinity6e branch tip 97b7fc4e at audit time, Linux 4.9.84 (the defconfig pins the branch, not the SHA, so later builds may move)
Kernel ref resolution OpenIPC/firmware general/external.mk OPENIPC_KERNEL := $(OPENIPC_SOC_VENDOR)-$(OPENIPC_SOC_FAMILY)
Kernel config OpenIPC/firmware br-ext-chip-sigmastar/board/infinity6e/infinity6e-ssc012b.config selected by this device's defconfig (BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE); moving master, HEAD 1b0d5e2 at audit time
DTB arch/arm/boot/dts/infinity6e-ssc012b-s01a.dtb, built from the in-tree DTS and compiled into the kernel Image (CONFIG_SS_BUILTIN_DTB=y, CONFIG_SS_DTB_NAME="infinity6e-ssc012b-s01a") same kernel ref
WiFi driver OpenIPC package rtl88x2eu-openipc → github.com/libc0607/rtl88x2eu-20230815 (HEAD) + one cflags patch general/package/rtl88x2eu-openipc/rtl88x2eu-openipc.mk
Builder overlay this repository, devices/ssc338q_fpv_openipc-urllc-aio/ working tree

The bootloader does not hand the kernel an FDT on this platform: with CONFIG_SS_BUILTIN_DTB=y, arch/arm/kernel/devtree.c:281-299 falls back to the DTB embedded in the Image and merges the bootloader's ATAGs (memory, cmdline) into it. The audited DTS is what the running kernel sees.

Active DT node (matches the reported runtime state)

arch/arm/boot/dts/infinity6e.dtsi:818-828:

Sstar-ehci-1 {
    compatible = "Sstar-ehci-1";
    clocks = <&CLK_utmi>;
    camclk = <CAMCLK_utmi>;          /* compiled out: CONFIG_CAM_CLK is not set */
    interrupts = <GIC_SPI INT_IRQ_UHC IRQ_TYPE_LEVEL_HIGH>;
    dpdm_swap=<0>;
    power-enable-pad = <PAD_UNKNOWN>;
    status = "ok";
};

PAD_UNKNOWN = 0xFFFF (drivers/sstar/include/infinity6e/gpio.h:150). The board DTS infinity6e-ssc012b-s01a.dts applies no USB override, and CONFIG_SS_BUILTIN_UNFDT is not set, so the kernel Image's builtin DTB is the only device tree in play (see the boot path above). This matches the runtime facts exactly.

Kernel config (USB-relevant, infinity6e-ssc012b.config)

  • CONFIG_USB_EHCI_HCD=y built-in; xHCI/OHCI/DWC2/DWC3 disabled; USB 3.0 node unused for this radio.
  • CONFIG_MP_USB_MSTAR=y — enables the Sstar patch set in drivers/usb/host/ehci-hcd.c and drivers/usb/core/hub.c.
  • # CONFIG_SS_USB_LOWPWR_SUSPEND is not set; no USB PHY framework drivers (all UTMI handling is inside the Sstar EHCI driver).
  • CONFIG_USB_ANNOUNCE_NEW_DEVICES=y — dmesg reports the enumerated speed.

HS chirp / squelch / reset / PHY-tuning paths (as built)

All tuning is compile-time; there are no runtime knobs in this repo.

  1. Probe-time UTMI init — drivers/sstar/usb/host/ehci-mstar.c, Titania3_series_start_ehc() (lines 232-579), called from ehci_hcd_mstar_drv_probe() for soc:Sstar-ehci-1 (call at line 681):
    • USBC 0x0a/0x28 handshake resets the UHC MAC (lines 297-298).
    • CA (RX calibration) start/poll at UTMI 0x3c with a "CA Fail" warning if the result reads all-ones or all-zeros (lines 330-339).
    • Squelch/disconnect level: UTMI_DISCON_LEVEL_2A = 0x62 (ehci-mstar.h:310) written to UTMI 0x2a (lines 323-328, 396-397).
    • Chirp source select UTMI 0x15 bit5 (line 387); new-HW chirp overwrite cleared at UTMI 0x40 bit4 (line 394). ENABLE_NEW_HW_CHRIP_PATCH is not defined, so the chirp-detect-level register UTMI 0x42 keeps its hardware default.
    • Eye/ TX tuning: UTMI_EYE_SETTING_2C..2F = 0x10,0x02,0x00,0x81 (ehci-mstar.h:355-361) at UTMI 0x2c..0x2f (lines 406-410).
    • ENABLE_HS_CONNECTION_FAIL_INTO_VFALL_ECO is on (ehci-mstar.h:152), USBC 0x11 bit1 (line 453) — the known "HS connection fails into VFALL" mitigation is active.
    • DP/DM swap: _USB_UTMI_DPDM_SWAP_P0 = 0 (ehci-mstar.h:294) and dpdm_swap=<0> in DT (probe lines 674-678 OR the DT value into flag) both agree: no swap. UTMI 0x0b bit5 stays clear.
    • _USB_ANALOG_RX_SQUELCH_PATCH = 0 (ehci-mstar.h:254-258): the CA-calibration-based squelch adjustment is compiled out.
  2. Per-port-reset chirp window — drivers/usb/core/hub.c hub_port_reset() (lines 3124-3216), the _USB_HS_CHIRP_PATCH block, runs on every root-hub port reset for USB 2.0:
    • Before asserting reset: eye parameters zeroed (UTMI 0x2c..0x2f) and squelch switched to 0x80 at UTMI 0x2a (line 3168) — the value the Sstar chirp patch uses inside the reset window to catch a weak device chirp.
    • After the reset: eye parameters and squelch 0x62 restored, then a UTMI TX/RX software-reset pulse (UTMI 0x06 bits1:0, lines 3207-3212).
    • The FS/HS verdict comes from the EHCI port status alone. The speed-report cross-check against the UHC 0x84/0x85 registers is guarded by _USB_SPEED_REPORT_RESET_PATCH, which is referenced at hub.c:3007 but never defined anywhere — that block is compiled out in this build.
  3. Full-speed fallback latch — hub.c "bad dev" retry (lines 6113-6165): after repeated failed enumerations the driver sets UHC 0x40 bit7 ("force full speed", line 6138, via hcd->ehc_base); it is cleared on root-hub reinit when the device disconnects (lines 2353, 5557-5559). A device that enumerates successfully at FS from insertion did not need this latch — the port verdict itself was FS.
  4. VBUS gating — drivers/sstar/usb/host/infinity6e/usb_pad.c Enable_USB_VBUS() (lines 49-106): the DT property is present (0xffff), so the fallback default (PAD_PM_GPIO2) is not used; the value is truncated to (unsigned char)0xffff = 255 (line 80). 255 is out of range on this SoC — GPIO_NR = 127 (drivers/sstar/include/infinity6e/gpio.h:149, range-checked in mhal_pinmux.c:2054) — so gpio_request(255) fails and the function returns early. The probe ignores the return value (ehci-mstar.c:680). Net effect: no kernel-side VBUS gate; VBUS to the module is board-hardwired. Consistent with the device enumerating at all.
  5. Clocks — nothing in Linux consumes CLK_utmi/CAMCLK_utmi for this controller: the EHCI driver contains no clock/camclk code at all, so the UTMI reference clock state is inherited from the bootloader. There is no in-Linux analog power-cycle; the closest in-kernel equivalent is a full HCD unbind/rebind (below), which re-runs the whole Titania3_series_start_ehc() block including CA calibration.
  6. WiFi driver — rtl88x2eu-20230815 os_dep/linux/usb_intf.c (lines 637-661) passively records pusbd->speed (USB_SPEED_FULL → RTW_USB_SPEED_1_1). There is no module parameter, retry or force-HS logic in the Realtek driver; at most it adapts to the reported speed (e.g. USB_FULL_SPEED_BULK_SIZE in include/usb_ops.h:128-145). The speed is decided entirely by the host controller/PHY.

Why no device-specific software discrepancy was found (in this repository)

  • This repository's per-device delta for ssc338q_fpv_openipc-urllc-aio contains no USB-host configuration anywhere: the defconfig selects packages/flash size only, load_sigmastar drives the camera pipeline only, the overlay seeds WiFi/wifibroadcast config, and the exclude list only trims rootfs files.
  • The defconfig is byte-identical to the closest sibling device (ssc338q_fpv_openipc-mario-aio), so there is no per-device divergence to correct.
  • Kernel, builtin DTB and kernel config are stock openipc/linux sigmastar-infinity6e / OpenIPC/firmware artifacts; the DT state (dpdm_swap=0, power-enable-pad=0xffff) matches the reported runtime state, i.e. the firmware built is the firmware audited.
  • The FS fallback mitigations that exist in the kernel (chirp-window squelch 0x80, VFALL ECO) are compiled in and active for this build; the speed-report cross-check is compiled out (undefined macro), which weakens detection of a mis-reported speed but cannot by itself cause one.
  • Therefore a device-specific software correction within this repository is not justified by the evidence. A real fix would be a kernel-side change (openipc/linux driver/DT) or hardware — both outside this overlay's scope.

Candidate corrections considered and rejected

  • dpdm_swap=<1>: a swapped D+/D- pair would break full-speed enumeration too (same pair, same polarity); the device enumerates at FS, so polarity is correct. Flipping it would kill enumeration entirely. Rejected.
  • Enable _USB_ANALOG_RX_SQUELCH_PATCH or change UTMI_DISCON_LEVEL_2A / eye settings: driver-source macro changes in openipc/linux, with no in-repo evidence to pick values; the chirp window already uses the most sensitive squelch (0x80). Rejected without on-hardware UTMI measurements.
  • power-enable-pad → a real pad: VBUS is evidently board-hardwired (device enumerates with the property at PAD_UNKNOWN); pointing the gate at a wrong pad risks switching VBUS off. Rejected.
  • WiFi driver module options: none exist that influence enumeration speed (driver is passive). Rejected.

Assembly as observed (2026-10, Piotr): the radio is a custom carrier/module — not a drop-in dongle — connected to the host by a four-wire harness/pad connection, with two RF pigtails and visible local regulation on the carrier. The pad assignments have not been documented yet; nothing below assumes one.

With the software and software-adjacent candidates ruled out (see the conclusion above), the remaining fault domain is the USB high-speed physical path / signal integrity / rework, explicitly outside software scope:

  • D+/D- pair routing on the HiLink carrier and through the four-wire harness: continuity and symmetry from the SSC338Q pads to the module pads; controlled impedance along the pair; stubs or test points hanging off it; series resistors / ESD protection / common-mode chokes or other intervening components; via, connector/harness and solder joint integrity.
  • HS chirp failure with FS working is the classic marginal-analog signature: the same pair carries FS traffic fine while the HS chirp (a short, amplitude-critical burst at reset) is missed by the host squelch detector.

Next physical gate (before any rework):

  1. Macro photographs of both sides of the carrier/module — not yet reported.
  2. Identify all four host pads — determine which are VBUS, GND, D+, D- (the four-wire harness implies the classic set, but the actual assignment must come from tracing, not assumption) — not yet reported in full; the two data nets and their series resistors have been traced (see the fixed observations above).
  3. Trace D+/D- end to end, identifying every intervening component — series resistors, ESD arrays, common-mode chokes, vias, connectors, harness wires — and where the pair leaves the board. Status: performed for both data nets — each net is SSC338Q-side -> ~100 ohm series resistor -> module D+/D-, each resistor measuring ~100 ohm across its own endpoints, de-energized. No other intervening component was reported on the data nets.

Safety rule for all continuity/ohmmeter work: only with all power removed and rails discharged (unplug, then verify the rails are at 0 V before touching meter probes to pads). No powered measurements are proposed at this stage.

Gated, reversible experiment: reduce per-line series damping

Rationale: if the ~100 ohm per-line series resistors over-damp the pair, reducing the effective per-line series resistance by roughly four times (100 ohm -> ~25 ohm) into the range of common external USB 2.0 practice may let the HS chirp/eye reach the host squelch/timing margins again. This is a bounded, fully reversible test, not a repair commitment: the target value below is an example chosen from common practice, not the documented SSC338Q PHY/reference-design requirement, which must be confirmed from vendor material if the test succeeds.

Pre-flight gate (no soldering before this is done):

  1. Confirm the two resistors' package size and mark their exact locations (photograph before touching anything).
  2. Confirm the workmanship/ESD plan for soldering on the carrier.

Experiment (reversible — nothing is removed, parts are added in parallel):

  1. With all power removed and rails discharged and verified at 0 V (same rule as above). The work setup itself must not be able to feed voltage onto the unpowered board — including through the soldering iron's supply path — so use an isolated or battery-powered iron or equivalent isolation. Solder one matched resistor in parallel across each existing 100 ohm part — D+ and D- must be treated identically.
  2. Example value: 33 ohm in parallel with 100 ohm gives an effective (33 x 100) / (33 + 100) = 3300 / 133 = 24.8 ohm per line (~25 ohm). Any parallel pair follows R_eff = (R1 x R2) / (R1 + R2); keep the same value on both lines.
  3. Inspect under magnification for bridges, solder balls or damage to the parts and neighbours; the two lines must look identical.
  4. Before restoring power, measure each modified net again (de-energized) and confirm both read the same effective value, within part tolerance.
  5. Restore power only after inspection and run a fresh USB enumeration check (cat /sys/bus/usb/devices/1-1/speed).

Acceptance criterion: actual 480 Mbit/s negotiation. The enumeration result is the only judge of this test: no final line impedance or eye-quality outcome is assumed without signal-integrity measurement (a later diagnostic above). If behaviour regresses in any way or HS is not achieved, revert immediately: remove the parallel parts to restore the original ~100 ohm per line, and record what was observed. Until HS is actually demonstrated, keep the 4096 kbit/s operating limit (see the conclusion) regardless of this experiment.

Further isolation diagnostics, only after the gate above (all of them need rework access — the radio is pad-connected, not socketed, so this may mean a temporary rework socket or piggyback harness):

  • Try a known-good HS USB device (any USB 2.0 flash disk) on the same host pads. HS on the disk but not on the radio points at the carrier/module side; FS on both points at the board-side pair.
  • Try the RTL8812EU carrier on a different known-good HS host (a PC). HS there isolates the fault to this board's physical path.
  • With suitable equipment, capture the HS chirp amplitude/eye at the host pads against the USB 2.0 electrical limits.

Any board rework (series resistor changes, pair shortening, shielding) invalidates prior software observations; re-verify from the on-device commands below after any hardware change.

Evidence status: the platform-driver re-probe (step 5 below), the input-supply-capacity change, the module-input voltage measurement, and the per-line series-resistor tracing (de-energized resistance checks) were performed on hardware (2026-10, Piotr) — none of the software-adjacent steps improved negotiation, the ingress voltage is in range, and the traced topology is as recorded above. The parallel-resistor experiment has not been performed yet; the register-read diagnostics (steps 1-4 below) have not been reported yet. No HS negotiation has been observed at any point, and this document does not claim any.

On-device verification (read-only diagnostics; step 5 re-probe already completed on hardware)

Run from a root shell on the device over a link that is not the USB radio (Ethernet or serial console — see the wlan0 warning in step 5). All register reads are read-only devmem accesses; do not write UTMI/USBC/UHC registers from userspace (a write can wedge the bus until reboot). Steps 1-4 have not been run/reported on the affected board yet and remain the cheapest way to capture register-level evidence (CA calibration result, squelch value, line state, force-FS latch) alongside the hardware work.

Register addresses (physical; the RIU window maps virtual 0xFD200000 to physical 0x1F200000 — MS_IO_OFFSET 0xDE000000, drivers/sstar/include/ms_platform.h:24, plus registers.h:37-38). Register number n sits at byte offset 2*n, except odd n which sits at 2*n - 1 (exactly what hcd_readb does, hub.c:116-129). All reads are byte or 16-bit reads at these byte addresses.

Block Base (physical) Derived from
UTMI0 0x1F284200 _MSTAR_UTMI0_BASE = 0xFD200000 + 0x42100*2 (ehci-mstar-chip.h:37)
USBC0 0x1F284600 + 0x42300*2 (ehci-mstar-chip.h:39)
UHC0 (EHCI) 0x1F284800 + 0x42400*2 (ehci-mstar-chip.h:40)
  1. Current enumerated speed
    cat /sys/bus/usb/devices/*/speed        # expect 12 (FS symptom) or 480 (HS fixed)
    dmesg | grep -E 'new (full|high)-speed USB device'
    
  2. Force-full-speed latch check (stuck FS from a past failed HS enum)
    devmem 0x1F284880 8                     # UHC+0x40 bit7: 0x00/0x80
    
    Expected if healthy: bit7 clear. If bit7 is set, a previous enumeration failure latched FS; disconnect/reconnect the module's power (the root-hub reinit on disconnect clears it) and repeat.
  3. Port / line state (all UHC0 = EHCI bank, hcd->ehc_base; bit semantics as used by the driver: hub.c:4998 enable=bit2, urb.c:532 connect=bit0, message.c:88 csc=bit1, hub.c:5801-5802 line state)
    devmem 0x1F284860 8                     # UHC+0x30: bit0 connect, bit1 csc, bit2 enable
    devmem 0x1F284881 8                     # UHC+0x41: bits2:1 line state (odd reg -> 2n-1)
    devmem 0x1F284908 8                     # UHC+0x84: bit7 of the speed report
    devmem 0x1F28490A 8                     # UHC+0x85: bits3:0 of the speed report
    
    Speed-report composition (hub.c:3007-3030; the kernel-side cross-check is compiled out — these are raw hardware registers): spd = (bit7 of UHC+0x84) | ((UHC+0x85 & 0xf) << 1); 0x0c = high speed, 0x06 = full speed.
  4. UTMI tuning as left by the driver
    devmem 0x1F284254 8                      # UTMI+0x2a squelch: expect 0x62 idle
    devmem 0x1F284278 16                     # UTMI+0x3c CA calibration (16-bit)
    
    CA_FAIL signature (as the driver checks it, ehci-mstar.c:337-339): the 16-bit value at UTMI+0x78 masked with 0xFFF0 reading 0x0000 or 0xFFF0 — a failed RX calibration suppresses chirp detection and points at power/analog, not software. dmesg also prints WARNING: CA Fail !!.
  5. Full PHY re-init (in-kernel equivalent of a power cycle) — COMPLETED, no improvement (2026-10, Piotr: performed over Ethernet, device still enumerated at 12 Mbit/s). Kept here for reproducibility:
    ls /sys/bus/platform/drivers/Sstar-ehci-1/          # note the device name
    echo <device> > /sys/bus/platform/drivers/Sstar-ehci-1/unbind
    echo <device> > /sys/bus/platform/drivers/Sstar-ehci-1/bind
    
    Safety: wlan0 on this device is the USB radio itself (8812eu, S40network:6), so unbinding the EHCI takes wlan0 down — run this from Ethernet or a serial console, never over the USB radio's link. The radio disappears and re-enumerates after bind; if wlan0 does not come back on its own, re-run the network init (/etc/init.d/S40network restart) rather than poking WiFi config. Rebind re-runs Titania3_series_start_ehc() (USBC reset handshake, CA calibration, squelch/eye init) and then re-enumerates the radio. Expected dmesg on HS success: Sstar-ehci-1 H.W init, [USB] init squelch level 0x.. and a new high-speed USB device number N line. Re-running steps 1-4 afterwards gives the post-init register state. Observed on hardware: the device re-enumerated at full speed again.
  6. True analog power cycle — only a full board re-power removes power from the UTMI PHY and the module (VBUS is hardwired; power-enable-pad is not driven by Linux). Note this is distinct from the already-tested input-supply-capacity change, which alters headroom but was recorded as not improving negotiation. Power-cycle, then repeat steps 1-5 and compare: identical FS results across cold boot, re-probe and replug indicate the condition is stable (analog/hardware), while an occasional HS success would point at marginal timing.