SCMI device tree configuration

Revision as of 08:00, 10 May 2023 by Registered User (→‎DT configuration (STM32/SoC level): fix description)
Applicable for STM32MP13x lines, STM32MP15x lines


1. Article purpose[edit source]

The purpose of this article is to explain how the SCMI resources are configured in U-Boot bootloader and Linux® kernel. The configuration is performed using the device tree mechanism[1].

SCMI services provided in STM32 MPU platforms are described in the SCMI overview article.

2. DT bindings documentation[edit source]

Generic information about SCMI is available in the SCMI overview article.

The device tree binding documents for SCMI are stored either in the given applicable components listed below, or in the Linux kernel repository:

SCMI agent is only present in U-Boot and Linux® OS , while SCMI server is integrated in TF-A or OP-TEE. The DT bindings documentation only defines the SCMI agent configuration, there is no bindings for SCMI server configuration part.

The SCMI agent DT node must reflect the services exposed by SCMI server embedded in TF-A or OP-TEE.

2.1. DT bindings documentation - additional information[edit source]

An SCMI agent, in U-Boot or Linux kernel is represented by a node named scmi in the firmware node of the device tree. Each SCMI protocol used is represented by a subnode of the scmi node. SCMI protocol nodes define and register resources enumerated by the server or listed in the agent's device tree.

Valid values for compatible property are listed in the SCMI DT bindings [2].

    firmware {
        scmi {
            compatible = "...";
            #address-cells = <1>;
            #size-cells = <0>;
            (...)
            protocol@11 {
                reg = <0x11>;
                (...)
            };
            protocol@14 {
                reg = <0x14>;
                (...)
            };
            (...)
        };
    };

For example, the SCMI specification[3] defines the SCMI power domain management protocol as identified with protocol ID 0x11. Device tree represents this SCMI protocol as a power domain controller in the Linux® kernel, also called a "PM domain provider" in [4] documentation, that exposes power domains to Linux® kernel drivers. From SCMI communication perspective, agent and server for that platform use well defined ID numbers for each power domain, called domain IDs in SCMI litterature.

As shown in the source code snipet below, the Linux® power domain provider is a subnode named protocol@11 of the scmi node. Each power domain exposed through this protocol is identified by well known ID number. A device consuming the SCMI agent's power domain ID 2 would refer to that power domain using the SCMI protocol node phandle, scmi_devpd1 here, and use the SCMI power domain ID 2 as phandle argument: e.g. power-domains = <&scmi_devpd1 2>;. The below DTSI source code snipet is extracted from the SCMI DT bindings documentation[2].

    firmware {
        scmi {
            compatible = "arm,scmi-smc";
            shmem = <&cpu_scp_lpri0 &cpu_scp_lpri1>;
            arm,smc-id = <0xc3000001>;

            #address-cells = <1>;
            #size-cells = <0>;

            scmi_devpd1: protocol@11 {
                reg = <0x11>;
                #power-domain-cells = <1>;
            };
        };
    };

3. DT configuration[edit source]


This hardware description is a combination of the STM32 microprocessor device tree files (.dtsi extension) and board device tree files (.dts extension). See the Device tree for an explanation of the device-tree file organization.

STM32CubeMX can be used to generate the board device tree. Refer to How to configure the DT using STM32CubeMX for more details.

3.1. DT configuration (STM32/SoC level)[edit source]

As SCMI is closely related to the board configuration, SCMI device tree configration data are defined at board device tree level.

Info white.png Information

For STM32MP15x lines More info.png, ecosystem release unknown revision 5.0.0 Warning.png unknown range before Warning.png:
Prior ecosystem release v5.0.0, scmi node and shared memory used for SCMI communication were defined at SoC device tree level. For clarity, this has changed since ecosystem release v5.0.0 and later.

3.2. DT configuration (board level)[edit source]

The objective of this chapter is to explain how to enable and configure the DT nodes related to the board.
Using this chapter, the end-user can configure any parameters via the DT to adapt to a new board.

The objective of this chapter is to explain how to enable and configure the XXX DT nodes for a board.
Please add here the information to enable and configure the XXX peripheral""

Peripheral configuration should be done in specific board device tree files (board dts file and pinctrl dtsi file).

If pins of the internal peripheral need to be configured, then links to Pinctrl device tree configuration (and optionally to Pinctrl overview) must be added in the #DT configuration (board level) and/or #DT configuration examples.

3.3. DT configuration examples[edit source]

This OPTIONAL chapter must provide an example of how to configure the DT to adapt it to a new board.


When an STM32 MPU platform is to operate with an SCMI server in secure world, the SCMI agent needs to be described in Linux kernel and U-Boot bootloader device tree data.


An SCMI agent is described by a node named scmi. Devices and providers registered by the SCMI agent driver are described by subnodes, one per SCMI protocol used by the agent using reg bindings rules to carry the protocol ID number. Property compatible defines the SCMI transport layer used, either "arm,scmi-smc" or "linaro,scmi-optee" whether embedding TF-A or OP-TEE respectively.

When the using a predefined area of sram compatible memory for exchanging SCMI messages between non-secure and secure worlds, the platform must have a shmem property in the scmi node that refers to the phandle of a related "arm,scmi-shmem" compatible nodes in the device tree to describe the shared memory.

3.3.1. SCMI agent when TF-A in secure world[edit source]

