On Fri, Jul 12, 2024 at 5:23 PM Tim Harvey <thar...@gateworks.com> wrote: > > On Tue, Jun 4, 2024 at 9:36 AM Sebastian Reichel > <sebastian.reic...@collabora.com> wrote: > > > > This adds TCPM framework in preparation for fusb302 support, which can > > handle USB power delivery messages. This is needed to solve issues with > > devices, that are running from a USB-C port supporting USB-PD, but not > > having a battery. > > > > Such a device currently boots to the kernel without interacting with > > the power-supply at all. If there are no USB-PD message replies within > > 5 seconds, the power-supply assumes the peripheral is not capable of > > USB-PD. It usually takes more than 5 seconds for the system to reach > > the kernel and probe the I2C based fusb302 chip driver. Thus the > > system always runs into this state. The power-supply's solution to > > fix this error state is a hard reset, which involves removing the > > power from VBUS. Boards without a battery (or huge capacitors) will > > reset at this point resulting in a boot loop. > > > > This imports the TCPM framework from the kernel. The porting has > > originally been done by Rockchip using hardware timers and the Linux > > kernel's TCPM code from some years ago. > > > > I had a look at upgrading to the latest TCPM kernel code, but that > > beast became a lot more complex due to adding more USB-C features. > > I believe these features are not needed in U-Boot and with multiple > > kthreads and hrtimers being involved it is non-trivial to port them. > > Instead I worked on stripping down features from the Rockchip port > > to an even more basic level. Also the TCPM code has been reworked > > to avoid complete use of any timers (Rockchip used SoC specific > > hardware timers + IRQ to implement delayed work mechanism). Instead > > the delayed state changes are handled directly from the poll loop. > > > > Note, that (in contrast to the original Rockchip port) the state > > machine has the same hard reset quirk, that the kernel has - i.e. > > it avoids disabling the CC pin resistors for devices that are not > > self-powered. Without that quirk, the Radxa Rock 5B will not just > > end up doing a machine reset when a hard reset is triggered, but will > > not even recover, because the CPU will loose power and the FUSB302 > > will keep this state because of leak voltage arriving through the RX > > serial pin (assuming a serial adapter is connected). > > > > This also includes a 'tcpm' command, which can be used to get > > information about the current state and the negotiated voltage > > and current. > > > > Co-developed-by: Wang Jie <dave.w...@rock-chips.com> > > Signed-off-by: Wang Jie <dave.w...@rock-chips.com> > > Signed-off-by: Sebastian Reichel <sebastian.reic...@collabora.com> > > --- > > Makefile | 1 + > > cmd/Kconfig | 7 + > > cmd/Makefile | 1 + > > cmd/tcpm.c | 142 ++ > > drivers/usb/Kconfig | 2 + > > drivers/usb/tcpm/Kconfig | 8 + > > drivers/usb/tcpm/Makefile | 3 + > > drivers/usb/tcpm/tcpm-internal.h | 174 +++ > > drivers/usb/tcpm/tcpm-uclass.c | 102 ++ > > drivers/usb/tcpm/tcpm.c | 2251 ++++++++++++++++++++++++++++++ > > include/dm/uclass-id.h | 1 + > > include/usb/pd.h | 516 +++++++ > > include/usb/tcpm.h | 99 ++ > > 13 files changed, 3307 insertions(+) > > create mode 100644 cmd/tcpm.c > > create mode 100644 drivers/usb/tcpm/Kconfig > > create mode 100644 drivers/usb/tcpm/Makefile > > create mode 100644 drivers/usb/tcpm/tcpm-internal.h > > create mode 100644 drivers/usb/tcpm/tcpm-uclass.c > > create mode 100644 drivers/usb/tcpm/tcpm.c > > create mode 100644 include/usb/pd.h > > create mode 100644 include/usb/tcpm.h > > > > Hi Sebastian, > > I have a board that has a STMicroelectronics STUSB4500 USB PD sink > controller [1] on it that I would be interested in writing a driver > for using this TCPM class. This device is a USB PD sink controller > which has a nice 'auto-run' feature that has 3 updatable NVM backed > PDO's that it negotiates on its own with the the PD source so that you > get basic functionality without needing a driver. > > I am struggling a bit to get the stusb4500 working in a driver that > fits into your framework and I think its the fact that the STUSB4500 > has no buffering capability so the processing of messages during the > PD negotiation is extremely timing critical and I'm often missing the > SRC_CAP message. To help me understand the correct operation of the > tcpm state machine can you by chance enable DEBUG in fusb302.c and > tcpm.c and share the output with me? > > I'm trying to understand the required state machine transitions. It > looks to me like for a SINK the state machine should go like this: > INVALID_STATE -> SNK_UNATTACHED > SNK_UNATTACHED -> SNK_ATTACH_WAIT > ^^^ during tcpm_init > SNK_ATTACH_WAIT -> SNK_DEBOUNCED > SNK_DEBOUNCED -> SNK_ATTACHED > SNK_ATTACHED -> SNK_STARTUP > SNK_STARTUP -> SNK_DISCOVERY > SNK_DISCOVERY -> SNK_WAIT_CAPABILITIES > > At this point drvops->set_pd_rx(on) is called to allow your driver to > accept PD messages but I don't understand the following logic: > case SNK_WAIT_CAPABILITIES: > ret = drvops->set_pd_rx(dev, true); > if (ret < 0) { > tcpm_set_state(dev, SNK_READY, 0); > break; > } > /* > * If VBUS has never been low, and we time out waiting > * for source cap, try a soft reset first, in case we > * were already in a stable contract before this boot. > * Do this only once. > */ > if (port->vbus_never_low) { > port->vbus_never_low = false; > tcpm_set_state(dev, SOFT_RESET_SEND, > PD_T_SINK_WAIT_CAP); > } else { > tcpm_set_state(dev, hard_reset_state(port), > PD_T_SINK_WAIT_CAP); > } > > Why on error would you go straight to SNK_READY? The comment indicates > a return value of >=0 is a timeout. Why on success would you either go > straight to a hard/soft reset? What does fusb302.c return from > set_pd_rx and do after that call?
Hi Sebastian, I've managed to make it further through the TCPM state machine with my stusb4500 driver. I figured out that the intended operation of SNK_WAIT_CAPABILITIES is to send a soft reset which gets the PD SRC to send SRC_CAP which transitions to SNK_NEGOTIATE_CAPABILITIES then the PD SRC sends an ACCEPT which transitions to SNK_TRANSITION_SINK then a PS_READY which transitions to SNK_READY. I am seeing that when a PD_DATA_REQUEST to negotiate a contract my board loses power which does not happen if the STUSB4500 is allowed to run in its auto-run mode. Do you know if there is some sort of power glitch that is expected when a PD_DATA_REQUEST is sent from the SNK to the SRC that must be managed with hold-up caps or something? Best Regards, Tim