Radxa Rock 5B has a FUSB302 USB-C controller, which takes care of PD negotiation, cable orientation and informing about available Alt modes. The chip already has an upstream driver and is enabled in the arm64 defconfig, since it is quite common. Enabling support in Rock 5B is a bit tricky, since the board is usually powered from the USB-C port. If negotiation is not done correctly the board will reset because of a power-loss shortly after the driver is probed. On the EVB1 this is not an issue, since the board is not powered through USB-C.
Note, that properly handling FUSB302 is not just required for USB-PD, but also to get functional USB2/USB3/DP Altmode for the USB-C port on the Rock 5B.
Figuring this out would also be quite useful for other boards which use fusb302 (or other USB-C negotiators for their input) and I'd be interested in figuring this kind of usage out more generically. Libre Computer have some WIP patches around this topic.
Edit: I investigated and while I could see fusb302 related resets with Rock 5B with our current integration branch, that does not contain the patch reverted by the link. So that's yet another problem.
The kernel is lacking infrastructure for a proper handover. That is "discussed" (no response) in the linked message.
I also checked this against the USB-PD R2.0 V1.3 spec:
2.5.1 Source Operation
[...]
After a Hard Reset it is expected that the Port Partner will respond within tNoResponse. If this does not
occur then nHardResetCount further Hard Resets are carried out before the Source performs additional
Error Recovery steps, as defined in USB Type-C 1.2, by entering the ErrorRecovery state.
6.5.7 NoResponseTimer
[...]
For a non-responsive device, the Policy Engine in a Source May either decide to continue sending Source_Capabilities Messages or to go to non-USB Power Delivery operation and cease sending Source_Capabilities Messages.
6.5.17 Time Values and Timers
[...]
tNoResponse - min: 4.5 - max: 5.5 - units: seconds
So adding a driver in U-Boot is necessary to be compliant with the specification. The specification also mentions that soft resets can be upgraded to hard resets in some circumstances:
6.3.13 Soft Reset Message
[...]
If the error is not corrected by the Soft Reset, Hard Reset Signaling Shall be issued (see Section 6.7).
I couldn't find anything explicitly forbidding handling soft reset as hard reset, but it's obviously not what the specification had in mind. So I think the more important problem for now is adding a U-Boot driver for the fusb302.
I had a look at the Radxa U-Boot solution. In addition to the driver, they had to import TCPM framework. That in turn is using hrtimers for delayed state machine transitions. Rockchip introduced support for their timer IP and interrupts to handle that in U-Boot. I doubt that this will be upstreamable. Most delays are > 0.5 seconds with some being up to 10 seconds, so handling this via blocking delays is not acceptable. I think a workaround could be to register cyclic work in U-Boot using cyclic_register().
During out hardware enablement call, @kholk11 and @ehristev suggested doing this in the TF-A instead. That would require a way to share the I2C bus between the operating system and the firmware and requires defining new APIs to exchange the USB Type C information between the operating system and the firmware. So compared to the U-Boot solution it would be a giant amount of work. Apart from that doing it there makes the TF-A board specific. Ideally I would like to avoid that.
What I still need to check is the TCPM state machine itself to understand if it makes sense to start it in U-Boot and then have a communication pause between U-Boot stopping and the kernel starting. It would be bad if that pause can also end up in a hard reset from the power-supply.
I hacked some U-Boot code together, which initializes fusb302 and marks the fusb302 DT node as okay (U-Boot branch). With that the system boots up fine using our existing kernel branch. The U-Boot code still needs lot's of cleanups, but it is already very good progress.
The trick to reduce the amount of communication needed, allowing hand-over from U-Boot to the Kernel is this switching to low-power mode. The U-Boot driver prints this message for that:
CC activities detected, delay handlingCC activities detected, delay handlingCC activities detected, delay handlingCC activities detected, delay handlingCC activities detected, delay handlingCC activities detected, delay handlingPD chip enter low power mode