tree: 15a38cfc08dea0c2c50b2717cbc16f5a250c5d29 [path history] [tgz]
  1. meta/
  2. bind-tests.json
  3. BUILD.gn
  4. fusb302-controls-test.cc
  5. fusb302-controls.cc
  6. fusb302-controls.h
  7. fusb302-fifos-test.cc
  8. fusb302-fifos.cc
  9. fusb302-fifos.h
  10. fusb302-identity-test.cc
  11. fusb302-identity.cc
  12. fusb302-identity.h
  13. fusb302-info.json
  14. fusb302-protocol-test.cc
  15. fusb302-protocol.cc
  16. fusb302-protocol.h
  17. fusb302-sensors-test.cc
  18. fusb302-sensors.cc
  19. fusb302-sensors.h
  20. fusb302-signals-test.cc
  21. fusb302-signals.cc
  22. fusb302-signals.h
  23. fusb302-test.cc
  24. fusb302.bind
  25. fusb302.cc
  26. fusb302.h
  27. inspectable-types.h
  28. METADATA.textproto
  29. pd-sink-state-machine.cc
  30. pd-sink-state-machine.h
  31. README.md
  32. registers-test.cc
  33. registers.cc
  34. registers.h
  35. state-machine-base-test.cc
  36. state-machine-base.h
  37. typec-port-state-machine.cc
  38. typec-port-state-machine.h
  39. usb-pd-defs.cc
  40. usb-pd-defs.h
  41. usb-pd-message-objects-test.cc
  42. usb-pd-message-objects.h
  43. usb-pd-message-test.cc
  44. usb-pd-message-type-test.cc
  45. usb-pd-message-type.cc
  46. usb-pd-message-type.h
  47. usb-pd-message.h
  48. usb-pd-sink-policy-test.cc
  49. usb-pd-sink-policy.cc
  50. usb-pd-sink-policy.h
src/devices/power/drivers/fusb302/README.md

Driver for the onomni FUSB302 USB PD (Power Delivery) controller

Overall approach

This driver is currently targeted at serving the needs of the Khadas VIM3 supported by Fuchsia. The board uses a FUSB302BMPX as the USB PD controller on the USB Type C port that typically powers the board, and delegates the responsibility of driving the FUSB302B chip to the application processor that runs Fuchsia.

This setup leads to the following constraints.

  1. The driver must avoid getting a Hard Reset at all costs, because Hard Reset implies power cycling, which leads to a reboot.
  2. The driver must avoid breaking the USB Type C connection at all costs, because that would imply losing VBUS power, which leads to a reboot.
  3. It takes 5-10 seconds from the moment the VIM3 is powered on, which establishes the USB Type C connection, to the moment when this driver is brought up. We must attempt to re-negotiate a PD Contract at that point, in the hope that we can get more than the 15W (5V @ 3A) of power offered by the Type C connection's implicit contract.

We first use the FUSB302‘s automated power role detection, which figures out whether we’re a Source or a Sink (we're always a sink) and also figures out which of the two CC pins (CC1, CC2) in the Type C receptable is connected to the CC wire in the Type C cable. After power role detection completes, we configure the FUSB302 for the situation we detected. In particular, we point the BMC PHY to the correct CC pin.

Once we have a CC channel set up, we first wait for a relatively long time (currently 10 seconds) for a Source_Capabilities announcement. If we get an announcement, we can follow the message flow in the USB PD spec to get a PD contract. Type C ports on laptops tend to send Source_Capabilities announcements indefinitely, and this flow gets used there.

If we don‘t receive a Source_Capabilities, we try to issue a Soft Reset. When we succeed, this restarts the message flow that gets us to a PD Contract. Most power supplies only send Source_Capabilities announcements for the minimum time mandated by the USB PD spec, which is 7.5 seconds (nCapsCount = 50 messages every tTypeCSendSourceCap = 150 ms), and is not sufficient for us to get control of the FUSB302 chip. Some power supplies implement Soft Reset, and we’re able to get a PD contract in those cases. Other power supplies ignore the Soft Reset, in which case we remain with an implicit contract.

Source map

This driver combines two modules that should (and eventually) live in separate components: a USB PD (Power Delivery) implementation, and the code driving the FUSB302 chip.

The driver code has the following high-level structure.

  • registers has low-level descriptions for all the registers that make up the I2C API between the chip and the driver; the descriptions include documentation that represents our interpretation of the datasheet, and what we learned from experiments while bringing up the driver
  • fusb302-sensors covers registers that can be modeled as sensors, such as voltage meters; these always have a well-defined value
  • fusb302-signals covers registers that can be modeled as signals, which indicate that specific events have occurred
  • fusb302-controls covers registers that configure the chip's functional units, such as the switches that connect CC pins to various electrical blocks
  • fusb302-fifos covers the FIFOs used by the chip's BMC PHY
  • fusb302-protocol is built on top of fusb302-fifos and drives the chip's logic to present a full PD protocol layer implementation
  • fusb302-identity reports the chip version via Inspect and logs
  • fusb302 has “controller” logic that glues all the pieces above with the USB PD driver

The USB PD implementation has the following high-level structure.

  • usb-pd-defs defines geeneral concepts in the USB Type C and USB PD specs
  • usb-pd-message implements the USB PD message structure
  • usb-pd-message-type lists out PD message types; it is separated from usb-pd-message because the lists are rather bulky, and risk distracting the reader
  • usb-pd-message-objects implements the data object formats in the PD specs; currently, this is the minimum set of objects needed to establish a PD Contract and avoid getting a Hard Reset
  • state-machine-base extracts functionality common to the implementation of all state machines described by the USB PD spec
  • typec-port-state-machine implements the state machine that maintains the USB Type C Port State; it's mostly responsible for resetting the PD Policy Engine state machine when the Type C Port connection is established
  • pd-sink-state-machine implements the PD Policy Engine state machine; it's responsible for establishing and maintaining a PD Contract

Testing Tips

The biggest hurdle in testing this driver is that bugs tend to lead to Hard Reset. When the VIM3 is powered from the USB-C port, Hard Resets cause power cycling, which prevents the driver's logs from being transmitted to the development computer.

This hurdle can be mitigated using the following:

  • Power the VIM3 through the VIN port.
    • Ensure that your revision of the VIM3 board supports using the VIN and USB-C ports at the same time. Revision 13 and revision 14 support concurrent use. All board revisions below 13 deviate from the USB-C electrical specification when the VIN port is connected, and will likely damage USB-C equipment.
    • Build a charging circuit that plugs into the VIN port. An expedient approach entails splicing a VIN-to-VIN cable.
  • Connect to the VIM3 using both serial (usually via a Serial TTL to USB cable) and Ethernet cables; logs over serial come earlier, but Ethernet tends to carry more messages when the VIM3 loses power due to Hard Resets
  • When feasible, artificially delay the PD negotiation step that's failing, so the backlog of boot-time logs on the serial connection has time to drain.
  • A reliable USB PD sniffer is the only source of clues when the above fail. We recommend the “Twinkie” design, produced by the Chromium OS project. It reliably captures CC traffic, and delegates USB PD message decoding to a tool with a correct implementation.

References

The code contains references to the following documents.