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