1# Sensor Support for OpenBMC using phosphor-hwmon 2 3This document describes sensors provided by [phosphor-hwmon][15]. An alternate 4method is to use the suite of applications provided by [dbus-sensors][16]. While 5the configuration details between the two methods differ, the D-Bus 6representation remains mostly the same. 7 8OpenBMC makes it easy to add sensors for your hardware and is compliant with the 9traditional Linux HWMon sensor format. The architecture of OpenBMC sensors is to 10map sensors to [D-Bus][1] objects. The D-Bus object will broadcast the 11`PropertiesChanged` signal when either the sensor or threshold value changes. It 12is the responsibility of other applications to determine the effect of the 13signal on the system. 14 15## D-Bus 16 17``` 18Service xyz.openbmc_project.Hwmon-<hash>.Hwmon1 19Path /xyz/openbmc_project/sensors/<type>/<label> 20Interfaces xyz.openbmc_project.Sensor.[*], others (see below) 21 22Signals: All properties for an interface will broadcast signal changed 23``` 24 25**Path definitions** 26 27- **<type\>** : The [HWMon class][2] name in lower case. 28 29 - Examples include `temperature, fan_tach, voltage`. 30 31- **<label\>** : User defined name of the sensor. 32 - Examples include `ambient, cpu0, fan5` 33 34**Note**: The label shall comply with "Valid Object Paths" of [D-Bus Spec][3], 35that shall only contain the ASCII characters "[A-Z][a-z][0-9]\_". 36 37**Hash definition** 38 39The hash value in the service name is used to give the service a unique and 40stable name. It is a decimal number that is obtained by hashing characteristics 41of the device it is monitoring using std::hash(). 42 43## Redfish 44 45The [BMCWeb Redfish][10] support returns information about sensors. The support 46depends on two types of [ObjectMapper associations][11] to find the necessary 47sensor information on D-Bus. 48 49### Association Type #1: Linking a chassis to all sensors within the chassis 50 51Sensors are grouped by chassis in Redfish. An ObjectMapper association is used 52to link a chassis to all the sensors within the chassis. This includes the 53sensors for all hardware that is considered to be within the chassis. For 54example, a chassis might contain two fan sensors, an ambient temperature sensor, 55and a VRM output voltage sensor. 56 57#### D-Bus object paths 58 59The association links the following D-Bus object paths together: 60 61- Chassis inventory item object path 62- List of sensor object paths for sensors within the chassis 63 64#### Association names 65 66- "all_sensors" 67 - Contains the list of all sensors for this chassis 68- "chassis" 69 - Contains the chassis associated with this sensor 70 71#### Example associations 72 73- /xyz/openbmc_project/inventory/system/chassis/all_sensors 74 - "endpoints" property contains 75 - /xyz/openbmc_project/sensors/fan_tach/fan0_0 76 - /xyz/openbmc_project/sensors/fan_tach/fan0_1 77 - /xyz/openbmc_project/sensors/temperature/ambient 78 - /xyz/openbmc_project/sensors/voltage/p0_vdn_voltage 79- /xyz/openbmc_project/sensors/fan_tach/fan0_0/chassis 80 - "endpoints" property contains 81 - /xyz/openbmc_project/inventory/system/chassis 82 83### Association Type #2: Linking a low-level hardware item to its sensors 84 85A sensor is usually related to a low-level hardware item, such as a fan, power 86supply, VRM, or CPU. The Redfish sensor support can obtain the following 87information from the related hardware item: 88 89- Presence ([Inventory.Item interface][12]) 90- Functional state ([OperationalStatus interface][13]) 91- Manufacturer, Model, PartNumber, SerialNumber ([Decorator.Asset 92 interface][14]) 93 94For this reason, an ObjectMapper association is used to link a low-level 95hardware item to its sensors. For example, a processor VRM could have 96temperature and output voltage sensors, or a dual-rotor fan could have two tach 97sensors. 98 99#### D-Bus object paths 100 101The association links the following D-Bus object paths together: 102 103- Low-level hardware inventory item object path 104- List of sensor object paths for sensors related to that hardware item 105 106#### Association names 107 108- "sensors" 109 - Contains the list of sensors for this low-level hardware item 110- "inventory" 111 - Contains the low-level hardware inventory item for this sensor 112 113#### Example associations 114 115- /xyz/openbmc_project/inventory/system/chassis/motherboard/fan0/sensors 116 - "endpoints" property contains 117 - /xyz/openbmc_project/sensors/fan_tach/fan0_0 118 - /xyz/openbmc_project/sensors/fan_tach/fan0_1 119- /xyz/openbmc_project/sensors/fan_tach/fan0_0/inventory 120 - "endpoints" property contains 121 - /xyz/openbmc_project/inventory/system/chassis/motherboard/fan0 122 123## Development Details 124 125Sensor properties are standardized based on the type of sensor. A Threshold 126sensor contains specific properties associated with the rise and fall of a 127sensor value. The [Sensor Interfaces][4] are described in their respective YAML 128files. The path location in the source tree is identical to the interface being 129described below the [phosphor-dbus-interfaces][5] parent directory. 130 131 example: 132[openbmc/phosphor-dbus-interfaces/xyz/openbmc_project/Sensor/Threshold/Warning.yaml][6] 133 134 Maps to D-Bus interface 135`xyz.openbmc_project.Sensor.Threshold.Warning` 136 137Each 'name' property in the YAML file maps directly to D-Bus properties. 138 139 example: 140 141 [Warning.interface.yaml][6] 142 143``` 144properties: 145 - name: WarningHigh 146 type: int64 147 - name: WarningLow 148 type: int64 149 - name: WarningAlarmHigh 150 type: boolean 151 - name: WarningAlarmLow 152 type: boolean 153``` 154 155Maps to 156 157``` 158busctl --system introspect xyz.openbmc_project.Hwmon-3301914901.Hwmon1 \ 159 /xyz/openbmc_project/Sensors/temperature/ambient \ 160 xyz.openbmc_project.Sensor.Threshold.Warning | grep property 161 162.WarningAlarmHigh property b false emits-change writable 163.WarningAlarmLow property b false emits-change writable 164.WarningHigh property x 40000 emits-change writable 165.WarningLow property x 10000 emits-change writable 166 167``` 168 169### REST 170 171``` 172"/xyz/openbmc_project/Sensors/temperature/ambient": { 173 "Scale": -3, 174 "Unit": "xyz.openbmc_project.Sensor.Value.Unit.DegreesC", 175 "Value": 30125, 176 "WarningAlarmHigh": 0, 177 "WarningAlarmLow": 0, 178 "WarningHigh": 40000, 179 "WarningLow": 10000 180} 181``` 182 183### Other Interfaces 184 185Aside from the `xyz.openbmc_project.Sensor` interfaces, the sensor D-Bus objects 186may also expose the following interfaces: 187 1881. `xyz.openbmc_project.Control.FanSpeed` 189 - Provides a Target property to set a fan RPM value 1902. `xyz.openbmc_project.Control.FanPwm` 191 - Provides a Target property to set a fan PWM value 1923. `xyz.openbmc_project.State.Decorator.OperationalStatus` 193 - Provides a Functional property that tracks the state of any fault files 194 195### Signals 196 197Any property value change broadcasts a signal on D-Bus. When a value trips past 198a threshold, an additional D-Bus signal is sent. 199 200Example, if the value of WarningLow is 5... 201 202| From | To | propertyChanged Signals | 203| ---- | --- | ------------------------------------------------------------------------------------------------------------------------ | 204| 1 | 5 | "xyz.openbmc_project.Sensor.Value" : value = 5 | 205| 1 | 6 | "xyz.openbmc_project.Sensor.Value" : value = 6 ,<br>"xyz.openbmc_project.Sensor.Threshold.Warning" : WarningAlarmLow = 0 | 206| 5 | 6 | "xyz.openbmc_project.Sensor.Value" : value = 6 | 207| 6 | 1 | "xyz.openbmc_project.Sensor.Value" : value = 1 ,<br>"xyz.openbmc_project.Sensor.Threshold.Warning" : WarningAlarmLow = 1 | 208 209### System Configuration 210 211On the BMC each sensor's configuration is located in a file. These files can be 212found as a child of the `/etc/default/obmc/hwmon` path. 213 214## Creating a Sensor 215 216HWMon sensors are defined in the `recipes-phosphor/sensor/phosphor-hwmon%` path 217within the [machine configuration][7]. The children of the `obmc/hwmon` 218directory should follow the path of either: 219 2201. The children of the `devicetree/base` directory path on the system, as 221 defined by the kernel. The code obtains this from the OF_FULLNAME udev 222 environment variable. 223 2242. If the device isn't in the device tree, then the device path can be used. 225 226As an example, the Palmetto [configuration][8] file for the ambient temperature 227sensor. 228 229``` 230recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/bus@1e78a000/i2c-bus@c0/tmp423@4c.conf 231``` 232 233which maps to this specific sensor and conf file on the system... 234 235``` 236/sys/firmware/devicetree/base/ahb/apb/bus@1e78a000/i2c-bus@c0/tmp423@4c 237/etc/default/obmc/hwmon/ahb/apb/bus@1e78a000/i2c@c0/tmp423@4c.conf 238``` 239 240This next example shows using the device path as opposed to the devicetree path 241for the OCC device on an OpenPOWER system. Note how a '--' replaces a ':' in the 242directory names for the conf file. 243 244``` 245recipes-phosphor/sensors/phosphor-hwmon%/obmc/hwmon/devices/platform/gpio-fsi/fsi0/slave@00--00/00--00--00--06/sbefifo1-dev0/occ-hwmon.1.conf 246``` 247 248which maps to this specific sensor and conf file on the system... 249 250``` 251/sys/devices/platform/gpio-fsi/fsi0/slave@00:00/00:00:00:06/sbefifo1-dev0/occ-hwmon.1 252/etc/default/obmc/hwmon/devices/platform/gpio-fsi/fsi0/slave@00--00/00--00--00--06/sbefifo1-dev0/occ-hwmon.1.conf 253``` 254 255In order for the sensor to be exposed to D-Bus, the configuration file must 256describe the sensor attributes. Attributes follow a format. 257 258``` 259xxx_yyy#=value 260 261xxx = Attribute 262# = Association number (i.e. 1-n) 263yyy = HWMon sensor type (i.e. temp, pwm) 264``` 265 266| Attribute | Interfaces Added | 267| -------------- | -------------------------------------- | 268| LABEL | xyz.openbmc_project.Sensor.Value | 269| WARNHI, WARNLO | xyz.openbmc_project.Threshold.Warning | 270| CRITHI, CRITLO | xyz.openbmc_project.Threshold.Critical | 271 272The HWMon sensor type 273 274| [HWMon sensor type][2] | type | 275| ---------------------- | ---------------------------- | 276| temp | temperature | 277| in | voltage | 278| \* | All other names map directly | 279 280See the [HWMon interface][2] definitions for more definitions and keyword 281details 282 283In this conf example the tmp423 chip is wired to two temperature sensors. The 284values must be described in 10<sup>-3</sup> degrees Celsius. 285 286``` 287LABEL_temp1=ambient 288WARNLO_temp1=10000 289WARNHI_temp1=40000 290 291LABEL_temp2=cpu 292WARNLO_temp2=10000 293WARNHI_temp2=80000 294``` 295 296#### Additional Config File Entries 297 298The phosphor-hwmon code supports these additional config file entries: 299 300**INTERVAL** 301 302The interval, in microseconds, at which sensors should be read. If not specified 303the interval is 1000000us (1 second). 304 305``` 306INTERVAL=1000000 307``` 308 309**GAIN**, **OFFSET** 310 311Used to support scaled sensor readings, where value = (raw sensor reading) \* 312gain + offset 313 314``` 315GAIN_in3 = 5.0 #GAIN is a double 316OFFSET_in3 = 6 #OFFSET is an integer 317``` 318 319**MINVALUE**, **MAXVALUE** 320 321If found, will be used to set the MinValue/MaxValue properties on the 322`xyz.openbmc_project.Sensor.Value` interface. 323 324``` 325MINVALUE_temp1 = 1 326``` 327 328**MODE** 329 330Needed for certain device drivers, specifically the OpenPOWER OCC driver, where 331the instance number (the N in tempN_input) is dynamic and instead another file 332contains the known ID. 333 334For example 335 336``` 337temp26_input:29000 338temp26_label:171 339``` 340 341Where the 26 is just what hwmon assigns, but the 171 corresponds to something 342like an IPMI sensor value for a DIMM temperature. 343 344The config file would then have: 345 346``` 347MODE_temp26 = "label" #Tells the code to look in temp26_label 348LABEL_temp171 = "dimm3_temp" #Says that temp26_input holds dimm3_temp 349``` 350 351**REMOVERCS** 352 353Contains a list of device driver errno values where if these are obtained when 354reading the hardware, the corresponding sensor object will be removed from D-Bus 355until it is successfully read again. 356 357``` 358REMOVERCS = "5,6" #If any sensor on the device returns a 5 or 6, remove it. 359REMOVERCS_temp1 = "42" #If reading temp1_input returns a 42, remove it. 360``` 361 362**TARGET_MODE** 363 364Allows one to choose the fan target mode, either RPM or PWM, if the device 365driver exposes both methods. 366 367``` 368TARGET_MODE = "RPM" 369``` 370 371**PWM_TARGET** 372 373For fans that are PWM controlled, can be used to map the pwmN file to a fan M. 374 375``` 376PWM_TARGET_fan0 = 1 #Use the pwm1 file to control fan 0 377``` 378 379**ENABLE** 380 381Will write a value to a pwmN_enable file on startup if present. 382 383``` 384ENABLE_fan1 = 2 #Write a 2 to pwm1_enable 385``` 386 387### Defining sensors in an IPMI YAML configuration file 388 389For an example of how sensors entries are defined, consult the 390[example YAML](https://github.com/openbmc/phosphor-host-ipmid/blob/master/scripts/sensor-example.yaml) 391 392#### How to best choose coefficients 393 394Sensor reading, according to IPMI spec, is calculated as: 395 396```none 397y = L[(Mx + B * 10^(bExp)) * 10^(rExp)] 398``` 399 400- y: the 'final value' as reported by IPMItool 401- x: 8 bits, unsigned, reading data encoded in IPMI response packet 402- M: 10 bits, signed integer multiplier, `multiplierM` in YAML 403- B: 10 bits, signed additive offset, `offsetB` in YAML 404- bExp: 4 bits, signed, `bExp` in YAML 405- rExp: 4 bits, signed, `rExp` in YAML 406 407In addition, phosphor-ipmi-host configuration also supports `scale` property, 408which applies for analog sensors, meaning the value read over DBus should be 409scaled by 10^S. 410 411As you can tell, one should choose the coefficients based on possible sensor 412reading range and desired resolution. Commonly, B=0, we would have 413 414 Supported range: [0, 255 * M * 10^(scale - rExp)] 415 Resolution: M * 10^(scale - rExp) 416 417For a concrete example, let's say a voltage sensor reports between 0 to 5.0V. 418hwmon sysfs scales the value by 1000, so the sensor value read over DBus is 419between 0 and 5000. A possible configuration for this is: 420 421```none 422multiplierM: 20 423offsetB: 0 424bExp: 0 425rExp: -3 426scale: -3 427``` 428 429so for a DBus sensor value of 4986 meaning 4.986V, phosphor-ipmi-host would 430encode it as 431 432 x: 4986 / 20 = 249 433 M: 20 434 rExp: -3 435 436When ipmitool sensor list is called, the tool fetches sensor factors and 437computes value as: 438 439```none 440y = 20 * 249 * 10^-3 = 4.98 (V) 441``` 442 443## Additional Reading 444 445Mailing List [Comments on Sensor design][9] 446 447[1]: https://dbus.freedesktop.org/doc/dbus-tutorial.html 448[2]: https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface 449[3]: https://dbus.freedesktop.org/doc/dbus-specification.html#basic-types 450[4]: 451 https://github.com/openbmc/phosphor-dbus-interfaces/tree/master/yaml/xyz/openbmc_project/Sensor 452[5]: https://github.com/openbmc/phosphor-dbus-interfaces 453[6]: 454 https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Sensor/Threshold/Warning.interface.yaml 455[7]: https://github.com/openbmc/openbmc/tree/master/meta-openbmc-machines 456[8]: 457 https://github.com/openbmc/openbmc/blob/master/meta-ibm/meta-palmetto/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/bus@1e78a000/i2c-bus@c0/tmp423@4c.conf 458[9]: https://lists.ozlabs.org/pipermail/openbmc/2016-November/005309.html 459[10]: https://github.com/openbmc/bmcweb/blob/master/DEVELOPING.md#redfish 460[11]: 461 https://github.com/openbmc/docs/blob/master/architecture/object-mapper.md#associations 462[12]: 463 https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Inventory/Item.interface.yaml 464[13]: 465 https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/State/Decorator/OperationalStatus.interface.yaml 466[14]: 467 https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Inventory/Decorator/Asset.interface.yaml 468[15]: https://github.com/openbmc/phosphor-hwmon 469[16]: https://github.com/openbmc/dbus-sensors 470