SCMI on STM32MP1

1 Article Purpose[edit]

The purposes of this article is to explain the SCMI services in STM32MPU.

SCMI stands for System Control and Magagement Interface. It refers to Arm SCMI specification[1]. SCMI is a message driven interface where specific SCMI protocols expose statndard service for system resources.

STM32MP15 uses SCMI to abstrat RCC resources, as clock and reset controllers, assigned to secure world excluvie access by RCC TZEN configuration. Secure world embeds a SCMI server that exposes clock and reset controllers. Non-secure world uses SCMI drivers as SCMI clock driver clk-scmi.c[2] and SCMI reset driver reset-scmi.c[3] to handle the resource in the system.

2 What is SCMI and what is it used for[edit]

SCMI is a protocol based on message exchanged. It allows a resource master to expose device services to a client entity.

For example, the CPU clock cannot be freely manipulated by the non-secure world. Yet, Linux kernel executing in non-secure world may need to get or set the DDR frequency. Implementing a SCMI agent in non-secure world (Linux kernel, U-Boot bootloader) and a SCMI server in secure firmware (TF-A, OP-TEE) allows non-secure Linux kernel and U-Boot to natively discover the DDR clock as a standard clock device.

In the example, applied to STM32MP15, enabling security on the DDR clock is also related to enable the security on DDR controllers interfaces. DDR clock secure hardening is enabled from RCC interface. DDR controller access permissions are configure through ETZPC. STM32MP15 software release ensures platform configuration consistency.

3 STM32MP15 SCMI overview[edit]

SCMI on STM32MP15 is used to create server/client paths between secure and non-secure world to offer device driver services for the SoC resource when some firewalls configuration are hardened.

In STM32MP1 software release, the secure world, being TF-A or OP-TEE, embeds a SCMI server that exposes clock and reset controllers that non-secure world cannot access straight due to the configuration loaded in STM32MP1 RCC security hardening.

In STM32MP15 software release, secure world exposes some clock and reset controllers to non-secure world. Secure world can be TF-A or OP-TEE. They implement features from the SCMI specification v2.0 [4]. TF-A and OP-TEE supports necessary features from SCMI Base: clock, reset, domain protocols. These clock and reset controllers are related the SoC configuration that grants write access to specific RCC interface register. As stated in RCC security hardening, RCC TZEN restricts certain resource accesses, RCC MCKPROT restricts even more resource accesses.

Since there are 2 levels of secure hardening, STM32MP1 exposes system resources over 2 channel, represented by 2 agents in non-secure world. SCMI agent 0 discovers clocks and reset hardened per RCC TZEN enabling. SCMI agent 1 discovers clocks hardended upon RCC MCKPROT enabling.

4 STM32MP15 SCMI clocks and reset[edit]

In STM32MP15, SCMI exposes resource for the peripheral interfaces listed below. Note that when a related device is assigned to secure world by system configuration (see How to assign an internal peripheral to a runtime context for further information), the SCMI controls, even if exposed, will not allow non-secure world to effectively access the resource.

The SCMI clock protocol phandle together with the clock ID, supported values are defined in STM32MP1 DT clock bindings[5], forms a unique identifer for the clock resources in Linux and U-Boot executable.

The SCMI reset domain protocol phandle together with the agent reset domain ID, supported values are defined in STM32MP1 DT reset bindings[6], forms a unique identifer for the reset controller resources.

  • SCMI exposes CRYP1 clock with ID CK_SCMI0_CRYP1 to non-secure agent 0.
    SCMI exposes CRYP1 reset with ID RST_SCMI0_CRYP1 to non-secure agent 0.
  • SCMI exposes HASH1 clock with ID CK_SCMI0_HASH1 to non-secure agent 0.
    SCMI exposes HASH1 reset with ID RST_SCMI0_CRYP1 to non-secure agent 0.
  • SCMI exposes RNG1 clock with ID CK_SCMI0_RNG1 to non-secure agent 0.
    SCMI exposes RNG1 reset with ID RST_SCMI0_RNG1 to non-secure agent 0.
  • SCMI exposes BSEC clock with ID CK_SCMI0_BSEC to non-secure agent 0.
  • SCMI exposes GPIOZ bank clock with ID CK_SCMI0_GPIOZ to non-secure agent 0.
    SCMI exposes GPIOZ bank reset with ID RST_SCMI0_GPIOZ to non-secure agent 0.
  • SCMI exposes I2C4 and I2C6 clock with ID CK_SCMI0_I2Cx to non-secure agent 0.
    SCMI exposes I2C4 and I2C6 reset with ID RST_SCMI0_I2Cx to non-secure agent 0.
  • SCMI exposes SPI6 clock with ID CK_SCMI0_SPI6 to non-secure agent 0.
    SCMI exposes SPI6 reset with ID RST_SCMI0_SPI6 to non-secure agent 0.
  • SCMI exposes USART1 clock with ID CK_SCMI0_USART1 to non-secure agent 0.
    SCMI exposes USART1 reset with ID RST_SCMI0_USART1 to non-secure agent 0.
  • SCMI exposes IWDG1 bus clock with ID CK_SCMI0_IWDG1 to non-secure agent 0.
  • SCMI exposes RTC clock controller with ID CK_SCMI0_RTC to non-secure agent 0.
  • SCMI exposes MDMA reset controller with ID CK_SCMI0_MDMA to non-secure agent 0.
  • SCMI exposes MCU clock to non-secure agent 1 with ID CK_SCMI1_MCU.
    SCMI exposes MCU reset to non-secure agent 0 with ID RST_SCMI0_MCU.
    They can be used for coprocessor startup whether via Linux remoteproc framework or U-Boot bootloader.
  • SCMI exposes internal root clocks LSI, HSI and CSI to non-secure agent 0
    with IDs CLK_SCMI0_LSI, CLK_SCMI0_HSI and CLK_SCMI0_CSI.
  • SCMI exposes external root clocks LSE and HSE to non-secure agent 0
    with IDs CK_SCMI0_HSE and CK_SCMI0_LSE.
  • SCMI exposes PLL2Q and PLL2R to non-secure agent 0
    with IDs CK_SCMI0_PLL2_Q and CK_SCMI0_PLL2_R.
  • SCMI exposes PLL3Q and PLL3R to non-secure agent 1
    with IDs CK_SCMI1_PLL3_Q and CK_SCMI1_PLL3_R.

5 STM32MP15 SCMI agents[edit]

Among all clocks and resets exposed by STM32MP15, see the list in the previous section, all but MCU clock and PLL3Q and PLL3R clocks are related to RCC TZEN hardening, the 3 later being related to RCC MCKPROT hardening.

When RCC TZEN hardening is enabled, non-secure world shall rely on SCMI agent 0 to access the desired resources.

When RCC MCKPROT hardening is enabled, non-secure world shall rely on SCMI agent 1 to access the desired resources.

Each agent interface uses a specific shared memory for SCMI message exchanges. A specific notification layer is also used between non-secure and secure worlds. The device tree technology is used the define the SCMI message transport configuration, in non-secure side. In secure world, the transport means are built-in firmware image. The shared memories used are all located at the top (high addresses) is SYSRAM internal memory.

6 Device Tree description[edit]

The SCMI services device tree bindings are defined in the Linux kernel source tree in Arm SCMI DT bindings[7] documentation.

6.1 SCMI agent nodes[edit]

Each SCMI agent is a subnode of the firmware node in the device tree description.

SCMI devices are described in the firmware node of the device tree, with compatible = "arm,scmi".

                scmi-agent {
                        compatible = "arm,scmi";

                        (...) /* SCMI transport properties */

                        /* Below are the discovered SCMI protocols */
                        protocol@X {
                                reg = <0xX>;
                                (...)
                        };
                        protocol@Y {
                                reg = <0xY>;
                                (...)
                        };
                };

6.2 STM32MP1 SCMI Transport[edit]

SCMI framework support several transport layers for message exchange. SCMI uses a transport built on mmio-sram shared memory instance with a smc-mbox mailbox device for message notification.

