PLDM Service
Overview
The DMC PLDM service exposes platform sensor data to a BMC over MCTP-on-I3C. It is implemented as a Zephyr driver.
Acronyms used in this document:
Acronym |
Expansion |
Description |
|---|---|---|
BMC |
Baseboard Management Controller |
Requester side that discovers PLDM capabilities and reads sensor values. |
DAA |
Dynamic Address Assignment |
I3C enumeration step where the controller assigns runtime addresses to targets. |
DMC |
Device Management Controller |
Target/responder firmware side in this project. |
DMTF |
Distributed Management Task Force |
Standards body that publishes PLDM and MCTP specifications used by this service. |
DT |
Device Tree |
Hardware description data used to configure Zephyr, including PLDM sensor bindings and endpoint wiring. |
I3C |
Improved Inter-Integrated Circuit |
Physical bus used for target connectivity and message transport in this integration. |
MCTP |
Management Component Transport Protocol |
Transport layer that carries PLDM messages between requester and responder. |
PDR |
Platform Descriptor Record |
Structured records describing platform entities and sensors used by PLDM discovery. |
PLDM |
Platform Level Data Model |
DMTF protocol used here for platform discovery and sensor telemetry commands. |
TID |
Terminus ID |
PLDM identifier returned by |
Architecture
Component view
block
columns 6
block:BMC_CONTAINER
columns 1
space
BMC["BMC"]
space
end
block:DMC:4
columns 5
space
space
LABEL["DMC"]
space
space
DMC_TGT_IF["I3C Target Ctrl"]
space
space
space
DMC_SENSORS["DMC Sensors"]
MCTP_BIND["MCTP Target"]
space
block:PLDM
columns 1
PLDM_LABEL["PLDM"]
PLDM_SENS_BIND["Sensor Bindings"]
PDR_REPO["PDR"]
PLDM_RESP["Responder"]
end
space
SMC_SENSORS["SMC Sensors"]
end
block:SMC_CONTAINER
columns 1
space
space
SMC["SMC"]
end
style BMC_CONTAINER fill:none,stroke:none,stroke-width:0px
style LABEL fill:none,stroke:none,stroke-width:0px,font-weight:bold
style PLDM_LABEL fill:none,stroke:none,stroke-width:0px,font-weight:bold
style SMC_CONTAINER fill:none,stroke:none,stroke-width:0px,font-weight:bold
BMC --- DMC_TGT_IF
DMC_TGT_IF --- MCTP_BIND
MCTP_BIND --- PLDM_RESP
SMC_SENSORS --- PLDM_SENS_BIND
SMC_SENSORS --- SMC
DMC_SENSORS --- PLDM_SENS_BIND
PLDM_SENS_BIND --- PDR_REPO
PDR_REPO --- PLDM_RESP
Request/Response Ladder Example
sequenceDiagram
participant BMC as BMC
participant I3C as I3C Target Interface
participant MCTP as MCTP I3C Target Binding
participant RESP as PLDM Responder
participant PDR as PDR Repository Builder
participant MAP as PLDM Sensor Bindings
participant SNS as Sensor Nodes
BMC->>I3C: PLDM over MCTP frame
I3C->>MCTP: Deliver frame payload
I3C-->>BMC: I3C Write Acknowledged
MCTP->>RESP: Dispatch PLDM request
alt PDR discovery path
RESP->>PDR: GetPDRRepositoryInfo / GetPDR
PDR-->>RESP: Repository metadata / record data
else Sensor reading path
RESP->>MAP: Resolve sensor-id to descriptor
MAP->>SNS: sensor_sample_fetch + sensor_channel_get
SNS-->>MAP: sensor_value
MAP-->>RESP: Scaled PLDM reading
end
RESP-->>MCTP: PLDM response
MCTP-->>I3C: MCTP frame
alt IBI
I3C-->>BMC: IBI
BMC->>I3C: I3C read
else Polling
BMC->>I3C: I3C read
end
I3C-->>BMC: MCTP response on bus
I3C Target Interface
This service uses the STM32 I3C peripheral in target mode. It acts as the physical endpoint for
incoming management traffic. In the DT, zephyr,mctp-i3c-target binds to that target-mode
controller and exposes an MCTP transport endpoint to the PLDM responder.
This interface is responsible for:
participating in I3C bus enumeration/addressing driven by the BMC
receiving/sending MCTP frames over I3C once the endpoint is reachable
passing payloads up to the MCTP binding used by the PLDM responder
MCTP I3C Target Binding
The service uses Zephyr’s upstream zephyr,mctp-i3c-target binding/API as
the transport shim between the STM32 I3C target peripheral and libmctp.
At init time, the binding instance is created from DT and then registered as a bus with libmctp.
PLDM Responder
The PLDM responder is the protocol-facing driver component that sits above the MCTP I3C target binding and serves PLDM requests from the BMC.
Responsibilities:
initializes responder context and connects PLDM processing to MCTP RX/TX
handles PLDM Base discovery commands (for example
GetTID,GetPLDMTypes,GetPLDMCommands)dispatches PLDM Platform commands to repository/handler logic
references a dedicated PDR provider node that supplies descriptor data for repository generation and sensor reads
PDR Builder and Platform Handlers
The PDR builder/platform handler component manages PLDM Platform repository state and serves PDR-related commands from the responder.
Responsibilities:
binds numeric-sensor descriptors from
tenstorrent,pldm-pdrchild nodesbuilds the in-memory PDR repository at init
appends records in handle order (Terminus Locator, Numeric Sensor, and Sensor Auxiliary Names when
sensor-nameis present)serves repository metadata and record payloads for
GetPDRRepositoryInfoandGetPDR
Field sources
The current implementation does not negotiate PDR content at runtime. The repository is assembled once at init from a mix of DT-provided values, DT-derived defaults, and fixed code constants.
Terminus Locator PDR
Field |
Source |
Notes |
|---|---|---|
|
Static code |
Starts at |
|
Static code |
Set to |
|
Static code |
Set to |
|
Static code |
Fixed at |
|
Static code |
Computed from the encoded struct size. |
|
Static code |
Fixed at |
|
Static code |
Set to |
|
DTS |
Comes from |
|
Static code |
Fixed at |
|
Static code |
Set to |
|
Static code |
Fixed at |
|
DTS |
Comes from |
Numeric Sensor PDR
Field |
Source |
Notes |
|---|---|---|
|
Static code |
Assigned sequentially after the Terminus Locator record. |
|
Static code |
Set to |
|
Static code |
Set to |
|
Static code |
Fixed at |
|
Static code |
Computed from the struct size. |
|
Static code |
Fixed at |
|
DTS |
From |
|
DTS |
From |
|
DTS |
From |
|
DTS |
From |
|
DTS-derived |
Set when |
|
DTS or DTS-derived |
Uses |
|
DTS |
From |
|
Static code |
Set to |
|
Static code |
Set to |
|
Static code |
Set to |
|
Static code |
Set to |
|
Static code |
Set to |
|
Static code |
Set to |
|
Static code |
Set to |
|
Static code |
Set to |
|
Static code |
Set to |
|
Static code |
Set to |
|
Static code |
Fixed at |
|
Static code |
Fixed at |
|
Static code |
Fixed at |
|
Static code |
Fixed at |
|
Static code |
Fixed at |
|
Static code |
Fixed at |
|
Static code |
Fixed at |
|
Static code |
Fixed at |
|
Static code |
Fixed at |
|
Static code |
Set to |
|
Static code |
Fixed at |
Sensor Auxiliary Names PDR
This record is emitted only when the numeric sensor node provides
sensor-name.
Field |
Source |
Notes |
|---|---|---|
|
Static code |
Assigned immediately after the owning Numeric Sensor PDR. |
|
Static code |
Set to |
|
Static code |
Set to |
|
Static code |
Fixed at |
|
Static code |
Computed from encoded locale and UTF-16BE name bytes. |
|
Static code |
Fixed at |
|
DTS |
Reuses the owning numeric sensor node’s |
|
Static code |
Fixed at |
|
Static code |
Fixed to |
|
DTS |
Encoded from |
Sensor Nodes
Any Zephyr sensor device API can be used to source PLDM sensor values. The binding from a sensor-compatible device to the PDR must be defined in DT in order to be visible via PLDM.
tenstorrent,bh-arc-telemetry acts as a DMC sensor driver to map SMC
telemetry tags to Zephyr sensor channels. Each child map entry binds:
channel-type+channel-indextelemetry-tagoptional
scale-micro(defaults to1000000)
A single sensor can be the backend for multiple exported PLDM sensor nodes.
DTS example
/ {
/* The I3C controller. In DMC, this will always use the STM I3C controller */
i3c1 : i3c1 {
status = "okay";
};
/* The MCTP binding. This will bind i3c1 to libmctp */
mctp_i3c_target: mctp_i3c_target {
compatible = "zephyr,mctp-i3c-target";
i3c = <&i3c1>;
endpoint-id = <11>;
};
/* The PLDM binding. This will bind the libmctp callbacks through to PLDM processing */
pldm_mctp_responder: pldm_mctp_responder {
compatible = "tenstorrent,pldm-mctp-responder";
mctp-target = <&mctp_i3c_target>;
pdr = <&pldm_pdr0>;
pldm-tid = <11>;
};
/* The SMC sensor driver. This allows SMC sensor readings to be visible via a
* Zephyr-style sensor driver.
*/
smc_sensor: smc_sensor {
compatible = "tenstorrent,bh-arc-telemetry";
status = "okay";
arc = <&chip0_arc>;
vcore {
channel-type = <14>; /* SENSOR_CHAN_VOLTAGE */
channel-index = <0>;
telemetry-tag = <TAG_VCORE>;
};
/* Add additional nodes here for more channel-> telemetry mappings */
};
/* The PDR repository builder. This links zephyr sensor devices to a PLDM_SENSOR_ID,
* valid across all builds. The entries here are used both to assemble the PDR and also link
* runtime sensor fetches of a given PLDM_SENSOR_ID to a given zephyr sensor.
*/
pldm_pdr0: pldm_pdr0 {
compatible = "tenstorrent,pldm-pdr";
pldm_voltage0: pldm_voltage0 {
compatible = "tenstorrent,pldm-numeric-sensor";
sensor = <&zephyr_voltage_sensor0>;
channel-type = <14>; /* SENSOR_CHAN_VOLTAGE */
channel-index = <0>;
sensor-id = <PLDM_SENSOR_ID>; /* Tenstorrent specific, obeying compatibility rules */
};
};
};
This illustrates the phandle chain:
mctp_i3c_target -> pldm_mctp_responder -> pldm_pdr0 ->
tenstorrent,pldm-numeric-sensor.
Implemented PLDM Commands
The responder currently implements the following command sets.
Base
GetTIDSetTIDGetPLDMTypesGetPLDMVersionGetPLDMCommands
Platform
GetPDRRepositoryInfoGetPDRGetSensorReading
OEM
The responder may advertise Tenstorrent OEM type 0x3F. These requests use
the standard PLDM transport over MCTP-on-I3C, with the command code selecting
the OEM operation. Some OEM services may be unavailable depending on the
enabled Kconfig options of the DMC build.
Command |
Command code |
Request fields |
Purpose |
|---|---|---|---|
|
|
|
Queue a shell command for execution. |
|
|
|
Poll status and read back output chunks for an earlier request. |
|
|
|
Cancel a queued or running shell request when possible. |
Examples
SMC Voltage Read Flow
sequenceDiagram
participant BMC as BMC
box rgb(240, 248, 255) DMC
participant PLDM as PLDM Responder
participant DRV as bh-arc-telemetry Driver
end
box rgb(245, 245, 245) SMBus
participant SMB as SMBus
end
box rgb(248, 255, 248) SMC
participant TM as SMC Telemetry
participant ZS as Zephyr Sensor API
end
loop Background telemetry update
TM->>ZS: sensor fetch
ZS->>TM: sensor_value (int, frac) -> 16.16
end
BMC->>PLDM: GetSensorReading(sensor-id)
PLDM->>DRV: sensor_sample_fetch + sensor_channel_get
DRV->>TM: read telemetry tag
TM-->>DRV: 16.16 voltage value
DRV-->>PLDM: sensor_value (int, frac)
PLDM-->>PLDM: scale by 10^-unit_modifier
PLDM-->>BMC: present_reading
SMC Voltage Read - SMC timeout
sequenceDiagram
participant BMC as BMC
box rgb(240, 248, 255) DMC
participant PLDM as PLDM Responder
participant DRV as bh-arc-telemetry Driver
end
box rgb(245, 245, 245) SMBus
participant SMB as SMBus
end
box rgb(248, 255, 248) SMC
participant TM as SMC Telemetry
participant ZS as Zephyr Sensor API
end
loop Background telemetry update
TM->>ZS: sensor fetch
ZS--xTM: sensor fetch error
end
BMC->>PLDM: GetSensorReading(sensor-id)
PLDM->>DRV: sensor_sample_fetch + sensor_channel_get
DRV->>SMB: read telemetry request
SMB--xDRV: timeout / NACK
DRV-->>PLDM: sensor read error
PLDM-->>BMC: GetSensorReading CC = PLDM_ERROR
Compatibility
To keep requester integrations stable across firmware revisions, this service uses a fixed-ID compatibility model.
Compatibility policy:
treat
sensor-idas the stable external contract; IDs are defined and documented in firmware source and should not be reassigneduse Sensor Auxiliary Names as presentation metadata only; names may evolve without changing the underlying
sensor-iddo not reuse an existing ID for a different meaning, unit, or entity mapping
when adding new sensors, allocate new IDs instead of repurposing old ones
for incompatible semantic changes, introduce a new ID and deprecate the old ID during migration
Requester guidance:
discover IDs from PDRs (
GetPDRRepositoryInfo+GetPDR), then use those IDs forGetSensorReadingdo not infer identity from record order or display name alone
Notes and limits
GetPDRsupports multipart transfer with CRC in final chunk.Current auxiliary name encoding is UTF-16BE with
enlanguage tag.