Appendix · reference

Onsemi FUSB302B (USB Type-C / USB-PD)

BMC PHY + Type-C orientation detection driving sink-only PD r3.0 negotiation

Identity

PartON Semi FUSB302B (FUSB302BMPX)
RoleUSB Type-C controller: CC line detection + orientation, BMC PHY for USB-PD messaging, FIFO-backed message TX/RX
Bus / addressDTS &i2c4 addr 0x22; FreeBSD logs shifted addr 0x44 on iicbus3
GPIO / IRQINT_N on GPIO1_A2; IRQ-driven worker per 5ca6317 fusb302: switch from 10ms polling to IRQ-driven worker
DatasheetFUSB302B datasheet (ON Semi)
Pine64 wikiPinePhone Pro hardware
Schematicsheet 5 (USB-C / PD)

Status — ● working

Sink works end-to-end on every fresh boot: CC orientation, VBUS detection, Source_Capabilities decode, Request/Accept handshake, and a 9 V / 3 A contract that flows into the rk818 input current limit. The bring-up arc and live verification recipe are documented in essay 16 and the USB-C / PD recipe. The post-Hard_Reset recovery code is now in the overlay, but still needs a hardware soak to prove both received and locally-sent resets avoid PE_DISABLED. Source-role is bench-proven: on 2026-05-08, with hw.dwc3.force_host=1 and dev.fusb302.0.source_role=1, the phone enumerated a real Anker USB-C hub with a USB 2.0 hub IC, an ASIX AX88179A Gigabit-Ethernet adapter, a Norelsys NS1081 mass-storage bridge, and a Chicony USB keyboard. PD source-side messaging (PE_SRC_*, VDM/alt-mode) is still not implemented.

Driver

Linux splits the chip-specific FUSB302 driver from the generic TCPM state machine; we collapse both into a single file. That works for sink-only on a chip with this much I/O surface, but the cross-driver audit flagged two structural issues from the merge: PE_DISABLED is a FreeBSD-only state (Linux doesn’t have it; recovery is a timed sequence with PD_T_SAFE_0V), and the post-Hard_Reset BC_LVL=0 watchdog that triggers it was racing the source’s brief Rp drop. The overlay now writes FUSB302_RESET = RESET_PD on HARDRST, resets the BC_LVL watchdog state, adds PE_SNK_HARD_RESET_RECOVERY, and gives locally-sent Hard_Reset a timed PD_T_PS_HARD_RESET state. See the audit for register-level specifics.

PD_T_SENDER_RESP_MS = 100 remains intentionally generous for this polling driver. The sink-side Hard_Reset paths now carry the important timers explicitly: PD_T_PS_HARD_RESET_MS = 30 for Hard_Reset we send, and PD_T_SAFE_0V_MS = 650 for Hard_Reset received from a source.

Open work

Source-role: bench-proven

dev.fusb302.0.source_role=1 asks the power_supply layer to put rk818-charger into source mode, advertises Rp on both CC pins, and polls the source-side CC comparators as source_cc1 / source_cc2. The request is refused when the cached rk818 battery voltage is below dev.fusb302.0.source_min_voltage_mv so a weak battery cannot be asked to power a hub. f754656 typec: guard source role on battery voltage c3ed085 rk818: avoid live i2c in voltage callback

ebd8587 fusb302: return non-retry error for source guard

FUSB302 attach is now tolerant of transient I2C NACKs during boot: register reads and writes retry briefly before returning the bus error. This was added after a hub-attached reboot left the controller as an unattached unknown child on iicbus3 with Reset failed: 2.

4e5d139 fusb302: retry transient i2c transfer failures

On 2026-05-08, with kernel #203 (carrying 5a1cb12 dwc3: log host-attach state unconditionally for DWC3 host-attach diagnostics), hw.dwc3.force_host=1 set via nextboot, an Anker USB-C hub plugged in, and the battery at 3697 mV:

