Last edited one week ago

UCSI overview

Applicable for STM32MP13x lines, STM32MP15x lines, STM32MP21x lines, STM32MP23x lines, STM32MP25x lines

This article gives information about Linux® UCSI driver, and the STM32 UCSI firmware.

1. UCSI purpose[edit | edit source]

UCSI[1][2] stands for USB Type-C® Connector System Software Interface. It is a specification that defines a standard software interface for managing USB Type-C connectors and USB Power Delivery (USB PD) controllers. It provides a standardized and efficient way to manage power delivery, data transfer, and alternate modes. It enhances the user experience by enabling versatile and powerful connections through a single port.

In a UCSI enabled system, the Type-C port can me managed autonomously. The UCSI driver purpose is to be notified by (or to control) the USB Type-C interface, so the power role and/or the data role of the system is managed accordingly by the platform OS.

The UCSI specification[1][2] doesn't define the interface used to communicate with the UCSI controller (e.g. I2C, SPI...). On STM32 Arm® Cortex® MPUs More info.png, two flavors are available:

  • An external STM32G0 can be used, running the X-CUBE-UCSI Firmware Package.
    • On the STM32MP135F-DK Discovery kit More info green.png, the STM32MP13x lines More info.png communicates with the STM32G0 through the I2C protocol.
  • An internal STM32Cube USBPD_DRP_UCSI application running on the Cortex®-M33 processor on STM32MP23x lines More info.png or STM32MP25x lines More info.png.
    • On the STM32MP257F-EV1 More info green.png, STM32MP257F-DK More info green.png and STM32MP257F-DK More info green.png for STM32MP23x lines evaluation Info.png, the Cortex®-A35 communicates with the Cortex®-M33 through the Linux RPMsg framework.
Info white.png Information
  • The external STM32G0 UCSI flavor could be used on any of the STM32 Arm® Cortex® MPUs More info.png
  • The internal STM32Cube USBPD_DRP_UCSI application running on the Cortex®-M33 processor on STM32MP23x lines More info.png or STM32MP25x lines More info.png is supported for A35-TD flavor More info green.png only in OpenSTLinux BSP.

The OpenSTLinux BSP running on the Arm® Cortex®-A processor(s) acts as the OPM (OS Policy Manager). The STM32Cube UCSI application running on the Arm® Cortex®-M processor acts as the PPM (Platform Policy Manager) and the LPM (Local Policy Managers). It uses independently several internal peripherals including the UCPD internal peripheral.


2. UCSI Architecture overview[edit | edit source]

2.1. On STM32 Arm® Cortex® MPUs More info.png with external STM32G0[edit | edit source]

UCSI stm32g0.png

The X-CUBE-UCSI Firmware Package uses:

  • two I2C device addresses:
    • The primary address 0x53 may be tuned. It is reserved to communicate with the UCSI standard protocol.
    • The secondary address 0x51 is used either by:
      - the STM32G0 when in bootloader mode (refer to AN4221)
      - the UCSI application at runtime to control the firmware update. It allows to request the firmware version, and to switch to booloader mode when needed.
  • a GPIO based interrupt line to notify the application processor.

The Linux® UCSI driver:

  • gets notified through GPIO
  • can issue USCI commands onto the I2C link

It's responsible to switch the USB dual role stack, depending on the attached partner.
Please refer to USB_overview for further details on these interactions.

2.2. On STM32MP23x lines More info.png and STM32MP25x lines More info.png with the Cortex®-M33 for A35-TD flavor More info green.png[edit | edit source]

UCSI-stm32mp25.png

On STM32MP23x lines More info.png and STM32MP25x lines More info.png, all can be integrated in a single SoC:

On STM32MP25x lines More info.png (STM32MP257F-DK Discovery kit More info green.png), USB3DR SuperSpeed lines are available:

  • Routing the lines to the Type-C® connector is done through an external Super Speed switch to accommodate the cable orientation.
  • Cable orientation is detected by the firmware, GPIOs can be used to drive the external switch.

3. How to use[edit | edit source]