Compatible "arm,scmi-smc" requires node property shmem and a specific property: arm,smc-id = <FUNC_ID>; that defines the platform SMC function ID used for SCMI messages notification. When the platform defines a specific communication (couple SMC function ID and shared memory), the node of the SCMI protocol shall define both arm,smc-id and shmem properties in the SCMI protocol subnode.

Note that STM32MP15 platforms currently use a single channel with pre-allocated SYSRAM shared memory for SCMI, to expose clock and reset controllers, as show in the DTS extract below:

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

		scmi_shm: scmi_shm@0 {
			compatible = "arm,scmi-shmem";
			reg = <0 0x80>;
		};
	};

	firmware {
		scmi: scmi {
			compatible = "arm,scmi-smc";
			arm,smc-id = <0x82002000>;
			shmem = <&scmi_shm>;
			#address-cells = <1>;
			#size-cells = <0>;

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

			scmi_reset: protocol@16 {
				reg = <0x16>;
				#reset-cells = <1>;
			};
		};
	};

3.3.2. SCMI agent when OP-TEE in secure world[edit source]

Compatible "linaro,scmi-optee" requires a specific property in the device node: linaro,optee-channel-id = <CHANNEL_ID>; where CHANNEL_ID is the channel identifer defined for the SCMI communication.

When the platform uses a predefined area of sram compatible memory for exchanging SCMI messages bet ween non-secure and secure worlds, the platform must set property shmem = <SOME_PHANDLE> in the protocol node, next to linaro,optee-channel-id property unless what the agent assumes that channel rely on an OP-TEE shared memory buffer dynamically allocated.

OP-TEE SCMI DT bindings permits SCMI protocol to be carried on specific channels, allows concurrent sending of messages. In such cases, the protocol subnode shall have property linaro,optee-channel-id defined with the expect channel ID. When the channel uses a predefined area of sram compatible memory, property shmem must be defined next to linaro,optee-channel-id property in the protocol node, unless what the channel is expected to use an OP-TEE shared memory buffer dynamically allocated.

The below example describes an OP-TEE SCMI firmware that exposes 2 channels. Channel 0 uses pre-defined shared memory and is used for SCMI base comminucation and for SCMI reset controls messaging. Channel 1 uses dynamically allocated shared memory and is used for a voltage regulator controller.

	firmware {
		scmi: scmi {
			compatible = "linaro,scmi-optee";
			linaro,optee-channel-id = <0>;
			shmem = <&scmi_shm>;
			#address-cells = <1>;
			#size-cells = <0>;
			scmi_clk: protocol@14 {
				reg = <0x14>;
				#clock-cells = <1>;
			};
			protocol@17 {
				reg = <0x17>;
				linaro,optee-channel-id = <1>;
				regulators {
					#address-cells = <1>;
					#size-cells = <0>;
					scmi_reg11: reg11@0 {
						reg = <0>;
						regulator-name = "reg11";
						regulator-min-microvolt = <1100000>;
					};
				};
			};
		};
	};

Note that STM32MP15 platforms currently use a single channel with pre-allocated SYSRAM shared memory for SCMI communication. The example below illustrates when SCMI server is embedded in OP-TEE firmware and is exposing clocks and reset controllers:

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

		scmi_shm: scmi_shm@0 {
			compatible = "arm,scmi-shmem";
			reg = <0 0x80>;
		};
	};

	firmware {
		scmi: scmi {
			compatible = "linaro,scmi-optee";
			#address-cells = <1>;
			#size-cells = <0>;
			linaro,optee-channel-id = <0>;
			shmem = <&scmi_shm>;

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

			scmi_reset: protocol@16 {
				reg = <0x16>;
				#reset-cells = <1>;
			};
		};
	};

3.3.3. DT configuration for SCMI resource consumers[edit source]

All devices using SCMI clocks and reset controllers refer to the phandle of the related SCMI clock contoller node scmi_clk or SCMI reset controller node scmi_reset. For example, the CPU references an SCMI clock:

	cpus {
		#address-cells = <1>;
		#size-cells = <0>;

		cpu0: cpu@0 {
			compatible = "arm,cortex-a7";
			device_type = "cpu";
			reg = <0>;
			clocks = <&scmi_clk CK_SCMI_MPU>;
			clock-names = "cpu";
			operating-points-v2 = <&cpu0_opp_table>;
			nvmem-cells = <&part_number_otp>;
			nvmem-cell-names = "part_number";
			#cooling-cells = <2>;
		};
	};

We can point also examples for I2C4 bus...

		i2c4: i2c@5c002000 {
			compatible = "st,stm32mp15-i2c";
			reg = <0x5c002000 0x400>;
			(...)
			clocks = <&scmi_clk CK_SCMI_I2C4>;
			resets = <&scmi_reset RST_SCMI_I2C4>;
			(...)
		};

... or the RTC device node.

		rtc: rtc@5c004000 {
			compatible = "st,stm32mp1-rtc";
			reg = <0x5c004000 0x400>;
			clocks = <&scmi_clk CK_SCMI_RTCAPB>,
				 <&scmi_clk CK_SCMI_RTC>;
			clock-names = "pclk", "rtc_ck";
			interrupts-extended = <&exti 19 IRQ_TYPE_LEVEL_HIGH>;
			(...)
		};

4. References[edit source]

Please refer to the following links for additional information: