[PATCH v2 1/5] usb: tcpm: add core framework

Tim Harvey tharvey at gateworks.com
Wed Jul 17 20:13:04 CEST 2024


On Tue, Jul 16, 2024 at 7:00 PM Tim Harvey <tharvey at gateworks.com> wrote:
>
> On Fri, Jul 12, 2024 at 5:23 PM Tim Harvey <tharvey at gateworks.com> wrote:
> >
> > On Tue, Jun 4, 2024 at 9:36 AM Sebastian Reichel
> > <sebastian.reichel at 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.wang at rock-chips.com>
> > > Signed-off-by: Wang Jie <dave.wang at rock-chips.com>
> > > Signed-off-by: Sebastian Reichel <sebastian.reichel at 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?
>

Hi Sebastian,

I've determined why PD_DATA_REQUEST was causing my USB PD supply to
disable board power.... I had a bug in my implementation of
pd_transmit.

My stusb4500 driver is now working fine with your tcpm series and I
would be happy to submit it once your series is merged. Feel free to
cc me on follow-up submissions of your series so I can test with it.

Best Regards,

Tim


More information about the U-Boot mailing list