1# GPIO based hardware inventory 2 3Author: Alexander Hansen <alexander.hansen@9elements.com> 4 5Other contributors: Chu Lin <linchuyuan@google.com> (through their previous 6works), Amithash Prasad <amithash@meta.com> 7 8Created: August 26, 2024 9 10Reference: 11[Chu Lin's gpio based cable presence detection](https://github.com/openbmc/docs/blob/46902afd6ebd20d1148379df99fe2c0c591f56ba/designs/gpio-based-cable-presence.md) 12 13## Problem Description 14 15Due to increasing complexity of server designs and different configurations of 16the same system being possible, there is a need for a simple way to detect the 17presence of cards, cables and other connected entities which may or may not be 18plugged into a system. A subset of these entities support presence detection via 19gpios. This design focuses on those. 20 21Connected entities detectable via other means are out of scope of this design. 22 23## Background and References 24 25The existing design for the gpio based cable presence is partially implemented 26and focuses on IPMI use-case. 27 28[existing design by Chu Lin](https://github.com/openbmc/docs/blob/879601d92becfa1dbc082f487abfb5e0151a5091/designs/gpio-based-cable-presence.md) 29 30Currently the way to do gpio based presence detection is via 31phosphor-multi-gpio-presence and phosphor-inventory-manager. 32 33The static inventory is declared and the inventory items are exposed at runtime 34by phosphor-inventory-manager. 35 36The presence daemon then toggles the 'Present' property on dbus interface 37xyz.openbmc_project.Inventory.Item. 38 39Additional item-specific properties are statically declared in the 40phosphor-inventory-manager configuration. 41 42An example of how this is currently done: 43 44[presence daemon config](https://github.com/openbmc/openbmc/blob/1d438f68277cdb37e8062ae298402e9685882acb/meta-ibm/meta-sbp1/recipes-phosphor/gpio/phosphor-gpio-monitor/phosphor-multi-gpio-presence.json) 45 46[phosphor-inventory-manager config](https://github.com/openbmc/openbmc/blob/1d438f68277cdb37e8062ae298402e9685882acb/meta-ibm/meta-sbp1/recipes-phosphor/inventory/static-inventory/static-inventory.yaml) 47 48In the example we have inventory item **dimm_c0a1** which has following 49phosphor-multi-gpio-presence configuration: 50 51```json 52{ 53 "Name": "DIMM_C0A1", 54 "LineName": "PLUG_DETECT_DIMM_C0A1", 55 "ActiveLow": true, 56 "Bias": "PULL_UP", 57 "Inventory": "/system/chassis/motherboard/dimm_c0a1" 58} 59``` 60 61and phosphor-inventory-manager configuration: 62 63```yaml 64- name: Add DIMMs 65 description: > 66 Add the DIMM inventory path. 67 type: startup 68 actions: 69 - name: createObjects 70 objs: 71 /system/chassis/motherboard/dimm_c0a1: 72 xyz.openbmc_project.Inventory.Decorator.Replaceable: 73 FieldReplaceable: 74 value: true 75 type: boolean 76 xyz.openbmc_project.State.Decorator.OperationalStatus: 77 Functional: 78 value: true 79 type: boolean 80 xyz.openbmc_project.Inventory.Item: 81 PrettyName: 82 value: "DIMM C0A1" 83 type: string 84 Present: 85 value: false 86 type: boolean 87 xyz.openbmc_project.Inventory.Item.Dimm: 88 xyz.openbmc_project.Inventory.Decorator.LocationCode: 89 LocationCode: 90 value: "CPU0_DIMM_A1" 91 type: string 92``` 93 94## Requirements 95 96- Support the gpio based detection of inventory items without static 97 configuration 98 99- Allow configuration of the detectable inventory items through entity-manager 100 configuration 101 102 - e.g. cable 103 - e.g. fan board 104 - e.g. daughter board 105 - entity-manager should expose all required Inventory interfaces 106 - the properties for these inventory interfaces can be obtained through the 107 exposes record in the json configuration 108 109- When a device is detected as present using the GPIO configuration published by 110 entity-manager, its probe match data is published to D-Bus, which triggers 111 entity-manager to publish the associated configuration. 112 113- Support for re-use of presence information in PROBE statements 114 - detecting one entity as 'Present' should enable detecting other entities 115 based on that info 116 117## Proposed Design 118 119The proposed design is to create a new daemon in the entity-manager repository, 120which is 'gpio-presence-sensor'. 121 122It can be inspired by implementations found in downstream forks such as the 123[NVIDIA gpio presence sensor implementation](https://github.com/NVIDIA/dbus-sensors/blob/889abc1c9bfae9395690d1562f3e08453dfa12ba/src/GPIOPresenceSensorMain.cpp) 124 125### Diagram 126 127```mermaid 128sequenceDiagram 129 130participant PresenceDaemon 131participant EM 132participant AnyService 133 134note over PresenceDaemon: cable0 plug 135 136%% initial base configuration 137 138activate EM 139EM ->> EM: PROBE true on <br> xyz.openbmc_project.FruDevice <br> PRODUCT_PRODUCT_NAME=Yosemite V4 140EM ->> PresenceDaemon: expose Configuration <br> xyz.openbmc_project.Configuration.GPIODeviceDetect <br> Name=com.meta.Hardware.Yv4.cable0 141deactivate EM 142activate PresenceDaemon 143PresenceDaemon ->> PresenceDaemon: create dbus matcher <br> in case our configuration is removed 144 145%% start forward flow 146 147PresenceDaemon ->> PresenceDaemon: detect Device present <br> via GPIO Event 148PresenceDaemon ->> EM: expose <br>xyz.openbmc_project.Inventory.Source.DevicePresence <br> Name=com.meta.Hardware.Yv4.cable0 149activate EM 150deactivate PresenceDaemon 151EM ->> EM: PROBE true on <br>xyz.openbmc_project.Inventory.Source.DevicePresence <br> Name=com.meta.Hardware.Yv4.cable0 152EM ->> AnyService: expose new Configuration <br> Example: Voltage Sensor 153deactivate EM 154 155activate AnyService 156AnyService ->> AnyService: Example: <br> expose new Voltage Sensor 157AnyService ->> AnyService: produce Sensor readings 158 159%% start reverse flow 160note over PresenceDaemon: cable0 unplug 161 162activate PresenceDaemon 163PresenceDaemon ->> PresenceDaemon: detect Device absent <br> via GPIO Event 164PresenceDaemon ->> EM: remove <br>xyz.openbmc_project.Inventory.Source.DevicePresence <br> Name=com.meta.Hardware.Yv4.cable0 165deactivate PresenceDaemon 166 167activate EM 168EM ->> EM: PROBE false on <br>xyz.openbmc_project.Inventory.Source.DevicePresence <br> Name=com.meta.Hardware.Yv4.cable0 169EM ->> AnyService: remove new Configuration <br> Example: Voltage Sensor 170deactivate EM 171AnyService ->> AnyService: remove Sensor 172deactivate AnyService 173``` 174 175### Forward flow summary 176 177- EM exposes configuration for 'gpio-presence-sensor' 178- 'gpio-presence-sensor' creates a dbus matcher to watch for removal of it's 179 configuration 180- 'gpio-presence-sensor' uses gpios to detect hardware 181- 'gpio-presence-sensor' creates a dbus interface when it detects hardware 182- EM can probe new configuration files based on that dbus interface, via PROBE 183 statement 184- EM exposes the new configuration for the detected hardware 185 186### Reverse flow summary 187 188- 'gpio-presence-sensor' detects that the hardware is gone 189- 'gpio-presence-sensor' takes down the respective dbus interface 190- EM detects that via dbus matcher 191- EM removes the configuration for that hardware from dbus 192 193### Reverse flow summary (removal of configuration) 194 195- EM exposes configuration for 'gpio-presence-sensor' 196- 'gpio-presence-sensor' creates a dbus matcher to watch for removal of it's 197 configuration 198- 'gpio-presence-sensor' uses gpios to detect hardware 199- 'gpio-presence-sensor' creates a dbus interface when it detects hardware 200- EM removes the config for 'gpio-presence-sensor' 201- 'gpio-presence-sensor' takes down any dbus interfaces it created for detecting 202 hardware 203- EM detects that via dbus matcher 204- EM removes the configuration for that hardware from dbus 205 206### Proposed DBus Interfaces 207 208'gpio-presence-sensor' should consume configuration via dbus interface 209 210`xyz.openbmc_project.Configuration.GPIODeviceDetect` 211 212entity-manager already creates the needed dbus interfaces here. So there is no 213need to make something new. 214 215Below is a PDI yaml file to describe the proposed configuration interface: 216 217```yaml 218description: > 219 Information to enable a daemon to probe hardware based on gpio values 220properties: 221 - name: Name 222 type: string 223 description: > 224 Used by entity-manager to identify which hardware was detected. For 225 internal use by entity-manager. 226 - name: PresencePinNames 227 type: array[string] 228 description: > 229 Names of the gpio lines. 230 - name: PresencePinValues 231 type: array[uint64] 232 description: > 233 Values of the gpio lines for which the device is considered present. 234 Choosing 'uint64' instead of 'bool' here for compatibility with how EM 235 exposes configuration on dbus. 236``` 237 238'gpio-presence-sensor' then exposes 239`xyz.openbmc_project.Inventory.Source.DevicePresence` dbus interface of its own 240if it detects the hardware: 241 242```yaml 243description: > 244 Information for a daemon to expose if hardware has been detected based on 245 xyz.openbmc_project.Configuration.GPIODeviceDetect interface 246properties: 247 - name: Name 248 type: string 249 description: > 250 Used by entity-manager to identify which hw was detected. For internal use 251 by entity-manager. 252``` 253 254entity-manager can then consider the hardware as present and expose the 255inventory interfaces for it. 256 257### Handling removal of the device 258 259In case the gpio state changes, 'gpio-presence-sensor' can remove the 260`xyz.openbmc_project.Inventory.Source.DevicePresence` interface and 261entity-manager can have a dbus matcher for that, to then remove the respective 262inventory items and any inventory items detected below it aswell. 263 264### Proposed changes in entity-manager 265 266entity-manager needs to be extended to handle a new type 'GPIODeviceDetect' 267Exposes record. It needs to then create the 268`xyz.openbmc_project.Configuration.GPIODeviceDetect` dbus interface. 269 270#### Proposed EM Configuration Schema 271 272```json 273{ 274 "$schema": "http://json-schema.org/draft-07/schema#", 275 "$defs": { 276 "GPIODeviceDetect": { 277 "type": "object", 278 "properties": { 279 "Name": { 280 "type": "string" 281 }, 282 "Type": { 283 "type": "string" 284 }, 285 "PresencePinNames": { 286 "type": "array", 287 "items": { 288 "type": "string" 289 } 290 }, 291 "PresencePinValues": { 292 "type": "array", 293 "items": { 294 "type": "number" 295 } 296 } 297 }, 298 "required": ["Name", "Type", "PresencePinNames", "PresencePinValues"] 299 } 300 } 301} 302``` 303 304### Example EM Config Fragments 305 306Below is an incomplete example of how such a config could look like. 307 308The new part is the `"Type": "GPIODeviceDetect"` which is conveniently named the 309same as the Dbus interface. 310 311```json 312{ 313 Exposes: 314 [ 315 { 316 "Name": "com.meta.Hardware.Yv4.cable0", 317 "PresencePinNames": ["presence-cable0"], 318 "PresencePinValues": [1], 319 "Type": "GPIODeviceDetect" 320 }, 321 { 322 "Name": "com.meta.Hardware.Yv4.ComputeCard", 323 "PresencePinNames": ["presence-slot0a", "presence-slot0b"], 324 "PresencePinValues": [0, 1], 325 "Type": "GPIODeviceDetect" 326 }, 327 { 328 "Name": "com.meta.Hardware.Yv4.SidecarExpansion", 329 "PresencePinNames": ["presence-slot0a", "presence-slot0b"], 330 "PresencePinValues": [1, 0], 331 "Type": "GPIODeviceDetect" 332 }, 333 { 334 "Name": "com.meta.Hardware.Yv4.AirBlocker", 335 "PresencePinNames": ["presence-slot0a", "presence-slot0b"], 336 "PresencePinValues": [1, 1], 337 "Type": "GPIODeviceDetect" 338 }, 339 { 340 "Name": "com.meta.Hardware.Yv4.fanboard0", 341 "PresencePinNames": ["presence-fanboard0"], 342 "PresencePinValues": [0], 343 "Type": "GPIODeviceDetect" 344 }, 345 ... 346 ], 347 ... 348 "Name": "Chassis", 349 "Probe": "xyz.openbmc_project.FruDevice({'BOARD_PRODUCT_NAME': 'MYBOARDPRODUCT*'})", 350 "Type": "Board", 351} 352``` 353 354Another configuration can then contain additional records for the newly detected 355e.g. fan board. 356 357```json 358{ 359 Exposes: 360 [ 361 { 362 "Address": "0x28", 363 "Bus": 5, 364 "EntityId": 7, 365 "EntityInstance": 0, 366 "Name": "fanboard_air_inlet", 367 "Name1": "fanboard_air_outlet", 368 "Type": "NCT7802" 369 }, 370 ... 371 ], 372 ... 373 "Name": "My Fan Board 0", 374 "Probe": "xyz.openbmc_project.Inventory.Source.DevicePresence({'Name': 'com.meta.Hardware.Yv4.fanboard0'})", 375 "Type": "Board", 376} 377``` 378 379### Uniqueness of the "Name" property 380 381There is a need to namespace configuration for devices probed via gpios, 382according to their vendor or location in the system. "Name" is just a string but 383it can be used to create namespacing with dots. This will prevent accidental 384probing of unrelated configuration. 385 386## Alternatives Considered 387 388- The existing approach with phosphor-inventory-manager and static configuration 389 Leaning away from that because it cannot support multiple different chassis 390 configurations in one fw image. 391 392- Presence detection integrated into entity-manager. There already exists a 393 presence daemon, and it's an explicit non-goal of EM to implement any presence 394 detection. Maintainers have confirmed that EM should not implement this 395 feature internally. 396 397- Another daemon which would expose inventory items based on EM configuration. 398 This would mean EM does not need to expose the item-specific inventory 399 interfaces and properties. 400 401- Exposing the item-specific interfaces and properties in a generic way. This 402 means EM would lose any semantic knowledge of the entities it exposes and 403 become more like phosphor-inventory-manager 404 405- Preventing duplication in case of multiple instances of e.g. fan 406 board/daughter board/cable through an additional variable besides "Name" that 407 could then be used in the the configuration file of the entity. This is 408 already covered partially by `$index` but `$index` is not stable and depends 409 on order and count of the devices probed successfully. But this feature is 410 left out intentionally here to limit the scope. So multiple instances of a 411 daughter board may need multiple slightly different configuration files. 412 413- Comparing to Chu Lin's design, this design is not focused on the IPMI or 414 redfish use-case. It is separate from the external interface. It is assumed 415 the external interfaces can expose a cable inventory based on the 416 [cable dbus interface](https://github.com/openbmc/phosphor-dbus-interfaces/commit/3c5b76491afb8401627fc343077fe420f8a5e7f9) 417 which was created as part of Chu Lin's design. 418 419- Comparing to Chu Lin's design, this design does not directly provide a cable 420 inventory. So there is another daemon or configuration decorator needed to 421 expose a cable inventory item. 422 423- Comparing to Chu Lin's design, this design is not limited to cables. 424 425## Impacts 426 427### Organizational 428 429- Does this repository require a new repository? No 430- Who will be the initial maintainer(s) of this repository? 431- Which repositories are expected to be modified to execute this design? 432 - entity-manager 433- Make a list, and add listed repository maintainers to the gerrit review. 434 435## Testing 436 437How will this be tested? How will this feature impact CI testing? 438 439The feature can be tested in the entity-manager repository. We can use 440dbus-run-session to run an actual entity-manager to provide the configuration or 441simply provide a hardcoded configuration for 'gpio-presence-sensor'. For the 442gpio interactions, we can use `CONFIG_GPIO_SIM` or alternatively abstract the 443gpio interactions into a separate class which can then be stubbed. 444