Shared memory device with mmio-sram. Device tree bindings offers compatible "mmio-sram" devices to described physical memory. It is supported by U-Boot and Linux kernel. In STM32MP1 memory layout, 2 shared memories in SYSRAM internal RAM are reserved for non-secure SCMI communication. In exmample below, phandle scmi0_shm refers to SYSRAM range [0x2FFFF000 0x2FFFF07F] used by SCMI agent 0 for client/server communication.

        sram@2ffff000 {
                compatible = "mmio-sram";
                reg = <0x2ffff000 0x1000>;
                #address-cells = <1>;
                #size-cells = <1>;
                ranges = <0 0x2ffff000 0x1000>;

                scmi0_shm: scmi_shm@0 {
                        reg = <0 0x80>;
                };
        };

Mailbox device: ad-hoc arm,smc-mbox.
STM32MP1 software release uses a SMC mailbox described with a "arm,smc-mbox" compatible node. Property arm,func-id defines the function ID used to invoke secure world for a specific SCMI agent/server interface.

        scmi0_mbox: mailbox-0 {
                #mbox-cells = <0>;
                compatible = "arm,smc-mbox";
                arm,func-id = <0x82002000>;
        };

In example below, SCMI agent 0 uses scmi0_mbox mailbox and scmi0_shm as shared memory.

        firmware {
                scmi0: scmi-0 {
                        compatible = "arm,scmi";
                        (...)
                        mboxes = <&scmi0_mbox 0>;
                        mbox-names = "txrx";
                        shmem = <&scmi0_shm>;
                        (...)
                };
        };

6.3 STM32MP15 SCMI device tree nodes[edit]

STM32MP15 exposes SCMI over 2 devices in the device tree description. One device per supported SCMI agents, hence two: one for the clocks and reset controllers related to RCC TZEN hardening configuration, and one for the clock controllers related to RCC MCKPROT hardening configuration.

As defined in Arm SCMI DT bindings[8], a SCMI agent node can contain one or more supported SCMI protocols. Each are described in a specific subnode of the agent node. STM32MP15 implements SCMI Clock protocol (ID 0x14) that is a clock provider device and SCMI Reset Domain protocol (ID 0x16) that is a reset controller provider device.

Example below shows a configuration supported in STM32MP15 software release.

        /* Shared memory used for SCMI agent/server communication */
        scmi_sram: sram@2ffff000 {
                compatible = "mmio-sram";
                reg = <0x2ffff000 0x1000>;
                #address-cells = <1>;
                #size-cells = <1>;
                ranges = <0 0x2ffff000 0x1000>;

                scmi0_shm: scmi_shm@0 {
                        reg = <0 0x80>;
                };
                scmi1_shm: scmi_shm@200 {
                        reg = <0x200 0x80>;
                };
        };

        /* Mailbox device used for SCMI agent/server communication */
        scmi0_mbox: mailbox-0 {
                #mbox-cells = <0>;
                compatible = "arm,smc-mbox";
                arm,func-id = <0x82002000>;
        };
        scmi1_mbox: mailbox-1 {
                #mbox-cells = <0>;
                compatible = "arm,smc-mbox";
                arm,func-id = <0x82002001>;
        };

        /* SCMI agent nodes, in the firmware node */
        firmware {
                scmi0: scmi-0 {
                        compatible = "arm,scmi";
                        #address-cells = <1>;
                        #size-cells = <0>;

                        status = "okay"; /* To enable upon RCC[TZEN] */
                        mboxes = <&scmi0_mbox 0>;
                        mbox-names = "txrx";
                        shmem = <&scmi0_shm>;

                        scmi0_clk: protocol@14 {
                                reg = <0x14>;
                                #clock-cells = <1>;
                        };
                        scmi0_reset: protocol@16 {
                                reg = <0x16>;
                                #reset-cells = <1>;
                        };
                };

                scmi1: scmi-1 {
                        compatible = "arm,scmi";
                        #address-cells = <1>;
                        #size-cells = <0>;

                        status = "disabled"; /* To enable upon RCC[MCKPROT] */
                        mboxes = <&scmi1_mbox 0>;
                        mbox-names = "txrx";
                        shmem = <&scmi1_shm>;

                        scmi1_clk: protocol@14 {
                                reg = <0x14>;
                                #clock-cells = <1>;
                        };
                };

7 How to go further[edit]

One can follow SCMI developments through TF-A mailing list[9] and OP-TEE OS issues[10]and pull requests[11]forums.

8 References[edit]