mbox series

[v2,0/5] FUSB302 USB-C controller support

Message ID 20240604163546.60225-1-sebastian.reichel@collabora.com
Headers show
Series FUSB302 USB-C controller support | expand

Message

Sebastian Reichel June 4, 2024, 4:33 p.m. UTC
Hi,

On ROCK 5B power is usually supplied via it's USB-C port. This port has the
data lines connected to RK3588, VBUS connected to the input regulator and
CC pins connected to FUSB302. FUSB302 is a USB-C controller, which can be
accessed via I2C from RK3588. The USB-C controller is needed to figure out
the USB-C cable orientation, but also to do USB PD communication. Thus it
would be great to enable support for it in the operating system.

But the USB-PD specification requires, that a device reacts to USB-PD messages
send by the power-supply within around 5 seconds. If that does not happen the
power-supply assumes, that the device does not support USB-PD. If a device
later starts sending USB-PD messages it is considered an error, which is solved
by doing a hard reset. A USB-PD hard reset means, that all supply voltages are
removed for a short period of time. For boards, which are solely powered
through their USB-C port, like the Radxa Rock 5B, this results in an machine
reset. This is currently worked around by not describing the FUSB302 in the
kernel DT, so nothing will ever speak USB-PD on the Rock 5B. This means

1. the USB-C port cannot be used at all
2. the board will be running via fallback supply, which provides limited
   power capabilities

In order to avoid the hard reset, this adds FUSB302 support to U-Boot, so
that we react to the power-supply's queries in time. The code, which is
originally from the Linux kernel, consists of two parts:

1. the tcpm state machine, which implements the Type C port manager state
   machine as described in the USB PD specification
2. the fusb302 driver, which knows about specific registers

Especially the first part has been heavily modified compared to the
kernel, which makes use of multiple delayed works and threads. For this
I used a priorly ported version from Rockchip, removed their hacks and
any states not necessary in U-Boot (e.g. audio accessory support).

Changes since PATCHv1:
 * tcpm: split uclass specific code to tcpm-uclass
 * tcpm_print_info: move printing part to cmd/tcpm.c
 * tcpm_print_info: report more information
   - PD revision
   - Cable orientation
   - Power role
   - Data role
   - Print TCPM state based on connection status
 * tcpm: use "struct udevice *dev" instead of "struct tcpm_port *port"
   as function argument in most places and drop dev from the tcpm_port
   struct
 * tcpm: avoid useless kzalloc + copy + free for incoming events
 * tcpm: use dev_get_uclass_plat() for tcpm_port
 * tcpm: run tcpm_port_init() and tcpm_poll_event() from UCLASS post_probe()
 * tcpm/fusb302: get rid of tcpc_dev by using dm_tcpm_ops() for the
   function pointers and introducing get_connector_node() for the
   ofnode
 * fusb302: use "struct udevice *dev" instead of "struct fusb302_chip *chip"
   as function argument and drop dev from the fusb302_chip struct
 * fusb302: drop multiple unused members from fusb302_chip
 * fusb302: directly use udelay instead of usleep_range define
 * fusb302: use fusb302_ prefix for all functions. Afterwards tcpm_ prefix
   is only used for the tcpm code itself
 * fusb302: move fusb302_poll_event() to avoid forward defintion
 * fusb302: drop probe function
 * fusb302: drop unused LOG_BUFFER defines
 * roughly 20% of all lines of the series changed between v1 and v2, so
   I did not collect the Tested-by from Soeren Moch

Greetings,

-- Sebastian

Sebastian Reichel (5):
  usb: tcpm: add core framework
  usb: tcpm: fusb302: add driver
  board: rock5b-rk3588: add USB-C controller support
  board: rock5b-rk3588: enable USB-C in operating system
  MAINTAINERS: add TCPM section

 MAINTAINERS                               |    8 +
 Makefile                                  |    1 +
 arch/arm/dts/rk3588-rock-5b-u-boot.dtsi   |   28 +
 board/radxa/rock5b-rk3588/Makefile        |    6 +
 board/radxa/rock5b-rk3588/rock5b-rk3588.c |   33 +
 cmd/Kconfig                               |    7 +
 cmd/Makefile                              |    1 +
 cmd/tcpm.c                                |  142 ++
 configs/rock5b-rk3588_defconfig           |    5 +
 drivers/usb/Kconfig                       |    2 +
 drivers/usb/tcpm/Kconfig                  |   16 +
 drivers/usb/tcpm/Makefile                 |    4 +
 drivers/usb/tcpm/fusb302.c                | 1333 ++++++++++++
 drivers/usb/tcpm/fusb302_reg.h            |  177 ++
 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 +
 20 files changed, 4906 insertions(+)
 create mode 100644 board/radxa/rock5b-rk3588/Makefile
 create mode 100644 board/radxa/rock5b-rk3588/rock5b-rk3588.c
 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/fusb302.c
 create mode 100644 drivers/usb/tcpm/fusb302_reg.h
 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

