![]() |
RT-Thread RTOS
An open source embedded real-time operating system
|
Overview and protocol drivers: SCMI firmware protocol.
Implementation directory: **components/drivers/firmware/arm_scmi/**.
The agent is the only piece that knows how to move a struct rt_scmi_msg across the SoC boundary. Every rt_scmi_device on the SCMI bus shares the same **struct scmi_agent** instance created during platform **scmi_probe**.
| Callback | When it runs |
|---|---|
setup | Once per SCMI controller: parse DT, map shmem, request mailbox channel / program SMC |
process_msg | Every rt_scmi_process_msg() — serialize request, wait for reply, fill out_msg |
rt_scmi_process_msg() (agent.c) sets msg->sdev and calls agent->ops->process_msg.
**scmi_probe** sequence:
agent_ops = pdev->id->data — transport selected by compatible.agent_ops->setup(agent, &pdev->parent) — transport private state in agent->priv.scmi_channels_setup**: for each available child of the controller node, read **reg** → protocol_id, allocate rt_scmi_device, set sdev->agent, rt_scmi_device_register(sdev).SCMI_PROTOCOL_ID_BASE** (common protocol) on the same agent.Protocol drivers attach later via the SCMI bus (see main SCMI page).
Mailbox and SMC transports place the SCMI frame in **struct scmi_shared_mem**:
channel_status — FREE / ERROR bits; writer clears FREE before sending.msg_header — built with scmi_header(message_id, type, protocol_id, token) from scmi.h.msg_payload[] — command input; reply read back into msg->out_msg.| API | Role |
|---|---|
scmi_shmem_msg_write(shmem, msg) | Pack header + in_msg, mark channel busy |
scmi_shmem_msg_read(shmem, msg) | Copy reply after firmware marks channel free |
scmi_shmem_clear_channel(shmem) | Reset channel after TX done (mailbox) |
DT **shmem** phandle must point at a node with **compatible = "arm,scmi-shmem"**; address is **rt_ioremap**’d in agent setup.
Ensure the mapping matches firmware expectations (often device / non-cacheable). If the region is cacheable, flush or invalidate around access per your BSP / TRM.
Depends on **RT_USING_MBOX** and RT_FIRMWARE_ARM_SCMI_TRANSPORT_MAILBOX.
Setup
mboxes** and **shmem** phandles; pick channel index when multiple mailboxes exist (e.g. high vs low priority).rt_mbox_request_by_index() with client callbacks:tx_prepare** → scmi_shmem_msg_write()tx_done** → scmi_shmem_clear_channel() on successrx_callback** → optional msg->rx_callback for async use**process_msg**
rt_mbox_send(chan, msg, timeout) (30 ticks in tree).Typical DT:
See Mailbox subsystem and Mailbox device model (DM).
Depends on **RT_FIRMWARE_ARM_SCMI_TRANSPORT_SMC**.
Setup
arm,smc-id** — SMC function number for SCMI.shmem** like mailbox; optional **interrupts** — ISR sets done flag.arm,scmi-smc-param** use page/offset fields in struct scmi_agent_smc for shared memory location passed in registers.**process_msg**
smccc** call, waits for IRQ or polling done, reads reply from shmem.Use when firmware exposes SCMI only through EL3 traps (no separate mailbox IP).
Enabled when **RT_VIRTIO_SCMI** / RT_FIRMWARE_ARM_SCMI_TRANSPORT_VIRTIO is on. **compatible = "arm,scmi-virtio"** selects scmi_agent_virtio_ops — SCMI over a virtio queue instead of SoC mailbox/SMC. Typical in guest / hypervisor scenarios.
| Return | Meaning |
|---|---|
-RT_* from setup / process_msg | RT-Thread transport failure (ENOMEM, EIO, mbox timeout, …) |
out.status / payload status field | Firmware **SCMI_ERR_*** — use rt_scmi_strerror(status) for logs |
Do not assume firmware status equals POSIX -errno unless your wrapper converts it (protocol drivers often map SCMI_SUCCESS to RT_EOK explicitly).
components/drivers/firmware/arm_scmi/agent.ccomponents/drivers/firmware/arm_scmi/agent-mailbox.ccomponents/drivers/firmware/arm_scmi/agent-smc.ccomponents/drivers/virtio/virtio-scmi.c