# sudo sysctl dev.fusb302.0.source_role=1
fusb3020: source mode: polling as DFP, advertising default Rp on CC1/CC2
rk818_pmu0: rk818: type-C role -> source (5V→VBUS) (DCDC_EN=0xff)
fusb3020: source attach: CC1=Ra CC2=Rd, advertising default Rp
ugen4.2: <VIA Labs, Inc. USB2.0 Hub>
ugen4.3: <ASIX AX88179A>
ugen4.4: <Norelsys NS1081>             umass0
ugen4.5: <CHICONY USB Keyboard>        hkbd0
ugen4.6: <AnkerInnovations Limited Anker USB-C Hub Device>

See appendix: USB-C source role and host-mode bring-up for the full receipt and decode.

Still scaffolded / open

Parity verification

Four changes from the 2026-04-30 cross-driver audit landed in src/sys/dev/iicbus/fusb302.c:

  1. INTA.HARDRST handler writes FUSB302_RESET = FUSB302_RESET_PD (BIT(1)) — flushes the chip’s protocol layer, matching Linux’s fusb302_pd_reset() (drivers/usb/typec/tcpm/fusb302.c).
  2. Same handler resets bc_lvl_zero_ticks = 0 so the BC_LVL=0 watchdog at line ~1296 doesn’t fire on the post-Hard_Reset CC blip and slam us to PE_DISABLED.
  3. New PE_SNK_HARD_RESET_RECOVERY state with PD_T_SAFE_0V_MS = 650 deadline before falling into PE_SNK_STARTUP. Collapses Linux’s SNK_HARD_RESET_SINK_OFF → SNK_HARD_RESET_SINK_ON → SNK_STARTUP (drivers/usb/typec/tcpm/tcpm.c::_tcpm_pd_hard_reset) into a single timed transition since we don’t toggle VBUS ourselves.
  4. Locally-sent PE_SNK_HARD_RESET now sends the chip Hard_Reset token once, waits PD_T_PS_HARD_RESET_MS = 30, then returns to PE_SNK_STARTUP; no more 5 ms busy-wait in the policy-engine tick.

Bench predicates:

Source-role / OTG (bench-proven 2026-05-08)

Bench recipe:

# kernel #203 or later (carries 5a1cb12 host-attach diagnostics)
sudo nextboot -e hw.dwc3.force_host=1
sudo reboot
# after boot:
sysctl hw.dwc3.force_host          # expect 1
sysctl dev.rk818_pmu.0.rk818_voltage_mv   # expect ≥ 3600 mV
sudo sysctl dev.fusb302.0.source_role=1
sleep 1
sysctl dev.fusb302.0.source_cc1 dev.fusb302.0.source_cc2 dev.fusb302.0.vbus_present
usbconfig

Expected post-source_role=1 state (Anker USB-C hub partner):

dev.fusb302.0.source_cc1: 1     (Ra — VCONN sense, full-feature C-to-C cable)
dev.fusb302.0.source_cc2: 2     (Rd — sink/UFP)
dev.fusb302.0.vbus_present: 1
dev.rk818_pmu.0.rk818_source_role: 1

dmesg:
fusb3020: source mode: polling as DFP, advertising default Rp on CC1/CC2
rk818_pmu0: rk818: type-C role -> source (5V→VBUS) (DCDC_EN=0xff)
fusb3020: source attach: CC1=Ra CC2=Rd, advertising default Rp

usbconfig:
ugen4.2: <USB2.0 Hub VIA Labs, Inc.>     ← downstream hub IC
ugen4.3: <AX88179 Gigabit Ethernet ...>
ugen4.4: <NS1081 Norelsys>
ugen4.5: <KU-0833 Keyboard Chicony ...>
ugen4.6: <Anker USB-C Hub Device ...>

Falsifiers:

Source-mode draws real current. With nothing plugged into the wall side of the hub, the phone is powering everything from the battery: a fresh 3731 mV reading dropped to 3595 mV inside roughly a minute of source_role=1 while the AX88179, hub IC, and keyboard were enumerated. For longer benches, feed the hub’s PD-in port from a wall charger instead of running on battery.