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