USB Power delivery protocol on the CC line is managed independently by the UCSI firmware (either with external STM32G0 micro controller or internally with the Cortex®-M33 firmware).
Basically, the PPM detects if it's connected, if it's in front of a host or a device (by detecting a "Rp" pull-up or a "Rd" pull-down on the CC line). It also detects the presence of a Vbus and initiate USB power delivery messages on the CC line.
Once the connector attachment event has been detected by the PPM, it will notify the OPM throught UCSI events. The platform OS doesn't have access to the power delivery messages, but obtains a higher level of information through UCSI notifications, all described into the UCSI specification[1][2], such as:

  • the connection status
  • the connector partner type (Upstream Facing Port, Downstream Facing Port, powered cable...)
  • the power mode of operation (USB default, 1.5A, 3A, PD, e.g. power delivery...)
  • the power direction (provider or consumer)
  • the data role (device or host)
  • ...
Info white.png Information
USB Type-C® devices can act as:
  • Fixed power source and host, for example, A role.
  • Fixed power sink and peripheral, for example, B role.
  • Dual role power and dual role data, thanks to USB Power Delivery protocol[3].

Upon the initial plug, the devices connected together will obtain respectively one of the A and B role on each side. Then the power and data roles may be swapped, when both ends support it, with USB power delivery protocol.

This is exposed for the local port in:

cd /sys/class/typec/port0
ls
data_role             supplier:platform:49000000.usb
device                supported_accessory_modes
port0-partner         uevent
power                 usb_power_delivery
power_operation_mode  usb_power_delivery_revision
power_role            usb_typec_revision
preferred_role        vconn_source
subsystem             waiting_for_supplier
cat data_role
host [device]

This is exposed for the partner port in:

cd /sys/class/typec/port0-partner
ls
accessory_mode  subsystem                    usb_power_delivery_revision
device          supports_usb_power_delivery
power           uevent

More examples are available in USB overview articles: please refer to How to use typec from sysfs and How to perform USB data role swap or power role swap from sysfs.

4. Firmware update[edit | edit source]

4.1. On STM32 Arm® Cortex® MPUs More info.png with external STM32G0[edit | edit source]

The X-CUBE-UCSI Firmware Package can be updated into the STM32G0 flash memory:

  • Place the updated firmware in /lib/firmware/
  • The Linux® UCSI driver will compare firmware version found into the filesystem in /lib/firmware with the flashed firmware.
  • If a different firmware version is found in /lib/firmware. Kernel will replace old firmware with new firmware.
  • In case the STM32G0 isn't flashed, and it's in I2C bootloader mode (refer to AN4221), the kernel will flash the firmware.

The firmware name must be specified in the board device-tree, to activate the update mechanism. For example, on the STM32MP135F-DK Discovery kit More info green.png, it is located in arch/arm/boot/dts/st/stm32mp135f-dk.dts :

&i2c1 {
	typec@53 {
		compatible = "st,stm32g0-typec";
		reg = <0x53>;
		...
		firmware-name = "stm32g0-ucsi.mp135f-dk.fw";
		...
	};
};

In order trigger the update mechanism, the driver must be re-loaded. This can be done in various ways:

reboot
# or reload the module:
rmmod ucsi_stm32g0 && modprobe ucsi_stm32g0
# alternatively unbind, then bind the driver:
cd /sys/bus/i2c/drivers/ucsi-stm32g0-i2c/
ls
0-0053  bind  module  uevent  unbind
echo 0-0053 > unbind && echo 0-0053 > bind

In case no firmware is found on the STM32G0 MCU, the following message will come in dmesg log:

ucsi-stm32g0-i2c 0-0053: i2c read 53, 00 error: -6

During the firmware update process the following log will come on dmesg logs

ucsi-stm32g0-i2c 0-0053: Bootloader Version 0x12
ucsi-stm32g0-i2c 0-0053: Starting, option bytes:0xfffffeaa 

4.2. On STM32MP23x lines More info.png and STM32MP25x lines More info.png with the Cortex®-M33 for A35-TD flavor More info green.png[edit | edit source]

