| # PSU Sensor Module |
| |
| <!--* |
| # Document freshness: For more information, see go/fresh-source. |
| freshness: { owner: 'tlbmc-dev' reviewed: '2026-07-28' } |
| *--> |
| |
| The PSU Sensor Module in tlBMC is responsible for reading multi-channel power |
| telemetries (including voltage, current, power, and temperature) from hardware |
| power controllers, voltage regulators, and PMBus chips via the Hwmon and I3C |
| sysfs Hardware Abstraction Layers (HALs). |
| |
| ## Purpose & Overview |
| |
| PSU Sensors interface with hardware power controllers, PMBus chips, power |
| bricks, and hotswap controllers to collect critical runtime physical telemetry. |
| When enabled as part of the sensor collection subsystem, this module discovers |
| and monitors multi-channel power and thermal attributes, exposing them as |
| standard Redfish `Sensor` resources within the |
| `/redfish/v1/Chassis/{id}/Sensors` collection and integrating them directly into |
| the underlying Redfish thermal and power subsystems. |
| |
| ## Central Configuration (central_config.proto) |
| |
| PSU Sensor telemetry collection is managed under the central |
| `SensorCollectorModule` configuration within `central_config.proto`. Enabling |
| the central sensor collector activates the discovery and lifecycle management of |
| all configured PSU sensors. |
| |
| Field Name | Type | Default Value | Description |
| :------------------------------------ | :-------------------------------- | :------------ | :---------- |
| `enabled` | `bool` | `false` | Controls whether the sensor collector module is active. |
| `allow_sensor_creation_failure` | `bool` | `false` | If true, non-fatal hardware sysfs probe failures do not abort central sensor collection. |
| `enable_threshold_monitoring` | `bool` | `false` | If true, creates a background monitoring task to track thresholds and log SEL events upon crossing. |
| `sensor_collection_append_sub_module` | `SensorCollectionAppendSubmodule` | `none` | Controls appending tlBMC-discovered sensors to external Redfish sensor collections. |
| `thermal_control_sub_module` | `ThermalControlSubmodule` | `none` | Submodule for orchestrating Redfish thermal and power subsystem integrations. |
| |
| ## Entity Manager Configuration Reference |
| |
| Platform hardware developers configure and activate PSU sensors by defining JSON |
| configuration blocks within Entity Manager configuration files. When an Entity |
| Manager block declares `Type` matching a supported PSU sensor and specifies |
| `"TlbmcOwned": true`, tlBMC parses the block and instantiates the underlying |
| channels via sysfs. |
| |
| | Attribute Name | Expected Type | Description | |
| | :------------------------- | :------------------- | :----------------------- | |
| | `Type` | `string` | The specific hardware | |
| : : : chip or driver type : |
| : : : (e.g., `"ADM1266"`, : |
| : : : `"PMBUS"`). : |
| | `Name` | `string` | Base entity name for the | |
| : : : sensor group and : |
| : : : configuration block. : |
| | `Bus` | `integer` / `string` | Logical I2C or I3C bus | |
| : : : number (or expression : |
| : : : like `"$bus"`). : |
| | `Address` | `string` | Hexadecimal device | |
| : : : address on the bus : |
| : : : (e.g., `"0x40"`). : |
| | `Labels` | `array` of `string` | List of sysfs Hwmon | |
| : : : channel labels to expose : |
| : : : (e.g., `["vout1", : |
| : : : "curr1", : |
| : : : "highestpin"]`). : |
| | `<Label>_Name` / | `string` (optional) | Custom Redfish resource | |
| : `Name<Index>` : : name for a specific : |
| : : : label channel. : |
| | `<Label>_Max` / | `number` (optional) | Custom maximum and | |
| : `<Label>_Min` : : minimum reading range : |
| : : : overrides. : |
| | `<Label>_Scale` / | `number` (optional) | Custom scaling factor | |
| : `<Label>_Offset` : : (`reading / scale + : |
| : : : offset`) override. : |
| | `Thresholds` | `array` of `object` | List of threshold | |
| : : : definitions (`Name`, : |
| : : : `Value`, `Direction`, : |
| : : : `Severity`, optional : |
| : : : `Label`). : |
| | `RelatedItem` | `object` (optional) | Relates the sensor | |
| : : : entity to a target : |
| : : : parent resource (`Id`, : |
| : : : `Type`). : |
| | `RedfishHidden` | `boolean` / `array` | Hides specific sensor | |
| : : : instances or all (`*` or : |
| : : : `true`) from Redfish : |
| : : : collections. : |
| | `AppendToSensorCollection` | `boolean` / `array` | Appends specific sensor | |
| : : : routes or all (`*` or : |
| : : : `true`) to Redfish : |
| : : : `SensorCollection`. : |
| | `SensorGroup` | `string` (optional) | Identifier for the | |
| : : : sensor group / root bus : |
| : : : topology association. : |
| | `TlbmcOwned` | `boolean` | Must be `true` for tlBMC | |
| : : : to discover and manage : |
| : : : this sensor entity. : |
| |
| ## Supported Chips & Drivers |
| |
| tlBMC registers a comprehensive hardware chip mapping table |
| (`kSupportedPsuSensorTypes`) that automatically associates Entity Manager `Type` |
| strings with Linux kernel sysfs driver names: |
| |
| | Entity Manager `Type` | Kernel Driver Name | Interface & Notes | |
| | :-------------------- | :----------------- | :-------------------------- | |
| | `ADM1266` | `"adm1266"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `ADM1272` | `"adm1272"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `ADM1273` | `"adm1275"` | Uses `adm1275` kernel | |
| : : : driver. : |
| | `BMR490` | `"bmr490"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `DPS800` | `"dps800"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `GOOGLE_TPU` | `"google_tpu"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `INA226` | `"ina226"` | Voltage and current | |
| : : : monitoring driver. : |
| | `LTC2991` | `"ltc2991"` | Octal I2C | |
| : : : voltage/current/temperature : |
| : : : monitor. : |
| | `LTC4287` | `"ltc4286"` | Uses `ltc4286` kernel | |
| : : : driver. : |
| | `LX6301` | `"lx6301"` | Standard I2C Hwmon driver. | |
| | `MAX20826` | `"max20826"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `MAX20830C` | `"max20830c"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `MAX20840C` | `"max20840c"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `MAX34451` | `"max34451"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `MP2925` | `"mp2925"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `MP2929` | `"mp2929"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `MP5998` | `"mp5998"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `PMBUS` | `"pmbus"` | Generic PMBus monitoring | |
| : : : interface. : |
| | `Q50SN12072` | `"q50sn12072"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `Q54SN120A4` | `"q54sn120a4"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `RAA228228` | `"raa228228"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `RAA229141` | `"raa229141"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `RAA229621` | `"raa229621"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `RAA229639` | `"raa229639"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `SBRMI_I3C` | `"sbrmi_i3c"` | **I3C Required Chip:** | |
| : : : Requires I3C Sysfs HAL : |
| : : : interaction : |
| : : : (`IsI3cPsuSensor`). : |
| | `SBTSI_I3C` | `"sbtsi_i3c"` | **I3C Required Chip:** | |
| : : : Requires I3C Sysfs HAL : |
| : : : interaction : |
| : : : (`IsI3cPsuSensor`). : |
| | `TDA38640` | `"tda38640"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `TDA38725` | `"tda38725"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `TDA38740` | `"tda38740"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `TPS25990` | `"tps25990"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `TPS546E25` | `"tps546e25"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `XDPE19284C` | `"xdpe19284c"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| | `XDPE1A2G5B` | `"xdpe1a2g5b"` | Standard I2C/PMBus Hwmon | |
| : : : driver. : |
| |
| > [!NOTE] Chips designated as **I3C Required Chips** (`SBTSI_I3C` and |
| > `SBRMI_I3C`) are verified via `PsuSensor::IsI3cPsuSensor` and utilize the |
| > `I3cSysfs` HAL for device detection and sysfs HWMon path resolution. |
| |
| ## Default Reading Properties & Scale Factors (kDefaultPsuSensorProperties) |
| |
| tlBMC automatically maps non-digit base labels (e.g., `vout1` stripped of |
| numbers -> `vout`) to standardized default physical reading properties |
| (`ReadingProperties`). This mapping assigns correct physical quantities, units |
| (`SensorUnit`), scale divisor powers (`pow(10, scale)`), and defaults: |
| |
| | Base Label | Physical | Default Unit | Scale | Default | |
| : : Quantity : : Divisor : Range : |
| : : : : (`pow(10, : (Min / : |
| : : : : scale)`) : Max) : |
| | :------------ | :---------- | :-------------------- | :---------- | :------- | |
| | `curr` / | Output | `UNIT_AMPERE` | `1000` | `0.0` / | |
| : `iout` : Current : : (`pow(10, : `255.0` : |
| : : : : 3)`) : A : |
| | `iin` | Input | `UNIT_AMPERE` | `1000` | `0.0` / | |
| : : Current : : (`pow(10, : `20.0` A : |
| : : : : 3)`) : : |
| | `isysin` / | System | `UNIT_AMPERE` | `1000` | `0.0` / | |
| : `isysout` : Current : : (`pow(10, : `255.0` : |
| : : : : 3)`) : A : |
| | `highestiout` | Peak Output | `UNIT_AMPERE` | `1000` | `0.0` / | |
| : / `peakiout` : Current : : (`pow(10, : `255.0` : |
| : : : : 3)`) : A : |
| | `vin` | Input | `UNIT_VOLT` | `1000` | `0.0` / | |
| : : Voltage : : (`pow(10, : `300.0` : |
| : : : : 3)`) : V : |
| | `in` / `vout` | Output | `UNIT_VOLT` | `1000` | `0.0` / | |
| : / `voltage` : Voltage : : (`pow(10, : `255.0` : |
| : : : : 3)`) : V : |
| | `vmon` | Auxiliary | `UNIT_VOLT` | `1000` | `0.0` / | |
| : : Input : : (`pow(10, : `255.0` : |
| : : Voltage : : 3)`) : V : |
| | `highestvin` | Peak Input | `UNIT_VOLT` | `1000` | `0.0` / | |
| : : Voltage : : (`pow(10, : `300.0` : |
| : : : : 3)`) : V : |
| | `highestvout` | Peak Output | `UNIT_VOLT` | `1000` | `0.0` / | |
| : : Voltage : : (`pow(10, : `255.0` : |
| : : : : 3)`) : V : |
| | `peakvin` | Peak Input | `UNIT_VOLT` | `1000` | `0.0` / | |
| : : Voltage : : (`pow(10, : `300.0` : |
| : : : : 3)`) : V : |
| | `peakvout` | Peak Output | `UNIT_VOLT` | `1000` | `0.0` / | |
| : : Voltage : : (`pow(10, : `255.0` : |
| : : : : 3)`) : V : |
| | `pin` | Input Power | `UNIT_WATT` | `1,000,000` | `0.0` / | |
| : : : : (`pow(10, : `3000.0` : |
| : : : : 6)`) : W : |
| | `pout` / | Output | `UNIT_WATT` | `1,000,000` | `0.0` / | |
| : `power` : Power : : (`pow(10, : `3000.0` : |
| : : : : 6)`) : W : |
| | `highestpin` | Peak Input | `UNIT_WATT` | `1,000,000` | `0.0` / | |
| : / `peakpin` : Power : : (`pow(10, : `3000.0` : |
| : : : : 6)`) : W : |
| | `temp` | Temperature | `UNIT_DEGREE_CELSIUS` | `1000` | `-128.0` | |
| : : : : (`pow(10, : / : |
| : : : : 3)`) : `127.0` : |
| : : : : : °C : |
| | `highesttemp` | Peak | `UNIT_DEGREE_CELSIUS` | `1000` | `-128.0` | |
| : / `peaktemp` : Temperature : : (`pow(10, : / : |
| : : : : 3)`) : `127.0` : |
| : : : : : °C : |
| |
| > [!TIP] When sysfs returns integer raw readings (e.g. millivolts, milliamps, |
| > microwatts), `PsuSensor::HandleRefreshResult` applies the final conversion: |
| > `reading = (raw_value / scale) + offset`. |
| |
| ## Special File Type Handling (PsuSensorFileType) |
| |
| To handle distinct historical sysfs file naming conventions across power |
| controller drivers, `PsuSensor::GetPsuSensorFileInfo` inspects sysfs file |
| suffixes and associates them with appropriate label modification prefixes: |
| |
| * **`kDefault` (`_input` suffix):** Standard telemetry input reading file |
| (e.g., `in1_input`, `temp1_input`). Applies an empty (`""`) label modifier |
| prefix. |
| * **`kHighestPower` (`_input_highest` suffix):** Special sysfs file generated |
| for peak power telemetries (e.g., `power1_input_highest`). Applies the |
| `"highest"` label modifier prefix. |
| * **`kHighestDefault` (`_highest` suffix):** Special sysfs file generated for |
| peak temperature or voltage defaults (e.g., `temp1_highest`). Applies the |
| `"highest"` label modifier prefix. |
| |
| **Label Normalization:** To maintain cross-platform compatibility where |
| integrators interchange `"highest"` and `"peak"` modifiers (e.g. `"highestpin"` |
| vs `"peakpin"`), tlBMC automatically maps both prefixes to the same underlying |
| sysfs input file. |
| |
| ## Sensor Key Generation (GetPsuSensorKey) |
| |
| Every instantiated PSU Sensor receives a fully qualified unique identifier |
| (`name`) within Redfish: |
| |
| 1. **Custom Name Check:** If the Entity Manager configuration explicitly |
| provides `<Label>_Name` or `Name<Index>`, that string is used directly. |
| 2. **Fallback Derivation:** Otherwise, combines the parent configuration block |
| name and the label's descriptive type name (e.g., `ADM1266_Input_Voltage`). |
| 3. **Unit Prefix Assignment:** Regardless of origin, `GetPsuSensorKey` prefixes |
| the final Redfish identifier based on its physical unit: |
| * `UNIT_AMPERE` $\rightarrow$ `current_{name}` |
| * `UNIT_VOLT` $\rightarrow$ `voltage_{name}` |
| * `UNIT_WATT` $\rightarrow$ `power_{name}` |
| * `UNIT_DEGREE_CELSIUS` $\rightarrow$ `temperature_{name}` |
| |
| ## Protobuf Configuration |
| |
| The following underlying protobuf schemas define the runtime data structures, |
| properties, and configuration parsing models for PSU Sensors: |
| |
| * [psu_sensor_config.proto](http://google3/third_party/milotic/external/cc/tlbmc/configs/psu_sensor_config.proto): |
| Defines `PsuSensorType` enums and the primary `PsuSensorConfig` message |
| mapping labels to instance properties. |
| * [hal_common_config.proto](http://google3/third_party/milotic/external/cc/tlbmc/configs/hal_common_config.proto): |
| Defines logical bus numbers and hardware addresses (`HalCommonConfig`). |
| * [sensor_instance_properties.proto](http://google3/third_party/milotic/external/cc/tlbmc/configs/sensor_instance_properties.proto): |
| Defines instance-specific units, thresholds, transforms, ranges, and |
| visibility flags (`SensorInstanceProperties`). |
| * [entity_common_config.proto](http://google3/third_party/milotic/external/cc/tlbmc/configs/entity_common_config.proto): |
| Defines entity-level refresh intervals, queue sizes, sensor groups, and |
| power state dependencies (`EntityCommonConfig`). |
| * [central_config.proto](http://google3/third_party/milotic/external/cc/tlbmc/central_config/central_config.proto): |
| Defines top-level collection orchestration options |
| (`SensorCollectorModule`). |
| * [reading_range_config.proto](http://google3/third_party/milotic/external/cc/tlbmc/configs/reading_range_config.proto): |
| Defines min/max operational reading ranges (`ReadingRangeConfigs`). |
| * [reading_transform_config.proto](http://google3/third_party/milotic/external/cc/tlbmc/configs/reading_transform_config.proto): |
| Defines scaling divisors and offsets (`ReadingTransformConfig`). |
| * [threshold_config.proto](http://google3/third_party/milotic/external/cc/tlbmc/configs/threshold_config.proto): |
| Defines critical and non-critical thresholds (`ThresholdConfigs`). |
| |
| ## Usage & Configuration Examples |
| |
| Below is a concrete, fully qualified Entity Manager configuration block defining |
| an `ADM1266` power supply controller on Bus 20 at Address `0x40`. It exposes |
| specific voltage channels and configures an upper critical threshold: |
| |
| ```json |
| { |
| "Address": "0x40", |
| "Bus": 20, |
| "Labels": [ |
| "vout1", |
| "vout5", |
| "vout6" |
| ], |
| "Name": "ADM1266", |
| "Thresholds": [ |
| { |
| "Direction": "greater than", |
| "Label": "vout1", |
| "Name": "upper critical", |
| "Severity": 1, |
| "Value": 13.56 |
| } |
| ], |
| "TlbmcOwned": true |
| } |
| ``` |
| |
| ## Code References |
| |
| * [psu_sensor.h](http://google3/third_party/milotic/external/cc/tlbmc/sensors/psu_sensor.h): |
| Main header defining `PsuSensor`, `PsuSensorFileType`, and scale mappings. |
| * [psu_sensor.cc](http://google3/third_party/milotic/external/cc/tlbmc/sensors/psu_sensor.cc): |
| Implementation file containing registered chip models, default properties, |
| and sysfs reading parsers. |
| * [entity_config_json_impl.cc](http://google3/third_party/milotic/external/cc/tlbmc/configs/entity_config_json_impl.cc): |
| Entity Manager JSON configuration parser implementing |
| `ParsePsuSensorConfig`. |