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