The application should be loaded on the Arm® Cortex®-M33 processor by using the Linux remoteproc framework.
In OpenSTLinux, a systemctl service is used to load the firmware, depending on the board variant, and on how it is configured. These firmware are available, for each board in:

ls /usr/local/Cube-M33-examples/
.... STM32MP257F-DK  STM32MP257F-EV1

# For STM32MP257F-DK:
ls /usr/local/Cube-M33-examples/STM32MP257F-DK/Demonstrations/USBPD_DRP_UCSI/lib/firmware/
USBPD_DRP_UCSI_CM33_NonSecure_sign.bin  USBPD_DRP_UCSI_CM33_NonSecure_stripped.elf

The systemctl to abstracts the image format supported, as described in Remote processor boot through sysfs section:

cat /sys/class/remoteproc/remoteproc1/name # check remoteprocX is the m33
m33
cat /sys/class/remoteproc/remoteproc1/fw_format
  • ELF: USBPD_DRP_UCSI_CM33_NonSecure_stripped.elf needs to be updated
  • TEE: USBPD_DRP_UCSI_CM33_NonSecure_sign.bin needs to be updated

Place the updated firmware in the relevant board folder:

cp <firmware> /usr/local/Cube-M33-examples/<board>/Demonstrations/USBPD_DRP_UCSI/lib/firmware/

# For ELF format, on STM32MP257F-DK board:
cp USBPD_DRP_UCSI_CM33_NonSecure_stripped.elf /usr/local/Cube-M33-examples/STM32MP257F-DK/Demonstrations/USBPD_DRP_UCSI/lib/firmware/
  • Run the following commands on device console to run the new firmware
systemctl stop st-m33firmware-load.service  # Stops the firmware currently running
systemctl start st-m33firmware-load.service # Loads and starts the new firmware
Warning white.png Warning
Be careful during the development cycle: the service st-m33firmware-load.service creates a copy of this firmware file in /lib/firmware/ before it gets loaded.
In case the user updates it directly in /lib/firmware/, it will be overwritten.

In order to permanently disable or enable the firmware service at boot time, following commands can be used

systemctl disable st-m33firmware-load.service
systemctl enable st-m33firmware-load.service

An alternative solution to start the Stm32Cube UCSI application can be found in remote processor boot section.

5. How to trace and debug[edit | edit source]

5.1. Tracing Linux UCSI core with ftrace[edit | edit source]

The Linux UCSI core proposes some trace points that can be traced by the Linux® kernel Ftrace tool. I2C layer can also be traced, as it is used to communicate with the UCSI controller.

echo 1 > /sys/kernel/debug/tracing/events/ucsi/enable # Tracing UCSI Events
echo 1 > /sys/kernel/debug/tracing/events/i2c/enable  # Tracing I2C Events
echo 1 > /sys/kernel/debug/tracing/tracing_on

Once ftrace has been enabled, any event on the Type-C connector can be traced (plug, unplug, or power event).

cat /sys/kernel/debug/tracing/trace
...
  irq/61-0-0053-410     [000] .....   292.223643: i2c_write: i2c-0 #0 a=053 f=0000 l=1 [04]
  irq/61-0-0053-410     [000] .....   292.223652: i2c_read: i2c-0 #1 a=053 f=0001 l=4
  irq/61-0-0053-410     [000] .....   292.223890: i2c_reply: i2c-0 #1 a=053 f=0001 l=4 [02-00-00-20]
  irq/61-0-0053-410     [000] .....   292.223896: i2c_result: i2c-0 n=2 ret=2
...
    kworker/0:0-6       [000] .....   292.225223: ucsi_connector_change: port0 status: change=5004, opmode=4, connected=1, sourcing=0, partner_flags=1, partner_type=1, request_data_obj=00000000, BC status=0
...

5.2. Tracing STM32Cube UCSI application with STM32CubeMonitor-UCPD tool[edit | edit source]

The STM32CubeMonitor-UCPD[4] allows tracing:

  • the USB Power delivery stack
  • the UCSI notifications and messages

