xref: /openbmc/docs/designs/inventory/gpio-based-hardware-inventory.md (revision abbf7355231fbd9d5231e136780c167f2a89494e)
1 # GPIO based hardware inventory
2 
3 Author: Alexander Hansen <alexander.hansen@9elements.com>
4 
5 Other contributors: Chu Lin <linchuyuan@google.com> (through their previous
6 works), Amithash Prasad <amithash@meta.com>
7 
8 Created: August 26, 2024
9 
10 Reference:
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 
15 Due to increasing complexity of server designs and different configurations of
16 the same system being possible, there is a need for a simple way to detect the
17 presence of cards, cables and other connected entities which may or may not be
18 plugged into a system. A subset of these entities support presence detection via
19 gpios. This design focuses on those.
20 
21 Connected entities detectable via other means are out of scope of this design.
22 
23 ## Background and References
24 
25 The existing design for the gpio based cable presence is partially implemented
26 and 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 
30 Currently the way to do gpio based presence detection is via
31 phosphor-multi-gpio-presence and phosphor-inventory-manager.
32 
33 The static inventory is declared and the inventory items are exposed at runtime
34 by phosphor-inventory-manager.
35 
36 The presence daemon then toggles the 'Present' property on dbus interface
37 xyz.openbmc_project.Inventory.Item.
38 
39 Additional item-specific properties are statically declared in the
40 phosphor-inventory-manager configuration.
41 
42 An 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 
48 In the example we have inventory item **dimm_c0a1** which has following
49 phosphor-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 
61 and 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 
119 The proposed design is to create a new daemon in the entity-manager repository,
120 which is 'gpio-presence-sensor'.
121 
122 It 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
128 sequenceDiagram
129 
130 participant PresenceDaemon
131 participant EM
132 participant AnyService
133 
134 note over PresenceDaemon: cable0 plug
135 
136 %% initial base configuration
137 
138 activate EM
139 EM ->> EM: PROBE true on <br> xyz.openbmc_project.FruDevice <br> PRODUCT_PRODUCT_NAME=Yosemite V4
140 EM ->> PresenceDaemon: expose Configuration <br> xyz.openbmc_project.Configuration.GPIODeviceDetect <br> Name=com.meta.Hardware.Yv4.cable0
141 deactivate EM
142 activate PresenceDaemon
143 PresenceDaemon ->> PresenceDaemon: create dbus matcher <br> in case our configuration is removed
144 
145 %% start forward flow
146 
147 PresenceDaemon ->> PresenceDaemon: detect Device present <br> via GPIO Event
148 PresenceDaemon ->> EM: expose <br>xyz.openbmc_project.Inventory.Source.DevicePresence <br> Name=com.meta.Hardware.Yv4.cable0
149 activate EM
150 deactivate PresenceDaemon
151 EM ->> EM: PROBE true on <br>xyz.openbmc_project.Inventory.Source.DevicePresence <br> Name=com.meta.Hardware.Yv4.cable0
152 EM ->> AnyService: expose new Configuration <br> Example: Voltage Sensor
153 deactivate EM
154 
155 activate AnyService
156 AnyService ->> AnyService: Example: <br> expose new Voltage Sensor
157 AnyService ->> AnyService: produce Sensor readings
158 
159 %% start reverse flow
160 note over PresenceDaemon: cable0 unplug
161 
162 activate PresenceDaemon
163 PresenceDaemon ->> PresenceDaemon: detect Device absent <br> via GPIO Event
164 PresenceDaemon ->> EM: remove <br>xyz.openbmc_project.Inventory.Source.DevicePresence <br> Name=com.meta.Hardware.Yv4.cable0
165 deactivate PresenceDaemon
166 
167 activate EM
168 EM ->> EM: PROBE false on <br>xyz.openbmc_project.Inventory.Source.DevicePresence <br> Name=com.meta.Hardware.Yv4.cable0
169 EM ->> AnyService: remove new Configuration <br> Example: Voltage Sensor
170 deactivate EM
171 AnyService ->> AnyService: remove Sensor
172 deactivate 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 
212 entity-manager already creates the needed dbus interfaces here. So there is no
213 need to make something new.
214 
215 Below is a PDI yaml file to describe the proposed configuration interface:
216 
217 ```yaml
218 description: >
219   Information to enable a daemon to probe hardware based on gpio values
220 properties:
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
240 if it detects the hardware:
241 
242 ```yaml
243 description: >
244   Information for a daemon to expose if hardware has been detected based on
245   xyz.openbmc_project.Configuration.GPIODeviceDetect interface
246 properties:
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 
254 entity-manager can then consider the hardware as present and expose the
255 inventory interfaces for it.
256 
257 ### Handling removal of the device
258 
259 In case the gpio state changes, 'gpio-presence-sensor' can remove the
260 `xyz.openbmc_project.Inventory.Source.DevicePresence` interface and
261 entity-manager can have a dbus matcher for that, to then remove the respective
262 inventory items and any inventory items detected below it aswell.
263 
264 ### Proposed changes in entity-manager
265 
266 entity-manager needs to be extended to handle a new type 'GPIODeviceDetect'
267 Exposes 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 
306 Below is an incomplete example of how such a config could look like.
307 
308 The new part is the `"Type": "GPIODeviceDetect"` which is conveniently named the
309 same 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 
354 Another configuration can then contain additional records for the newly detected
355 e.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 
381 There is a need to namespace configuration for devices probed via gpios,
382 according to their vendor or location in the system. "Name" is just a string but
383 it can be used to create namespacing with dots. This will prevent accidental
384 probing 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 
437 How will this be tested? How will this feature impact CI testing?
438 
439 The feature can be tested in the entity-manager repository. We can use
440 dbus-run-session to run an actual entity-manager to provide the configuration or
441 simply provide a hardcoded configuration for 'gpio-presence-sensor'. For the
442 gpio interactions, we can use `CONFIG_GPIO_SIM` or alternatively abstract the
443 gpio interactions into a separate class which can then be stubbed.
444