Comments

Soeren Moch June 4, 2024, 5:46 p.m. UTC | #1
Hi,

On 04.06.24 18:33, Sebastian Reichel wrote:
> Hi,
>
> On ROCK 5B power is usually supplied via it's USB-C port. This port has the
> data lines connected to RK3588, VBUS connected to the input regulator and
> CC pins connected to FUSB302. FUSB302 is a USB-C controller, which can be
> accessed via I2C from RK3588. The USB-C controller is needed to figure out
> the USB-C cable orientation, but also to do USB PD communication. Thus it
> would be great to enable support for it in the operating system.
>
> But the USB-PD specification requires, that a device reacts to USB-PD messages
> send by the power-supply within around 5 seconds. If that does not happen the
> power-supply assumes, that the device does not support USB-PD. If a device
> later starts sending USB-PD messages it is considered an error, which is solved
> by doing a hard reset. A USB-PD hard reset means, that all supply voltages are
> removed for a short period of time. For boards, which are solely powered
> through their USB-C port, like the Radxa Rock 5B, this results in an machine
> reset. This is currently worked around by not describing the FUSB302 in the
> kernel DT, so nothing will ever speak USB-PD on the Rock 5B. This means
>
> 1. the USB-C port cannot be used at all
> 2. the board will be running via fallback supply, which provides limited
>     power capabilities
>
> In order to avoid the hard reset, this adds FUSB302 support to U-Boot, so
> that we react to the power-supply's queries in time. The code, which is
> originally from the Linux kernel, consists of two parts:
>
> 1. the tcpm state machine, which implements the Type C port manager state
>     machine as described in the USB PD specification
> 2. the fusb302 driver, which knows about specific registers
>
> Especially the first part has been heavily modified compared to the
> kernel, which makes use of multiple delayed works and threads. For this
> I used a priorly ported version from Rockchip, removed their hacks and
> any states not necessary in U-Boot (e.g. audio accessory support).
>
> Changes since PATCHv1:
>   * tcpm: split uclass specific code to tcpm-uclass
>   * tcpm_print_info: move printing part to cmd/tcpm.c
>   * tcpm_print_info: report more information
>     - PD revision
>     - Cable orientation
>     - Power role
>     - Data role
>     - Print TCPM state based on connection status
>   * tcpm: use "struct udevice *dev" instead of "struct tcpm_port *port"
>     as function argument in most places and drop dev from the tcpm_port
>     struct
>   * tcpm: avoid useless kzalloc + copy + free for incoming events
>   * tcpm: use dev_get_uclass_plat() for tcpm_port
>   * tcpm: run tcpm_port_init() and tcpm_poll_event() from UCLASS post_probe()
>   * tcpm/fusb302: get rid of tcpc_dev by using dm_tcpm_ops() for the
>     function pointers and introducing get_connector_node() for the
>     ofnode
>   * fusb302: use "struct udevice *dev" instead of "struct fusb302_chip *chip"
>     as function argument and drop dev from the fusb302_chip struct
>   * fusb302: drop multiple unused members from fusb302_chip
>   * fusb302: directly use udelay instead of usleep_range define
>   * fusb302: use fusb302_ prefix for all functions. Afterwards tcpm_ prefix
>     is only used for the tcpm code itself
>   * fusb302: move fusb302_poll_event() to avoid forward defintion
>   * fusb302: drop probe function
>   * fusb302: drop unused LOG_BUFFER defines
>   * roughly 20% of all lines of the series changed between v1 and v2, so
>     I did not collect the Tested-by from Soeren Moch
>
Makes sense, of course.

