1# Add a New System to OpenBMC
2
3**Document Purpose:** How to add a new system to the OpenBMC distribution
4
5**Audience:** Programmer familiar with OpenBMC
6
7**Prerequisites:** Completed Development Environment Setup [Document][32]
8
9## Overview
10
11**Please note:** This document is no longer officially supported by the OpenBMC
12team. It still contains a lot of useful information so it has been left here.
13Ideally this guide would become a standalone document (outside of the
14development tree) and would cover all of the different areas that must
15be updated to add a new system.
16
17This document will describe the following:
18
19* Review background about Yocto and BitBake
20* Creating a new system layer
21* Populating this new layer
22* Building the new system and testing in QEMU
23* Adding configs for sensors, LEDs, inventories, etc.
24
25## Background
26
27The OpenBMC distribution is based on [Yocto](https://www.yoctoproject.org/).
28Yocto is a project that allows developers to create custom Linux distributions.
29OpenBMC uses Yocto to create their embedded Linux distribution to run on
30a variety of devices.
31
32Yocto has a concept of hierarchical layers. When you build a Yocto-based
33distribution, you define a set of layers for that distribution. OpenBMC uses
34many common layers from Yocto as well as some of its own layers. The layers
35defined within OpenBMC can be found with the meta-* directories in OpenBMC
36[GitHub](https://github.com/openbmc/openbmc).
37
38Yocto layers are a combination of different files that define packages to
39incorporate in that layer. One of the key file types used in these layers is
40[BitBake](https://github.com/openembedded/bitbake/blob/master/README) recipes.
41
42BitBake is a fully functional language in itself. For this lesson, we will
43focus on only the aspects of BitBake required to understand the process of
44adding a new system.
45
46## Start the Initial BitBake
47
48For this work, you will need to have allocated at least 100GB of space to your
49development environment and as much memory and CPU as possible. The initial
50build of an OpenBMC distribution can take hours. Once that first build is done
51though, future builds will use cached data from the first build, speeding the
52process up by orders of magnitude.
53
54So before we do anything else, let's get that first build going.
55
56Follow the direction on the OpenBMC GitHub [page](https://github.com/openbmc/openbmc/blob/master/README.md#2-download-the-source)
57for the Romulus system (steps 2-4).
58
59## Create a New System
60
61While the BitBake operation is going above, let's start creating our new system.
62Similar to previous lessons, we'll be using Romulus as our reference. Our new
63system will be called romulus-prime.
64
65From your openbmc repository you cloned above, the Romulus layer is defined
66within `meta-ibm/meta-romulus/`.  The Romulus layer is defined within the
67`conf` subdirectory. Under `conf` you will see a layout like this:
68
69```
70meta-ibm/meta-romulus/conf/
71├── bblayers.conf.sample
72├── conf-notes.txt
73├── layer.conf
74├── local.conf.sample
75└── machine
76    └── romulus.conf
77```
78
79To create our new romulus-prime system we are going to start out by copying
80our romulus layer.
81```
82cp -R meta-ibm/meta-romulus meta-ibm/meta-romulus-prime
83```
84
85Let's review and modify each file needed in our new layer
86
871. meta-ibm/meta-romulus-prime/conf/bblayers.conf.sample
88
89   This file defines the layers to pull into the meta-romulus-prime
90   distribution. You can see in it a variety of Yocto layers (meta, meta-poky,
91   meta-openembedded/meta-oe, ...). It also has OpenBMC layers like
92   meta-phosphor, meta-openpower, meta-ibm, and meta-ibm/meta-romulus.
93
94   The only change you need in this file is to change the two instances of
95   meta-romulus to meta-romulus-prime. This will ensure your new layer is used
96   when building your new system.
97
982. meta-ibm/meta-romulus-prime/conf/conf-notes.txt
99
100   This file simply states the default target the user will build when working
101   with your new layer. This remains the same as it is common for all OpenBMC
102   systems.
103
1043. meta-ibm/meta-romulus-prime/conf/layer.conf
105
106   The main purpose of this file is to tell BitBake where to look for recipes
107   (\*.bb files). Recipe files end with a `.bb` extension and are what contain
108   all of the packaging logic for the different layers. `.bbappend` files are
109   also recipe files but provide a way to append onto `.bb` files.
110   `.bbappend` files are commonly used to add or remove something from a
111   corresponding `.bb` file in a different layer.
112
113   The only change you need in here is to find/replace the "romulus-layer" to
114   "romulus-prime-layer"
115
1164. meta-ibm/meta-romulus-prime/conf/local.conf.sample
117
118   This file is where all local configuration settings go for your layer. The
119   documentation in it is well done and it's worth a read.
120
121   The only change required in here is to change the `MACHINE` to
122   `romulus-prime`.
123
1245. meta-ibm/meta-romulus-prime/conf/machine/romulus.conf
125
126   This file describes the specifics for your machine. You define the kernel
127   device tree to use, any overrides to specific features you will be pulling
128   in, and other system specific pointers. This file is a good reference for
129   the different things you need to change when creating a new system (kernel
130   device tree, MRW, LED settings, inventory access, ...)
131
132   The first thing you need to do is rename the file to `romulus-prime.conf`.
133
134   **Note** If our new system really was just a variant of Romulus,
135   with the same hardware configuration, then we could have just created a
136   new machine in the Romulus layer. Any customizations for that system
137   could be included in the corresponding .conf file for that new machine. For
138   the purposes of this exercise we are assuming our romulus-prime system has
139   at least a few hardware changes requiring us to create this new layer.
140
141## Build New System
142
143This will not initially compile but it's good to verify a few things from the
144initial setup are done correctly.
145
146Do not start this step until the build we started at the beginning of this
147lesson has completed.
148
1491. Modify the conf for your current build
150
151   Within the shell you did the initial "bitbake" operation you need to reset
152   the conf file for your build. You can manually copy in the new files or just
153   remove it and let BitBake do it for you:
154   ```
155   cd ..
156   rm -r ./build/conf
157   . setup romulus-prime
158   ```
159
160   Run your "bitbake" command.
161
1622. Nothing RPROVIDES 'romulus-prime-config'
163
164   This will be your first error after running "bitbake obmc-phosphor-image"
165   against your new system.
166
167   The openbmc/skeleton repository was used for initial prototyping of OpenBMC.
168   Within this repository is a [configs](https://github.com/openbmc/skeleton/tree/master/configs) directory.
169
170   The majority of this config data is no longer used but until it is all
171   completely removed, you need to provide it.
172
173   Since this repository and file are on there way out, we'll simply do a quick
174   workaround for this issue.
175
176   Create a config files as follows:
177   ```
178   cp meta-ibm/meta-romulus-prime/recipes-phosphor/workbook/romulus-config.bb meta-ibm/meta-romulus-prime/recipes-phosphor/workbook/romulus-prime-config.bb
179
180   vi meta-ibm/meta-romulus-prime/recipes-phosphor/workbook/romulus-prime-config.bb
181
182   SUMMARY = "Romulus board wiring"
183   DESCRIPTION = "Board wiring information for the Romulus OpenPOWER system."
184   PR = "r1"
185
186   inherit config-in-skeleton
187
188   #Use Romulus config
189   do_make_setup() {
190           cp ${S}/Romulus.py \
191                   ${S}/obmc_system_config.py
192           cat <<EOF > ${S}/setup.py
193   from distutils.core import setup
194
195   setup(name='${BPN}',
196       version='${PR}',
197       py_modules=['obmc_system_config'],
198       )
199   EOF
200   }
201
202   ```
203
204   Re-run your "bitbake" command.
205
2063. Fetcher failure for URL: file://romulus.cfg
207
208   This is the config file required by the kernel. It's where you can put some
209   additional kernel config parameters. For our purposes here, just modify
210   romulus-prime to use the romulus.cfg file. We just need to add the `-prime`
211   to the prepend path.
212   ```
213   vi ./meta-ibm/meta-romulus-prime/recipes-kernel/linux/linux-aspeed_%.bbappend
214
215   FILESEXTRAPATHS_prepend_romulus-prime := "${THISDIR}/${PN}:"
216   SRC_URI += "file://romulus.cfg"
217   ```
218
219   Re-run your "bitbake" command.
220
2214. No rule to make target arch/arm/boot/dts/aspeed-bmc-opp-romulus-prime.dtb
222
223   The .dtb file is a device tree blob file. It is generated during the Linux
224   kernel build based on its corresponding .dts file. When you introduce a
225   new OpenBMC system, you need to send these kernel updates upstream. The
226   linked email [thread](https://lists.ozlabs.org/pipermail/openbmc/2018-September/013260.html)
227   is an example of this process. Upstreaming to the kernel is a lesson in
228   itself. For this lesson, we will simply use the Romulus kernel config files.
229   ```
230   vi ./meta-ibm/meta-romulus-prime/conf/machine/romulus-prime.conf
231   # Replace the ${MACHINE} variable in the KERNEL_DEVICETREE
232
233   # Use romulus device tree
234   KERNEL_DEVICETREE = "${KMACHINE}-bmc-opp-romulus.dtb"
235   ```
236
237   Re-run your "bitbake" command.
238
239## Boot New System
240
241And you've finally built your new system's image! There are more
242customizations to be done but let's first verify what you have boots.
243
244Your new image will be in the following location from where you ran your
245"bitbake" command:
246```
247./tmp/deploy/images/romulus-prime/obmc-phosphor-image-romulus-prime.static.mtd
248```
249Copy this image to where you've set up your QEMU session and re-run the
250command to start QEMU (`qemu-system-arm` command from
251[dev-environment.md][32]), giving your new file as input.
252
253Once booted, you should see the following for the login:
254```
255romulus-prime login:
256```
257
258There you go! You've done the basics of creating, booting, and building a new
259system. This is by no means a complete system but you now have the base for
260the customizations you'll need to do for your new system.
261
262## Further Customizations
263
264There are a lot of other areas to customize when creating a new system.
265
266### Kernel changes
267
268This section describes how you can make changes to the kernel to port OpenBMC
269to a new machine.
270The device tree is in https://github.com/openbmc/linux/tree/dev-4.13/arch/arm/boot/dts.
271For examples, see [aspeed-bmc-opp-romulus.dts][1] or a similar machine.
272Complete the following steps to make kernel changes:
273
2741. Add the new machine device tree:
275   * Describe the GPIOs, e.g. LED, FSI, gpio-keys, etc. You should get such
276     info from schematic.
277   * Describe the i2c buses and devices, which usually include various hwmon
278     sensors.
279   * Describe the other devices, e.g. uarts, mac.
280   * Usually the flash layout does not need to change. Just include
281     `openbmc-flash-layout.dtsi`.
2822. Modify Makefile to build the device tree.
2833. Reference to [openbmc kernel doc][31] on submitting patches to mailing list.
284
285Note:
286* In `dev-4.10`, there is common and machine-specific initialization code in
287  `arch/arm/mach-aspeed/aspeed.c` which is used to do common initializations
288  and perform specific settings in each machine.
289  Starting in branch `dev-4.13`, there is no such initialization code. Most of
290  the inits are done with the upstream clock and reset driver.
291* If the machine needs specific settings (e.g. uart routing), please
292  send mail to [the mailing list][2] for discussion.
293
294
295### Workbook
296
297In legacy OpenBMC, there is a "workbook" to describe the machine's services,
298sensors, FRUs, etc.
299This workbook is a python configuration file and it is used by other services
300in [skeleton][3].
301In the latest OpenBMC, the skeleton services are mostly replaced by
302phosphor-xxx services and thus skeleton is deprecated.
303But the workbook is still needed for now to make the build.
304
305[meta-quanta][4] is an example that defines its own config in OpenBMC tree, so
306that it does not rely on skeleton repo, although it is kind of dummy.
307
308Before [e0e69be][26], or before v2.4 tag, OpenPOWER machines use several
309configurations related to GPIO. For example, in [Romulus.py][5], the
310configuration details are as follows:
311
312```python
313GPIO_CONFIG['BMC_POWER_UP'] = \
314        {'gpio_pin': 'D1', 'direction': 'out'}
315GPIO_CONFIG['SYS_PWROK_BUFF'] = \
316        {'gpio_pin': 'D2', 'direction': 'in'}
317
318GPIO_CONFIGS = {
319    'power_config' : {
320        'power_good_in' : 'SYS_PWROK_BUFF',
321        'power_up_outs' : [
322            ('BMC_POWER_UP', True),
323        ],
324        'reset_outs' : [
325        ],
326    },
327}
328```
329The PowerUp and PowerOK GPIOs are needed for the build to power on the chassis
330and check the power state.
331
332After that, the GPIO related configs are removed from the workbook, and
333replaced by `gpio_defs.json`, e.g. [2a80da2][27] introduces the GPIO json
334config for Romulus.
335
336```json
337{
338    "gpio_configs": {
339         "power_config": {
340            "power_good_in": "SYS_PWROK_BUFF",
341            "power_up_outs": [
342                { "name": "SOFTWARE_PGOOD", "polarity": true},
343                { "name": "BMC_POWER_UP", "polarity": true}
344            ],
345            "reset_outs": [
346            ]
347        }
348    },
349
350     "gpio_definitions": [
351        {
352            "name": "SOFTWARE_PGOOD",
353            "pin": "R1",
354            "direction": "out"
355        },
356        {
357            "name": "BMC_POWER_UP",
358            "pin": "D1",
359            "direction": "out"
360        },
361    ...
362}
363```
364
365Each machine shall define the similar json config to describe the GPIO
366configurations.
367
368
369### Hwmon Sensors
370
371Hwmon sensors include sensors on board (e.g. temperature sensors, fans) and
372OCC sensors.
373The config files path and name shall match the devices in device tree.
374
375There is detailed document in openbmc [doc/architecture/sensor-architecture][6].
376
377Here let's take Romulus as an example.
378The config files are in [meta-romulus/recipes-phosphor/sensors][7] which
379includes sensors on board and sensors of OCC, where on board sensors are via
380i2c and occ sensors are via FSI.
381
382* [w83773g@4c.conf][8] defines the `w83773` temperature sensor containing 3
383temperatures:
384   ```
385   LABEL_temp1 = "outlet"
386   ...
387   LABEL_temp2 = "inlet_cpu"
388   ...
389   LABEL_temp3 = "inlet_io"
390   ```
391   This device is defined in its device tree as [w83773g@4c][9].
392   When BMC starts, the udev rule will start `phosphor-hwmon` and it will create
393   temperature sensors on below DBus objects based on its sysfs attributes.
394   ```
395   /xyz/openbmc_project/sensors/temperature/outlet
396   /xyz/openbmc_project/sensors/temperature/inlet_cpu
397   /xyz/openbmc_project/sensors/temperature/inlet_io
398   ```
399* [pwm-tacho-controller@1e786000.conf][10] defines the fans and the config is
400   similar as above, the difference is that it creates `fan_tach` sensors.
401* [occ-hwmon.1.conf][11] defines the occ hwmon sensor for master CPU.
402   This config is a bit different, that it shall tell `phosphor-hwmon` to read
403   the label instead of directly getting the index of the sensor, because CPU
404   cores and DIMMs could be dynamic, e.g. CPU cores could be disabled, DIMMs
405   could be pulled out.
406   ```
407   MODE_temp1 = "label"
408   MODE_temp2 = "label"
409   ...
410   MODE_temp31 = "label"
411   MODE_temp32 = "label"
412   LABEL_temp91 = "p0_core0_temp"
413   LABEL_temp92 = "p0_core1_temp"
414   ...
415   LABEL_temp33 = "dimm6_temp"
416   LABEL_temp34 = "dimm7_temp"
417   LABEL_power2 = "p0_power"
418   ...
419   ```
420   * The `MODE_temp* = "label"` tells that if it sees `tempX`, it shall read
421      the label which is the sensor id.
422   * And `LABEL_temp* = "xxx"` tells the sensor name for the corresponding
423      sensor id.
424   * For example, if `temp1_input` is 37000 and `temp1_label` is 91 in sysfs,
425      `phosphor-hwmon` knows `temp1_input` is for sensor id 91, which is
426      `p0_core0_temp`, so it creates
427      `/xyz/openbmc_project/sensors/temperature/p0_core0_temp` with sensor
428      value 37000.
429   * For Romulus, the power sensors do not need to read label since all powers
430      are available on a system.
431   * For Witherspoon, the power sensors are similar to temperature sensors,
432      that it shall tell hwmon to read the `function_id` instead of directly
433      getting the index of the sensor.
434
435
436### LEDs
437
438Several parts are involved for LED.
439
4401. In kernel dts, LEDs shall be described, e.g. [romulus dts][12] describes
441   3 LEDs, `fault`, `identify` and `power`.
442   ```
443     leds {
444       compatible = "gpio-leds";
445
446       fault {
447         gpios = <&gpio ASPEED_GPIO(N, 2) GPIO_ACTIVE_LOW>;
448       };
449
450       identify {
451         gpios = <&gpio ASPEED_GPIO(N, 4) GPIO_ACTIVE_HIGH>;
452       };
453
454       power {
455         gpios = <&gpio ASPEED_GPIO(R, 5) GPIO_ACTIVE_LOW>;
456       };
457     };
458   ```
4592. In machine layer, LEDs shall be configured via yaml to describe how it
460   functions, e.g. [Romulus led yaml][28]:
461   ```
462   bmc_booted:
463       power:
464           Action: 'Blink'
465           DutyOn: 50
466           Period: 1000
467           Priority: 'On'
468   power_on:
469       power:
470           Action: 'On'
471           DutyOn: 50
472           Period: 0
473           Priority: 'On'
474   ...
475   ```
476   It tells the LED manager to set the `power` LED to blink when BMC is ready
477   and booted, and set it on when host is powered on.
4783. At runtime, LED manager automatically set LEDs on/off/blink based on the
479   above yaml config.
4804. LED can be accessed manually via /xyz/openbmc_project/led/, e.g.
481   * Get identify LED state:
482      ```
483      curl -b cjar -k https://$bmc/xyz/openbmc_project/led/physical/identify
484      ```
485   * Set identify LED to blink:
486      ```
487      curl -b cjar -k -X PUT -H "Content-Type: application/json" -d '{"data": "xyz.openbmc_project.Led.Physical.Action.Blink" }' https://$bmc/xyz/openbmc_project/led/physical/identify/attr/State
488      ```
4895. When an error related to a FRU occurs, an event log is created in logging
490   with a CALLOUT path. [phosphor-fru-fault-monitor][29] monitors the logs:
491   * Assert the related fault LED group when a log with the CALLOUT path is
492      generated;
493   * De-assert the related fault LED group when the log is marked as
494      "Resolved" or deleted.
495
496**Note**: This yaml config can be automatically generated by
497[phosphor-mrw-tools][13] from its MRW, see [Witherspoon example][14].
498
499
500### Inventories and other sensors
501
502Inventories, other sensors (e.g. CPU/DIMM temperature), and FRUs are defined
503in ipmi's yaml config files.
504
505E.g. [meta-romulus/recipes-phosphor/ipmi][15]
506* `romulus-ipmi-inventory-map` defines regular inventories, e.g. CPU, memory,
507   motherboard.
508* `phosphor-ipmi-fru-properties` defines extra properties of the inventories.
509* `phosphor-ipmi-sensor-inventory` defines the sensors from IPMI.
510* `romulus-ipmi-inventory-sel` defines inventories used for IPMI SEL.
511
512For inventory map and fru-properties, they are similar between different
513systems, you can refer to this example and make one for your system.
514
515For ipmi-sensor-inventory, the sensors from IPMI are different between
516systems, so you need to define your own sensors, e.g.
517```
5180x08:
519  sensorType: 0x07
520  path: /org/open_power/control/occ0
521  ...
5220x1e:
523  sensorType: 0x0C
524  path: /system/chassis/motherboard/dimm0
525  ...
5260x22:
527  sensorType: 0x07
528  path: /system/chassis/motherboard/cpu0/core0
529```
530The first value `0x08`, `0x1e` and `0x22` are the sensor id of IPMI, which is
531defined in MRW.
532You should follow the system's MRW to define the above config.
533
534**Note**: The yaml configs can be automatically generated by
535[phosphor-mrw-tools][13] from its MRW, see [Witherspoon example][14].
536
537
538### Fans
539[phosphor-fan-presence][16] manages all the services about fan:
540* `phosphor-fan-presence` checks if a fan is present, creates the fan DBus
541   objects in inventory and update the `Present` property.
542* `phosphor-fan-monitor` checks if a fan is functional, and update the
543   `Functional` property of the fan Dbus object.
544* `phosphor-fan-control` controls the fan speed by setting the fan speed target
545   based on conditions, e.g. temperatures.
546* `phosphor-cooling-type` checks and sets if the system is air-cooled or
547   water-cooled by setting properties of
548   `/xyz/openbmc_project/inventory/system/chassis` object.
549
550All the above services are configurable, e.g. by yaml config.
551So the machine specific configs shall be written when porting OpenBMC to a new
552machine.
553
554Taking Romulus as an example, it is air-cooled and has 3 fans without GPIO
555presence detection.
556
557#### Fan presence
558Romulus has no GPIO detection for fans, so it checks fan tach sensor:
559```
560- name: fan0
561  path: /system/chassis/motherboard/fan0
562  methods:
563    - type: tach
564      sensors:
565        - fan0
566```
567The yaml config tells that
568* It shall create `/system/chassis/motherboard/fan0` object in inventory.
569* It shall check fan0 tach sensor (`/sensors/fan_tach/fan0`) to set `Present`
570   property on the fan0 object.
571
572#### Fan monitor
573Romulus fans use pwm to control the fan speed, where pwm ranges from 0 to 255,
574and the fan speed ranges from 0 to about 7000.
575So it needs a factor and offset to mapping the pwm to fan speed:
576```
577  - inventory: /system/chassis/motherboard/fan0
578    allowed_out_of_range_time: 30
579    deviation: 15
580    num_sensors_nonfunc_for_fan_nonfunc: 1
581    sensors:
582      - name: fan0
583        has_target: true
584        target_interface: xyz.openbmc_project.Control.FanPwm
585        factor: 21
586        offset: 1600
587```
588The yaml config tells that:
5891. It shall use `FanPwm` as target interface of the tach sensor.
5902. It shall calculate the expected fan speed as `target * 21 + 1600`.
5913. The deviation is `15%`, so if the fan speed is out of the expected range
592   for more than 30 seconds, fan0 shall be set as non-functional.
593
594#### Fan control
595The fan control service requires 4 yaml configuration files:
596* `zone-condition` defines the cooling zone conditions. Romulus is always
597   air-cooled, so this config is as simple as defining an `air_cooled_chassis`
598   condition based on the cooling type property.
599   ```
600  - name: air_cooled_chassis
601    type: getProperty
602    properties:
603      - property: WaterCooled
604        interface: xyz.openbmc_project.Inventory.Decorator.CoolingType
605        path: /xyz/openbmc_project/inventory/system/chassis
606        type: bool
607        value: false
608   ```
609* `zone-config` defines the cooling zones. Romulus has only one zone:
610   ```
611  zones:
612    - zone: 0
613      full_speed: 255
614      default_floor: 195
615      increase_delay: 5
616      decrease_interval: 30
617   ```
618   It defines that the zone full speed and default floor speed for the fans,
619   so the fan pwm will be set to 255 if it is in full speed, and set to 195 if
620   fans are in default floor speed.
621* `fan-config` defines which fans are controlled in which zone and which target
622   interface shall be used, e.g. below yaml config defines fan0 shall be
623   controlled in zone0 and it shall use `FanPwm` interface.
624   ```
625  - inventory: /system/chassis/motherboard/fan0
626    cooling_zone: 0
627    sensors:
628      - fan0
629    target_interface: xyz.openbmc_project.Control.FanPwm
630    ...
631   ```
632* `events-config` defines the various events and its handlers, e.g. which fan
633   targets shall be set in which temperature.
634   This config is a bit complicated, the [example event yaml][17] provides
635   documents and examples.
636   Romulus example:
637   ```
638    - name: set_air_cooled_speed_boundaries_based_on_ambient
639      groups:
640          - name: zone0_ambient
641            interface: xyz.openbmc_project.Sensor.Value
642            property:
643                name: Value
644                type: int64_t
645      matches:
646          - name: propertiesChanged
647      actions:
648          - name: set_floor_from_average_sensor_value
649            map:
650                value:
651                    - 27000: 85
652                    - 32000: 112
653                    - 37000: 126
654                    - 40000: 141
655                type: std::map<int64_t, uint64_t>
656          - name: set_ceiling_from_average_sensor_value
657            map:
658                value:
659                    - 25000: 175
660                    - 27000: 255
661                type: std::map<int64_t, uint64_t>
662   ```
663   The above yaml config defines the fan floor and ceiling speed in
664   `zone0_ambient`'s different temperatures. E.g.
665   1. When the temperature is lower than 27 degreesC, the floor speed (pwm)
666      shall be set to 85.
667   2. When the temperature is between 27 and 32 degrees C, the floor speed
668      (pwm) shall be set to 112, etc.
669
670With above configs, phosphor-fan will run the fan presence/monitor/control
671logic as configured specifically for the machine.
672
673**Note**: Romulus fans are simple. For a more complicated example, refer to
674[Witherspoon fan configurations][18]. The following are the additional
675functions of Witherspoon fan configuration:
676
677* It checks GPIO for fan presence.
678* It checks GPIO to determine if the system is air or water cooled.
679* It has more sensors and more events in fan control.
680
681
682### GPIOs
683This section mainly focuses on the GPIOs in device tree that shall be
684monitored.
685E.g.:
686* A GPIO may represent a signal of host checkstop.
687* A GPIO may represent a button press.
688* A GPIO may represent if a device is attached or not.
689
690They are categorized as `phosphor-gpio-presence` for checking presences of a
691device, and `phosphor-gpio-monitor` for monitoring a GPIO.
692
693#### GPIOs in device tree
694All the GPIOs to be monitored shall be described in the device tree.
695E.g.
696```
697  gpio-keys {
698    compatible = "gpio-keys";
699    checkstop {
700      label = "checkstop";
701      gpios = <&gpio ASPEED_GPIO(J, 2) GPIO_ACTIVE_LOW>;
702      linux,code = <ASPEED_GPIO(J, 2)>;
703    };
704    id-button {
705      label = "id-button";
706      gpios = <&gpio ASPEED_GPIO(Q, 7) GPIO_ACTIVE_LOW>;
707      linux,code = <ASPEED_GPIO(Q, 7)>;
708    };
709  };
710```
711The following code describes two GPIO keys, one for `checkstop` and the other
712for `id-button`, where the key code is calculated from [aspeed-gpio.h][24]:
713```
714#define ASPEED_GPIO_PORT_A 0
715#define ASPEED_GPIO_PORT_B 1
716...
717#define ASPEED_GPIO_PORT_Y 24
718#define ASPEED_GPIO_PORT_Z 25
719#define ASPEED_GPIO_PORT_AA 26
720...
721
722#define ASPEED_GPIO(port, offset) \
723  ((ASPEED_GPIO_PORT_##port * 8) + offset)
724```
725
726#### GPIO Presence
727Witherspoon and Zaius have examples for gpio presence.
728
729* [Witherspoon][19]:
730   ```
731   INVENTORY=/system/chassis/motherboard/powersupply0
732   DEVPATH=/dev/input/by-path/platform-gpio-keys-event
733   KEY=104
734   NAME=powersupply0
735   DRIVERS=/sys/bus/i2c/drivers/ibm-cffps,3-0069
736   ```
737   It checks GPIO key 104 for `powersupply0`'s presence, creates the inventory
738   object and bind or unbind the driver.
739* [Zaius][20]:
740   ```
741   INVENTORY=/system/chassis/pcie_card_e2b
742   DEVPATH=/dev/input/by-path/platform-gpio-keys-event
743   KEY=39
744   NAME=pcie_card_e2b
745   ```
746   It checks GPIO key 39 for `pcie_card_e2b`'s presence, and creates the
747   inventory object.
748
749#### GPIO monitor
750Typical usage of GPIO monitor is to monitor the checkstop event from the host,
751or button presses.
752
753* [checkstop monitor][21] is a common service for OpenPOWER machines.
754   ```
755   DEVPATH=/dev/input/by-path/platform-gpio-keys-event
756   KEY=74
757   POLARITY=1
758   TARGET=obmc-host-crash@0.target
759   ```
760   By default it monitors GPIO key 74, and if it is triggered, it tells
761   systemd to start `obmc-host-crash@0.target`.
762   For systems using a different GPIO pin for checkstop, it simply overrides
763   the default one by specifying its own config file in meta-machine layer.
764   E.g. [Zaius's checkstop config][22].
765   **Note**: when the key is pressed, `phosphor-gpio-monitor` starts the target
766   unit and exits.
767* [id-button monitor][23] is an example service on Romulus to monitor ID
768   button press.
769   ```
770   DEVPATH=/dev/input/by-path/platform-gpio-keys-event
771   KEY=135
772   POLARITY=1
773   TARGET=id-button-pressed.service
774   EXTRA_ARGS=--continue
775   ```
776   It monitors GPIO key 135 for the button press and starts
777   `id-button-pressed.service`, that handles the event by setting the identify
778   LED group's `Assert` property.
779   **Note**: It has an extra argument, `--continue`, that tells
780   `phosphor-gpio-monitor` to not exit and continue running when the key is
781   pressed.
782
783[1]: https://github.com/openbmc/linux/blob/dev-4.13/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts
784[2]: https://lists.ozlabs.org/listinfo/openbmc
785[3]: https://github.com/openbmc/skeleton
786[4]: https://github.com/openbmc/openbmc/tree/master/meta-quanta/meta-q71l/recipes-phosphor/workbook
787[5]: https://github.com/openbmc/skeleton/blob/master/configs/Romulus.py
788[6]: https://github.com/openbmc/docs/blob/master/architecture/sensor-architecture.md
789[7]: https://github.com/openbmc/openbmc/tree/master/meta-ibm/meta-romulus/recipes-phosphor/sensors
790[8]: https://github.com/openbmc/openbmc/blob/298c4328fd20fcd7645da1565c143b1b668ef541/meta-ibm/meta-romulus/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c%401e78a000/i2c-bus%40440/w83773g%404c.conf
791[9]: https://github.com/openbmc/linux/blob/aca92be80c008bceeb6fb62fd1d450b5be5d0a4f/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts#L208
792[10]: https://github.com/openbmc/openbmc/blob/298c4328fd20fcd7645da1565c143b1b668ef541/meta-ibm/meta-romulus/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/pwm-tacho-controller%401e786000.conf
793[11]: https://github.com/openbmc/openbmc/blob/298c4328fd20fcd7645da1565c143b1b668ef541/meta-ibm/meta-romulus/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/devices/platform/gpio-fsi/fsi0/slave%4000--00/00--00--00--06/sbefifo1-dev0/occ-hwmon.1.conf
794[12]: https://github.com/openbmc/linux/blob/aca92be80c008bceeb6fb62fd1d450b5be5d0a4f/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts#L42
795[13]: https://github.com/openbmc/phosphor-mrw-tools
796[14]: https://github.com/openbmc/openbmc/blob/764b88f4056cc98082e233216704e94613499e64/meta-ibm/meta-witherspoon/conf/distro/openbmc-witherspoon.conf#L4
797[15]: https://github.com/openbmc/openbmc/tree/master/meta-ibm/meta-romulus/recipes-phosphor/ipmi
798[16]: https://github.com/openbmc/phosphor-fan-presence
799[17]: https://github.com/openbmc/phosphor-fan-presence/blob/master/control/example/events.yaml
800[18]: https://github.com/openbmc/openbmc/tree/master/meta-ibm/meta-witherspoon/recipes-phosphor/fans
801[19]: https://github.com/openbmc/openbmc/blob/master/meta-ibm/meta-witherspoon/recipes-phosphor/gpio/phosphor-gpio-monitor/obmc/gpio/phosphor-power-supply-0.conf
802[20]: https://github.com/openbmc/openbmc/blob/master/meta-ingrasys/meta-zaius/recipes-phosphor/gpio/phosphor-gpio-monitor/obmc/gpio/phosphor-pcie-card-e2b.conf
803[21]: https://github.com/openbmc/openbmc/blob/master/meta-openpower/recipes-phosphor/host/checkstop-monitor.bb
804[22]: https://github.com/openbmc/openbmc/blob/master/meta-ingrasys/meta-zaius/recipes-phosphor/host/checkstop-monitor/obmc/gpio/checkstop
805[23]: https://github.com/openbmc/openbmc/tree/master/meta-ibm/meta-romulus/recipes-phosphor/gpio
806[24]: https://github.com/openbmc/linux/blob/dev-4.13/include/dt-bindings/gpio/aspeed-gpio.h
807[25]: https://github.com/openbmc/docs/blob/master/development/add-new-system.md
808[26]: https://github.com/openbmc/openbmc/commit/e0e69beab7c268e4ad98972016c78b0d7d5769ac
809[27]: https://github.com/openbmc/openbmc/commit/2a80da2262bf13aa1ddb589cf3f2b672d26b0975
810[28]: https://github.com/openbmc/openbmc/blob/3cce45a96f0416b4c3d8f2b698cb830662a29227/meta-ibm/meta-romulus/recipes-phosphor/leds/romulus-led-manager-config/led.yaml
811[29]: https://github.com/openbmc/phosphor-led-manager/tree/master/fault-monitor
812[30]: https://github.com/openbmc/docs/blob/master/development/dev-environment.md
813[31]: https://github.com/openbmc/docs/blob/master/kernel-development.md
814[32]: https://github.com/openbmc/docs/blob/master/development/dev-environment.md
815