It requires the _TRACE compilation switch to be activated when building the STM32Cube UCSI application. It is enabled by default:

  • On STM32MP135F-DK More info green.png, the STLink exposes two VCP (virtual COM ports):
    - the first one (VCP1) is for the STM32MP13x lines More info.png console,
    - the second one (VCP2) is for the STM32G0 USB power delivery and UCSI traces.
  • On STM32MP257F-EV1 More info green.png, STM32MP257F-DK More info green.png and STM32MP257F-DK More info green.png for STM32MP23x lines evaluation Info.png, traces are available on USART6 on EXPANSION connector.

The UART port used for tracing can be configured:

To read and decode the traces:

  • First, plugin the serial port used for tracing, to a computer running STM32CubeMonitor-UCPD[4].
  • Then click on "Select Tracer Port", on the entry corresponding to the second port.
  • Last, generate some activity on the USB Type-C port (e.g. plug-in or remove a USB device).

STM32CubeMonitor-UCPD-UCSI.png

Note that when nothing has been plugged-in on the dual role Type-C port toggles its CC lines, from source (SRC) to sink (SNK) as seen above. Then some activity on USB Power delivery stack and on UCSI is seen upon cable attach.

5.3. I2C debug commands[edit | edit source]

5.3.1. On the primary I2C address, dedicated to UCSI protocol[edit | edit source]

The UCSI driver module should be unloaded, before performing any direct I2C access:

rmmod ucsi_stm32g0

Identify the I2C bus number:

  • For example, on the STM32MP135F-DK More info green.png, the stm32g0 is wired to I2C1 (e.g. I2C at 0x40012000):
i2cdetect -l
i2c-0   i2c             STM32F7 I2C(0x40012000)                 I2C adapter
i2c-1   i2c             STM32F7 I2C(0x4c006000)                 I2C adapter
  • For example, on the STM32MP257F-EV1 More info green.png, the UCSI firwmare responds on the RPMSg I2C:
i2cdetect -l
i2c-0   i2c             STM32F7 I2C(0x0000000040130000)         I2C adapter
i2c-1   i2c             rpmsg_i2c-0x401 adapter                 I2C adapter

Check the STM32G0 is responding on I2C bus, on the STM32MP135F-DK More info green.png:

i2cdetect -y 0
    0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- UU -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- 51 -- 53 -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --

Read UCSI version, on the primary I2C address:

  • On the STM32MP135F-DK More info green.png:
i2ctransfer -f -y 0 w1@0x53 0x00 r2
0x20 0x01
  • on the STM32MP257F-EV1 More info green.png:
i2ctransfer -f -y 1 w1@0x35 0x00 r2
0x20 0x01

5.3.2. On the secondary I2C address[edit | edit source]

On STM32 Arm® Cortex® MPUs More info.png with external STM32G0, the X-CUBE-UCSI Firmware Package uses a secondary I2C address, to control the firmware.
The UCSI application responds to below commands on the secondary I2C address:

Command code Command answer Description
0x00, 0xff 4 bytes Get firmware version
0x21, 0xde 0 bytes Reset directly, go to bootloader mode

The UCSI driver module should be unloaded, before performing any direct I2C access:

rmmod ucsi_stm32g0

For example, on the STM32MP135F-DK Discovery kit More info green.png, read the firmware version, on the secondary I2C address:

i2ctransfer -f -y 0 w2@0x51 0x00 0xff r4
0x02 0x06 0x22 0x20

Go to bootloader mode

i2cset -f -y 0 0x51 0x21 0xde

Then only the bootloader i2c address can be detected (e.g. 0x51)

root@stm32mp1-e3-5b-21:~# i2cdetect -y 0
    0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- UU -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- 51 -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --

6. Source code location[edit | edit source]

The UCSI Linux drivers to control USB Type-C® and USB Power Delivery are located in:

The UCSI firmware used either in the Cortex®-M33 coprocessor or in an external STM32G0, can be found:

7. To go further[edit | edit source]

Linux® documentation and support:

8. References[edit | edit source]