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