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``` 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``` 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 ``` 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 ``` 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 ``` 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 ``` 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``` 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``` 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 281https://github.com/openbmc/linux/tree/dev-4.13/arch/arm/boot/dts. For examples, 282see [aspeed-bmc-opp-romulus.dts][1] or a similar machine. Complete the following 283steps 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 LABEL_temp1 = "outlet" 392 ... 393 LABEL_temp2 = "inlet_cpu" 394 ... 395 LABEL_temp3 = "inlet_io" 396 ``` 397 This device is defined in its device tree as [w83773g@4c][9]. When BMC starts, 398 the udev rule will start `phosphor-hwmon` and it will create temperature 399 sensors on below DBus objects based on its sysfs attributes. 400 ``` 401 /xyz/openbmc_project/sensors/temperature/outlet 402 /xyz/openbmc_project/sensors/temperature/inlet_cpu 403 /xyz/openbmc_project/sensors/temperature/inlet_io 404 ``` 405- [pwm-tacho-controller@1e786000.conf][10] defines the fans and the config is 406 similar as above, the difference is that it creates `fan_tach` sensors. 407- [occ-hwmon.1.conf][11] defines the occ hwmon sensor for master CPU. This 408 config is a bit different, that it shall tell `phosphor-hwmon` to read the 409 label instead of directly getting the index of the sensor, because CPU cores 410 and DIMMs could be dynamic, e.g. CPU cores could be disabled, DIMMs could be 411 pulled out. 412 ``` 413 MODE_temp1 = "label" 414 MODE_temp2 = "label" 415 ... 416 MODE_temp31 = "label" 417 MODE_temp32 = "label" 418 LABEL_temp91 = "p0_core0_temp" 419 LABEL_temp92 = "p0_core1_temp" 420 ... 421 LABEL_temp33 = "dimm6_temp" 422 LABEL_temp34 = "dimm7_temp" 423 LABEL_power2 = "p0_power" 424 ... 425 ``` 426 - The `MODE_temp* = "label"` tells that if it sees `tempX`, it shall read the 427 label which is the sensor id. 428 - And `LABEL_temp* = "xxx"` tells the sensor name for the corresponding sensor 429 id. 430 - For example, if `temp1_input` is 37000 and `temp1_label` is 91 in sysfs, 431 `phosphor-hwmon` knows `temp1_input` is for sensor id 91, which is 432 `p0_core0_temp`, so it creates 433 `/xyz/openbmc_project/sensors/temperature/p0_core0_temp` with sensor 434 value 37000. 435 - For Romulus, the power sensors do not need to read label since all powers 436 are available on a system. 437 - For Witherspoon, the power sensors are similar to temperature sensors, that 438 it shall tell hwmon to read the `function_id` instead of directly getting 439 the index of the sensor. 440 441### LEDs 442 443Several parts are involved for LED. 444 4451. In kernel dts, LEDs shall be described, e.g. [romulus dts][12] describes 3 446 LEDs, `fault`, `identify` and `power`. 447 448 ``` 449 leds { 450 compatible = "gpio-leds"; 451 452 fault { 453 gpios = <&gpio ASPEED_GPIO(N, 2) GPIO_ACTIVE_LOW>; 454 }; 455 456 identify { 457 gpios = <&gpio ASPEED_GPIO(N, 4) GPIO_ACTIVE_HIGH>; 458 }; 459 460 power { 461 gpios = <&gpio ASPEED_GPIO(R, 5) GPIO_ACTIVE_LOW>; 462 }; 463 }; 464 ``` 465 4662. In machine layer, LEDs shall be configured via yaml to describe how it 467 functions, e.g. [Romulus led yaml][28]: 468 ``` 469 bmc_booted: 470 power: 471 Action: 'Blink' 472 DutyOn: 50 473 Period: 1000 474 Priority: 'On' 475 power_on: 476 power: 477 Action: 'On' 478 DutyOn: 50 479 Period: 0 480 Priority: 'On' 481 ... 482 ``` 483 It tells the LED manager to set the `power` LED to blink when BMC is ready 484 and booted, and set it on when host is powered on. 4853. At runtime, LED manager automatically set LEDs on/off/blink based on the 486 above yaml config. 4874. LED can be accessed manually via /xyz/openbmc_project/led/, e.g. 488 - Get identify LED state: 489 ``` 490 curl -b cjar -k https://$bmc/xyz/openbmc_project/led/physical/identify 491 ``` 492 - Set identify LED to blink: 493 ``` 494 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 495 ``` 4965. When an error related to a FRU occurs, an event log is created in logging 497 with a CALLOUT path. [phosphor-fru-fault-monitor][29] monitors the logs: 498 - Assert the related fault LED group when a log with the CALLOUT path is 499 generated; 500 - De-assert the related fault LED group when the log is marked as "Resolved" 501 or deleted. 502 503**Note**: This yaml config can be automatically generated by 504[phosphor-mrw-tools][13] from its MRW, see [Witherspoon example][14]. 505 506### Inventories and other sensors 507 508Inventories, other sensors (e.g. CPU/DIMM temperature), and FRUs are defined in 509ipmi's yaml config files. 510 511E.g. [meta-romulus/recipes-phosphor/ipmi][15] 512 513- `romulus-ipmi-inventory-map` defines regular inventories, e.g. CPU, memory, 514 motherboard. 515- `phosphor-ipmi-fru-properties` defines extra properties of the inventories. 516- `phosphor-ipmi-sensor-inventory` defines the sensors from IPMI. 517- `romulus-ipmi-inventory-sel` defines inventories used for IPMI SEL. 518 519For inventory map and fru-properties, they are similar between different 520systems, you can refer to this example and make one for your system. 521 522For ipmi-sensor-inventory, the sensors from IPMI are different between systems, 523so you need to define your own sensors, e.g. 524 525``` 5260x08: 527 sensorType: 0x07 528 path: /org/open_power/control/occ0 529 ... 5300x1e: 531 sensorType: 0x0C 532 path: /system/chassis/motherboard/dimm0 533 ... 5340x22: 535 sensorType: 0x07 536 path: /system/chassis/motherboard/cpu0/core0 537``` 538 539The first value `0x08`, `0x1e` and `0x22` are the sensor id of IPMI, which is 540defined in MRW. You should follow the system's MRW to define the above config. 541 542**Note**: The yaml configs can be automatically generated by 543[phosphor-mrw-tools][13] from its MRW, see [Witherspoon example][14]. 544 545### Fans 546 547[phosphor-fan-presence][16] manages all the services about fan: 548 549- `phosphor-fan-presence` checks if a fan is present, creates the fan DBus 550 objects in inventory and update the `Present` property. 551- `phosphor-fan-monitor` checks if a fan is functional, and update the 552 `Functional` property of the fan Dbus object. 553- `phosphor-fan-control` controls the fan speed by setting the fan speed target 554 based on conditions, e.g. temperatures. 555- `phosphor-cooling-type` checks and sets if the system is air-cooled or 556 water-cooled by setting properties of 557 `/xyz/openbmc_project/inventory/system/chassis` object. 558 559All the above services are configurable, e.g. by yaml config. So the machine 560specific configs shall be written when porting OpenBMC to a new machine. 561 562Taking Romulus as an example, it is air-cooled and has 3 fans without GPIO 563presence detection. 564 565#### Fan presence 566 567Romulus has no GPIO detection for fans, so it checks fan tach sensor: 568 569``` 570- name: fan0 571 path: /system/chassis/motherboard/fan0 572 methods: 573 - type: tach 574 sensors: 575 - fan0 576``` 577 578The yaml config tells that 579 580- It shall create `/system/chassis/motherboard/fan0` object in inventory. 581- It shall check fan0 tach sensor (`/sensors/fan_tach/fan0`) to set `Present` 582 property on the fan0 object. 583 584#### Fan monitor 585 586Romulus fans use pwm to control the fan speed, where pwm ranges from 0 to 255, 587and the fan speed ranges from 0 to about 7000. So it needs a factor and offset 588to mapping the pwm to fan speed: 589 590``` 591 - inventory: /system/chassis/motherboard/fan0 592 allowed_out_of_range_time: 30 593 deviation: 15 594 num_sensors_nonfunc_for_fan_nonfunc: 1 595 sensors: 596 - name: fan0 597 has_target: true 598 target_interface: xyz.openbmc_project.Control.FanPwm 599 factor: 21 600 offset: 1600 601``` 602 603The yaml config tells that: 604 6051. It shall use `FanPwm` as target interface of the tach sensor. 6062. It shall calculate the expected fan speed as `target * 21 + 1600`. 6073. The deviation is `15%`, so if the fan speed is out of the expected range for 608 more than 30 seconds, fan0 shall be set as non-functional. 609 610#### Fan control 611 612The fan control service requires 4 yaml configuration files: 613 614- `zone-condition` defines the cooling zone conditions. Romulus is always 615 air-cooled, so this config is as simple as defining an `air_cooled_chassis` 616 condition based on the cooling type property. 617 ``` 618 - name: air_cooled_chassis 619 type: getProperty 620 properties: 621 - property: WaterCooled 622 interface: xyz.openbmc_project.Inventory.Decorator.CoolingType 623 path: /xyz/openbmc_project/inventory/system/chassis 624 type: bool 625 value: false 626 ``` 627- `zone-config` defines the cooling zones. Romulus has only one zone: 628 ``` 629 zones: 630 - zone: 0 631 full_speed: 255 632 default_floor: 195 633 increase_delay: 5 634 decrease_interval: 30 635 ``` 636 It defines that the zone full speed and default floor speed for the fans, so 637 the fan pwm will be set to 255 if it is in full speed, and set to 195 if fans 638 are in default floor speed. 639- `fan-config` defines which fans are controlled in which zone and which target 640 interface shall be used, e.g. below yaml config defines fan0 shall be 641 controlled in zone0 and it shall use `FanPwm` interface. 642 ``` 643 - inventory: /system/chassis/motherboard/fan0 644 cooling_zone: 0 645 sensors: 646 - fan0 647 target_interface: xyz.openbmc_project.Control.FanPwm 648 ... 649 ``` 650- `events-config` defines the various events and its handlers, e.g. which fan 651 targets shall be set in which temperature. This config is a bit complicated, 652 the [example event yaml][17] provides documents and examples. Romulus example: 653 ``` 654 - name: set_air_cooled_speed_boundaries_based_on_ambient 655 groups: 656 - name: zone0_ambient 657 interface: xyz.openbmc_project.Sensor.Value 658 property: 659 name: Value 660 type: int64_t 661 matches: 662 - name: propertiesChanged 663 actions: 664 - name: set_floor_from_average_sensor_value 665 map: 666 value: 667 - 27000: 85 668 - 32000: 112 669 - 37000: 126 670 - 40000: 141 671 type: std::map<int64_t, uint64_t> 672 - name: set_ceiling_from_average_sensor_value 673 map: 674 value: 675 - 25000: 175 676 - 27000: 255 677 type: std::map<int64_t, uint64_t> 678 ``` 679 The above yaml config defines the fan floor and ceiling speed in 680 `zone0_ambient`'s different temperatures. E.g. 681 1. When the temperature is lower than 27 degreesC, the floor speed (pwm) 682 shall be set to 85. 683 2. When the temperature is between 27 and 32 degrees C, the floor speed (pwm) 684 shall be set to 112, etc. 685 686With above configs, phosphor-fan will run the fan presence/monitor/control logic 687as configured specifically for the machine. 688 689**Note**: Romulus fans are simple. For a more complicated example, refer to 690[Witherspoon fan configurations][18]. The following are the additional functions 691of Witherspoon fan configuration: 692 693- It checks GPIO for fan presence. 694- It checks GPIO to determine if the system is air or water cooled. 695- It has more sensors and more events in fan control. 696 697### GPIOs 698 699This section mainly focuses on the GPIOs in device tree that shall be monitored. 700E.g.: 701 702- A GPIO may represent a signal of host checkstop. 703- A GPIO may represent a button press. 704- A GPIO may represent if a device is attached or not. 705 706They are categorized as `phosphor-gpio-presence` for checking presences of a 707device, and `phosphor-gpio-monitor` for monitoring a GPIO. 708 709#### GPIOs in device tree 710 711All the GPIOs to be monitored shall be described in the device tree. E.g. 712 713``` 714 gpio-keys { 715 compatible = "gpio-keys"; 716 checkstop { 717 label = "checkstop"; 718 gpios = <&gpio ASPEED_GPIO(J, 2) GPIO_ACTIVE_LOW>; 719 linux,code = <ASPEED_GPIO(J, 2)>; 720 }; 721 id-button { 722 label = "id-button"; 723 gpios = <&gpio ASPEED_GPIO(Q, 7) GPIO_ACTIVE_LOW>; 724 linux,code = <ASPEED_GPIO(Q, 7)>; 725 }; 726 }; 727``` 728 729The following code describes two GPIO keys, one for `checkstop` and the other 730for `id-button`, where the key code is calculated from [aspeed-gpio.h][24]: 731 732``` 733#define ASPEED_GPIO_PORT_A 0 734#define ASPEED_GPIO_PORT_B 1 735... 736#define ASPEED_GPIO_PORT_Y 24 737#define ASPEED_GPIO_PORT_Z 25 738#define ASPEED_GPIO_PORT_AA 26 739... 740 741#define ASPEED_GPIO(port, offset) \ 742 ((ASPEED_GPIO_PORT_##port * 8) + offset) 743``` 744 745#### GPIO Presence 746 747Witherspoon and Zaius have examples for gpio presence. 748 749- [Witherspoon][19]: 750 ``` 751 INVENTORY=/system/chassis/motherboard/powersupply0 752 DEVPATH=/dev/input/by-path/platform-gpio-keys-event 753 KEY=104 754 NAME=powersupply0 755 DRIVERS=/sys/bus/i2c/drivers/ibm-cffps,3-0069 756 ``` 757 It checks GPIO key 104 for `powersupply0`'s presence, creates the inventory 758 object and bind or unbind the driver. 759- [Zaius][20]: 760 ``` 761 INVENTORY=/system/chassis/pcie_card_e2b 762 DEVPATH=/dev/input/by-path/platform-gpio-keys-event 763 KEY=39 764 NAME=pcie_card_e2b 765 ``` 766 It checks GPIO key 39 for `pcie_card_e2b`'s presence, and creates the 767 inventory object. 768 769#### GPIO monitor 770 771Typical usage of GPIO monitor is to monitor the checkstop event from the host, 772or button presses. 773 774- [checkstop monitor][21] is a common service for OpenPOWER machines. 775 ``` 776 DEVPATH=/dev/input/by-path/platform-gpio-keys-event 777 KEY=74 778 POLARITY=1 779 TARGET=obmc-host-crash@0.target 780 ``` 781 By default it monitors GPIO key 74, and if it is triggered, it tells systemd 782 to start `obmc-host-crash@0.target`. For systems using a different GPIO pin 783 for checkstop, it simply overrides the default one by specifying its own 784 config file in meta-machine layer. E.g. [Zaius's checkstop config][22]. 785 **Note**: when the key is pressed, `phosphor-gpio-monitor` starts the target 786 unit and exits. 787- [id-button monitor][23] is an example service on Romulus to monitor ID button 788 press. 789 ``` 790 DEVPATH=/dev/input/by-path/platform-gpio-keys-event 791 KEY=135 792 POLARITY=1 793 TARGET=id-button-pressed.service 794 EXTRA_ARGS=--continue 795 ``` 796 It monitors GPIO key 135 for the button press and starts 797 `id-button-pressed.service`, that handles the event by setting the identify 798 LED group's `Assert` property. **Note**: It has an extra argument, 799 `--continue`, that tells `phosphor-gpio-monitor` to not exit and continue 800 running when the key is pressed. 801 802[1]: 803 https://github.com/openbmc/linux/blob/dev-4.13/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts 804[2]: https://lists.ozlabs.org/listinfo/openbmc 805[3]: https://github.com/openbmc/skeleton 806[4]: 807 https://github.com/openbmc/openbmc/tree/master/meta-quanta/meta-q71l/recipes-phosphor/workbook 808[5]: https://github.com/openbmc/skeleton/blob/master/configs/Romulus.py 809[6]: 810 https://github.com/openbmc/docs/blob/master/architecture/sensor-architecture.md 811[7]: 812 https://github.com/openbmc/openbmc/tree/master/meta-ibm/meta-romulus/recipes-phosphor/sensors 813[8]: 814 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 815[9]: 816 https://github.com/openbmc/linux/blob/aca92be80c008bceeb6fb62fd1d450b5be5d0a4f/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts#L208 817[10]: 818 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 819[11]: 820 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 821[12]: 822 https://github.com/openbmc/linux/blob/aca92be80c008bceeb6fb62fd1d450b5be5d0a4f/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts#L42 823[13]: https://github.com/openbmc/phosphor-mrw-tools 824[14]: 825 https://github.com/openbmc/openbmc/blob/764b88f4056cc98082e233216704e94613499e64/meta-ibm/meta-witherspoon/conf/distro/openbmc-witherspoon.conf#L4 826[15]: 827 https://github.com/openbmc/openbmc/tree/master/meta-ibm/meta-romulus/recipes-phosphor/ipmi 828[16]: https://github.com/openbmc/phosphor-fan-presence 829[17]: 830 https://github.com/openbmc/phosphor-fan-presence/blob/master/control/example/events.yaml 831[18]: 832 https://github.com/openbmc/openbmc/tree/master/meta-ibm/meta-witherspoon/recipes-phosphor/fans 833[19]: 834 https://github.com/openbmc/openbmc/blob/master/meta-ibm/meta-witherspoon/recipes-phosphor/gpio/phosphor-gpio-monitor/obmc/gpio/phosphor-power-supply-0.conf 835[20]: 836 https://github.com/openbmc/openbmc/blob/master/meta-ingrasys/meta-zaius/recipes-phosphor/gpio/phosphor-gpio-monitor/obmc/gpio/phosphor-pcie-card-e2b.conf 837[21]: 838 https://github.com/openbmc/openbmc/blob/master/meta-openpower/recipes-phosphor/host/checkstop-monitor.bb 839[22]: 840 https://github.com/openbmc/openbmc/blob/master/meta-ingrasys/meta-zaius/recipes-phosphor/host/checkstop-monitor/obmc/gpio/checkstop 841[23]: 842 https://github.com/openbmc/openbmc/tree/master/meta-ibm/meta-romulus/recipes-phosphor/gpio 843[24]: 844 https://github.com/openbmc/linux/blob/dev-4.13/include/dt-bindings/gpio/aspeed-gpio.h 845[25]: https://github.com/openbmc/docs/blob/master/development/add-new-system.md 846[26]: 847 https://github.com/openbmc/openbmc/commit/e0e69beab7c268e4ad98972016c78b0d7d5769ac 848[27]: 849 https://github.com/openbmc/openbmc/commit/2a80da2262bf13aa1ddb589cf3f2b672d26b0975 850[28]: 851 https://github.com/openbmc/openbmc/blob/3cce45a96f0416b4c3d8f2b698cb830662a29227/meta-ibm/meta-romulus/recipes-phosphor/leds/romulus-led-manager-config/led.yaml 852[29]: https://github.com/openbmc/phosphor-led-manager/tree/master/fault-monitor 853[30]: https://github.com/openbmc/docs/blob/master/development/dev-environment.md 854[31]: https://github.com/openbmc/docs/blob/master/kernel-development.md 855[32]: https://github.com/openbmc/docs/blob/master/development/dev-environment.md 856