I retested this v2 series on top of 2024.07-rc4, everything still works
perfectly fine for me.

Tested-by: Soeren Moch <smoch@web.de>



U-Boot 2024.07-rc4-00005-gc9c6c70498 (Jun 04 2024 - 19:18:57 +0200)

Model: Radxa ROCK 5 Model B
DRAM:  8 GiB
Core:  355 devices, 33 uclasses, devicetree: separate
MMC:   mmc@fe2c0000: 1, mmc@fe2d0000: 2, mmc@fe2e0000: 0
Loading Environment from nowhere... OK
In:    serial@feb50000
Out:   serial@feb50000
Err:   serial@feb50000
Model: Radxa ROCK 5 Model B
Net:   No ethernet found.
Hit any key to stop autoboot:  0
=> tcpm list
| Name                            | Parent name         | Parent uclass
@ seq
| usb-typec@22                    | i2c@feac0000        | i2c @ 4 |
status: 0
=> tcpm dev usb-typec@22
dev: 0 @ usb-typec@22
=> tcpm info
Orientation: normal
PD Revision: rev3
Power Role:  sink
Data Role:   device
Voltage:     12.000 V
Current:      2.500 A
=>

Thanks again,
Soeren
Tim Harvey June 24, 2024, 9:20 p.m. UTC | #2
On Tue, Jun 4, 2024 at 9:35 AM Sebastian Reichel
<sebastian.reichel@collabora.com> wrote:
>
> Hi,
>
> On ROCK 5B power is usually supplied via it's USB-C port. This port has the
> data lines connected to RK3588, VBUS connected to the input regulator and
> CC pins connected to FUSB302. FUSB302 is a USB-C controller, which can be
> accessed via I2C from RK3588. The USB-C controller is needed to figure out
> the USB-C cable orientation, but also to do USB PD communication. Thus it
> would be great to enable support for it in the operating system.
>
> But the USB-PD specification requires, that a device reacts to USB-PD messages
> send by the power-supply within around 5 seconds. If that does not happen the
> power-supply assumes, that the device does not support USB-PD. If a device
> later starts sending USB-PD messages it is considered an error, which is solved
> by doing a hard reset. A USB-PD hard reset means, that all supply voltages are
> removed for a short period of time. For boards, which are solely powered
> through their USB-C port, like the Radxa Rock 5B, this results in an machine
> reset. This is currently worked around by not describing the FUSB302 in the
> kernel DT, so nothing will ever speak USB-PD on the Rock 5B. This means
>
> 1. the USB-C port cannot be used at all
> 2. the board will be running via fallback supply, which provides limited
>    power capabilities
>
> In order to avoid the hard reset, this adds FUSB302 support to U-Boot, so
> that we react to the power-supply's queries in time. The code, which is
> originally from the Linux kernel, consists of two parts:
>
> 1. the tcpm state machine, which implements the Type C port manager state
>    machine as described in the USB PD specification
> 2. the fusb302 driver, which knows about specific registers
>
> Especially the first part has been heavily modified compared to the
> kernel, which makes use of multiple delayed works and threads. For this
> I used a priorly ported version from Rockchip, removed their hacks and
> any states not necessary in U-Boot (e.g. audio accessory support).
>

Hi Sebastian,

It seems here that your goal was primarily to react to the USB-PD
messages to negotiate board power. It looks like your tpmc class
implementation has the ability to handle role determination among
everything else from the tpmc but it's not clear to me how a tpmc
would hook into a USB controller to provide role feedback.

The rk3588 you're using in this series has a DWC3 controller
configured with dr_mode of otg which means it will register the
dwc3-generic-peripheral driver. When dwc3_core_init_mode is called,
what exists to set dwc->dr_mode according to the mode the TPMC is
showing? In other words what is here to provide the means for your OTG
controller to act in both host mode and device mode?

Perhaps it is beyond the scope of your series but I'm looking for a
framework where a driver monitoring a GPIO can provide the role to UDC
drivers. For example, I'm talking about a USB-B connector with the ID
pin going to a generic GPIO or a GPIO connected to a bus-less type-C
CC controller like the TPS25821 which provides a SINK# pin to specify
if you have a host cable vs a device cable attached.

Best Regards,

Tim