summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLei YU <mine260309@gmail.com>2019-01-24 17:35:52 +0800
committerGunnar Mills <gmills@us.ibm.com>2019-03-20 16:29:20 +0000
commitace9cd140d93e92c82b9bd705efea599cc5118e6 (patch)
treea1aa2fff34d9a0af48e8e65ecbc477ddd0531cd0
parent458e3d98ca06306d60b53f2315d63778b4d4bf88 (diff)
downloadopenbmc-docs-ace9cd140d93e92c82b9bd705efea599cc5118e6.tar.gz
openbmc-docs-ace9cd140d93e92c82b9bd705efea599cc5118e6.zip
add-new-system: Add detailed configurations
Add detailed description about configurations for various components (e.g. sensors, LEDs, GPIOs, etc) with examples. Change-Id: Id606e4bac00ddb8fd8773beffb30296a910be8c0 Signed-off-by: Lei YU <mine260309@gmail.com>
-rw-r--r--development/add-new-system.md558
1 files changed, 551 insertions, 7 deletions
diff --git a/development/add-new-system.md b/development/add-new-system.md
index f46bbc1..1742fc1 100644
--- a/development/add-new-system.md
+++ b/development/add-new-system.md
@@ -4,7 +4,7 @@
**Audience:** Programmer familiar with OpenBMC
-**Prerequisites:** Completed Development Environment Setup [Document][1]
+**Prerequisites:** Completed Development Environment Setup [Document][32]
## Overview
@@ -14,6 +14,7 @@ This document will describe the following:
* Creating a new system layer
* Populating this new layer
* Building the new system and testing in QEMU
+* Adding configs for sensors, LEDs, inventories, etc.
## Background
@@ -242,7 +243,7 @@ Your new image will be in the following location from where you ran your
```
Copy this image to where you've set up your QEMU session and re-run the
command to start QEMU (`qemu-system-arm` command from
-[dev-environment.md][1]), giving your new file as input.
+[dev-environment.md][32]), giving your new file as input.
Once booted, you should see the following for the login:
```
@@ -256,10 +257,553 @@ the customizations you'll need to do for your new system.
## Further Customizations
There are a lot of other areas to customize when creating a new system.
-We'll dig into more detail with these (IPMI, HWMON, LED) in future
-development guides.
-Although not in the same format as these guides, [Porting_Guide](https://github.com/mine260309/openbmc-intro/blob/master/Porting_Guide.md)
-provides a lot of very useful information as well on adding a new system.
+### Kernel changes
+
+This section describes how you can make changes to the kernel to port OpenBMC
+to a new machine.
+The device tree is in https://github.com/openbmc/linux/tree/dev-4.13/arch/arm/boot/dts.
+For examples, see [aspeed-bmc-opp-romulus.dts][1] or a similar machine.
+Complete the following steps to make kernel changes:
+
+1. Add the new machine device tree:
+ * Describe the GPIOs, e.g. LED, FSI, gpio-keys, etc. You should get such
+ info from schematic.
+ * Describe the i2c buses and devices, which usually include various hwmon
+ sensors.
+ * Describe the other devices, e.g. uarts, mac.
+ * Usually the flash layout does not need to change. Just include
+ `openbmc-flash-layout.dtsi`.
+2. Modify Makefile to build the device tree.
+3. Reference to [openbmc kernel doc][31] on submitting patches to mailing list.
+
+Note:
+* In `dev-4.10`, there is common and machine-specific initialization code in
+ `arch/arm/mach-aspeed/aspeed.c` which is used to do common initializations
+ and perform specific settings in each machine.
+ Starting in branch `dev-4.13`, there is no such initialization code. Most of
+ the inits are done with the upstream clock and reset driver.
+* If the machine needs specific settings (e.g. uart routing), please
+ send mail to [the mailing list][2] for discussion.
+
+
+### Workbook
+
+In legacy OpenBMC, there is a "workbook" to describe the machine's services,
+sensors, FRUs, etc.
+This workbook is a python configuration file and it is used by other services
+in [skeleton][3].
+In the latest OpenBMC, the skeleton services are mostly replaced by
+phosphor-xxx services and thus skeleton is deprecated.
+But the workbook is still needed for now to make the build.
+
+[meta-quanta][4] is an example that defines its own config in OpenBMC tree, so
+that it does not rely on skeleton repo, although it is kind of dummy.
+
+Before [e0e69be][26], or before v2.4 tag, OpenPOWER machines use several
+configurations related to GPIO. For example, in [Romulus.py][5], the
+configuration details are as follows:
+
+```python
+GPIO_CONFIG['BMC_POWER_UP'] = \
+ {'gpio_pin': 'D1', 'direction': 'out'}
+GPIO_CONFIG['SYS_PWROK_BUFF'] = \
+ {'gpio_pin': 'D2', 'direction': 'in'}
+
+GPIO_CONFIGS = {
+ 'power_config' : {
+ 'power_good_in' : 'SYS_PWROK_BUFF',
+ 'power_up_outs' : [
+ ('BMC_POWER_UP', True),
+ ],
+ 'reset_outs' : [
+ ],
+ },
+}
+```
+The PowerUp and PowerOK GPIOs are needed for the build to power on the chassis
+and check the power state.
+
+After that, the GPIO related configs are removed from the workbook, and
+replaced by `gpio_defs.json`, e.g. [2a80da2][27] introduces the GPIO json
+config for Romulus.
+
+```json
+{
+ "gpio_configs": {
+ "power_config": {
+ "power_good_in": "SYS_PWROK_BUFF",
+ "power_up_outs": [
+ { "name": "SOFTWARE_PGOOD", "polarity": true},
+ { "name": "BMC_POWER_UP", "polarity": true}
+ ],
+ "reset_outs": [
+ ]
+ }
+ },
+
+ "gpio_definitions": [
+ {
+ "name": "SOFTWARE_PGOOD",
+ "pin": "R1",
+ "direction": "out"
+ },
+ {
+ "name": "BMC_POWER_UP",
+ "pin": "D1",
+ "direction": "out"
+ },
+ ...
+}
+```
+
+Each machine shall define the similar json config to describe the GPIO
+configurations.
+
+
+### Hwmon Sensors
+
+Hwmon sensors include sensors on board (e.g. temperature sensors, fans) and
+OCC sensors.
+The config files path and name shall match the devices in device tree.
+
+There is detailed document in openbmc [doc/sensor-architecture][6].
+
+Here let's take Romulus as an example.
+The config files are in [meta-romulus/recipes-phosphor/sensors][7] which
+includes sensors on board and sensors of OCC, where on board sensors are via
+i2c and occ sensors are via FSI.
+
+* [w83773g@4c.conf][8] defines the `w83773` temperature sensor containing 3
+temperatures:
+ ```
+ LABEL_temp1 = "outlet"
+ ...
+ LABEL_temp2 = "inlet_cpu"
+ ...
+ LABEL_temp3 = "inlet_io"
+ ```
+ This device is defined in its device tree as [w83773g@4c][9].
+ When BMC starts, the udev rule will start `phosphor-hwmon` and it will create
+ temperature sensors on below DBus objects based on its sysfs attributes.
+ ```
+ /xyz/openbmc_project/sensors/temperature/outlet
+ /xyz/openbmc_project/sensors/temperature/inlet_cpu
+ /xyz/openbmc_project/sensors/temperature/inlet_io
+ ```
+* [pwm-tacho-controller@1e786000.conf][10] defines the fans and the config is
+ similar as above, the difference is that it creates `fan_tach` sensors.
+* [occ-hwmon.1.conf][11] defines the occ hwmon sensor for master CPU.
+ This config is a bit different, that it shall tell `phosphor-hwmon` to read
+ the label instead of directly getting the index of the sensor, because CPU
+ cores and DIMMs could be dynamic, e.g. CPU cores could be disabled, DIMMs
+ could be pulled out.
+ ```
+ MODE_temp1 = "label"
+ MODE_temp2 = "label"
+ ...
+ MODE_temp31 = "label"
+ MODE_temp32 = "label"
+ LABEL_temp91 = "p0_core0_temp"
+ LABEL_temp92 = "p0_core1_temp"
+ ...
+ LABEL_temp33 = "dimm6_temp"
+ LABEL_temp34 = "dimm7_temp"
+ LABEL_power2 = "p0_power"
+ ...
+ ```
+ * The `MODE_temp* = "label"` tells that if it sees `tempX`, it shall read
+ the label which is the sensor id.
+ * And `LABEL_temp* = "xxx"` tells the sensor name for the corresponding
+ sensor id.
+ * For example, if `temp1_input` is 37000 and `temp1_label` is 91 in sysfs,
+ `phosphor-hwmon` knows `temp1_input` is for sensor id 91, which is
+ `p0_core0_temp`, so it creates
+ `/xyz/openbmc_project/sensors/temperature/p0_core0_temp` with sensor
+ value 37000.
+ * For Romulus, the power sensors do not need to read label since all powers
+ are available on a system.
+ * For Witherspoon, the power sensors are similar to temperature sensors,
+ that it shall tell hwmon to read the `function_id` instead of directly
+ getting the index of the sensor.
+
+
+### LEDs
+
+Several parts are involved for LED.
+
+1. In kernel dts, LEDs shall be described, e.g. [romulus dts][12] describes
+ 3 LEDs, `fault`, `identify` and `power`.
+ ```
+ leds {
+ compatible = "gpio-leds";
+
+ fault {
+ gpios = <&gpio ASPEED_GPIO(N, 2) GPIO_ACTIVE_LOW>;
+ };
-[1]: https://github.com/openbmc/docs/blob/master/development/dev-environment.md
+ identify {
+ gpios = <&gpio ASPEED_GPIO(N, 4) GPIO_ACTIVE_HIGH>;
+ };
+
+ power {
+ gpios = <&gpio ASPEED_GPIO(R, 5) GPIO_ACTIVE_LOW>;
+ };
+ };
+ ```
+2. In machine layer, LEDs shall be configured via yaml to describe how it
+ functions, e.g. [Romulus led yaml][28]:
+ ```
+ bmc_booted:
+ power:
+ Action: 'Blink'
+ DutyOn: 50
+ Period: 1000
+ Priority: 'On'
+ power_on:
+ power:
+ Action: 'On'
+ DutyOn: 50
+ Period: 0
+ Priority: 'On'
+ ...
+ ```
+ It tells the LED manager to set the `power` LED to blink when BMC is ready
+ and booted, and set it on when host is powered on.
+3. At runtime, LED manager automatically set LEDs on/off/blink based on the
+ above yaml config.
+4. LED can be accessed manually via /xyz/openbmc_project/led/, e.g.
+ * Get identify LED state:
+ ```
+ curl -b cjar -k https://$bmc/xyz/openbmc_project/led/physical/identify
+ ```
+ * Set identify LED to blink:
+ ```
+ 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
+ ```
+5. When an error related to a FRU occurs, an event log is created in logging
+ with a CALLOUT path. [phosphor-fru-fault-monitor][29] monitors the logs:
+ * Assert the related fault LED group when a log with the CALLOUT path is
+ generated;
+ * De-assert the related fault LED group when the log is marked as
+ "Resolved" or deleted.
+
+**Note**: This yaml config can be automatically generated by
+[phosphor-mrw-tools][13] from its MRW, see [Witherspoon example][14].
+
+
+### Inventories and other sensors
+
+Inventories, other sensors (e.g. CPU/DIMM temperature), and FRUs are defined
+in ipmi's yaml config files.
+
+E.g. [meta-romulus/recipes-phosphor/ipmi][15]
+* `romulus-ipmi-inventory-map` defines regular inventories, e.g. CPU, memory,
+ motherboard.
+* `phosphor-ipmi-fru-properties` defines extra properties of the inventories.
+* `phosphor-ipmi-sensor-inventory` defines the sensors from IPMI.
+* `romulus-ipmi-inventory-sel` defines inventories used for IPMI SEL.
+
+For inventory map and fru-properties, they are similar between different
+systems, you can refer to this example and make one for your system.
+
+For ipmi-sensor-inventory, the sensors from IPMI are different between
+systems, so you need to define your own sensors, e.g.
+```
+0x08:
+ sensorType: 0x07
+ path: /org/open_power/control/occ0
+ ...
+0x1e:
+ sensorType: 0x0C
+ path: /system/chassis/motherboard/dimm0
+ ...
+0x22:
+ sensorType: 0x07
+ path: /system/chassis/motherboard/cpu0/core0
+```
+The first value `0x08`, `0x1e` and `0x22` are the sensor id of IPMI, which is
+defined in MRW.
+You should follow the system's MRW to define the above config.
+
+**Note**: The yaml configs can be automatically generated by
+[phosphor-mrw-tools][13] from its MRW, see [Witherspoon example][14].
+
+
+### Fans
+[phosphor-fan-presence][16] manages all the services about fan:
+* `phosphor-fan-presence` checks if a fan is present, creates the fan DBus
+ objects in inventory and update the `Present` property.
+* `phosphor-fan-monitor` checks if a fan is functional, and update the
+ `Functional` property of the fan Dbus object.
+* `phosphor-fan-control` controls the fan speed by setting the fan speed target
+ based on conditions, e.g. temperatures.
+* `phosphor-cooling-type` checks and sets if the system is air-cooled or
+ water-cooled by setting properties of
+ `/xyz/openbmc_project/inventory/system/chassis` object.
+
+All the above services are configurable, e.g. by yaml config.
+So the machine specific configs shall be written when porting OpenBMC to a new
+machine.
+
+Taking Romulus as an example, it is air-cooled and has 3 fans without GPIO
+presence detection.
+
+#### Fan presence
+Romulus has no GPIO detection for fans, so it checks fan tach sensor:
+```
+- name: fan0
+ path: /system/chassis/motherboard/fan0
+ methods:
+ - type: tach
+ sensors:
+ - fan0
+```
+The yaml config tells that
+* It shall create `/system/chassis/motherboard/fan0` object in inventory.
+* It shall check fan0 tach sensor (`/sensors/fan_tach/fan0`) to set `Present`
+ property on the fan0 object.
+
+#### Fan monitor
+Romulus fans use pwm to control the fan speed, where pwm ranges from 0 to 255,
+and the fan speed ranges from 0 to about 7000.
+So it needs a factor and offset to mapping the pwm to fan speed:
+```
+ - inventory: /system/chassis/motherboard/fan0
+ allowed_out_of_range_time: 30
+ deviation: 15
+ num_sensors_nonfunc_for_fan_nonfunc: 1
+ sensors:
+ - name: fan0
+ has_target: true
+ target_interface: xyz.openbmc_project.Control.FanPwm
+ factor: 21
+ offset: 1600
+```
+The yaml config tells that:
+1. It shall use `FanPwm` as target interface of the tach sensor.
+2. It shall calculate the expected fan speed as `target * 21 + 1600`.
+3. The deviation is `15%`, so if the fan speed is out of the expected range
+ for more than 30 seconds, fan0 shall be set as non-functional.
+
+#### Fan control
+The fan control service requires 4 yaml configuration files:
+* `zone-condition` defines the cooling zone conditions. Romulus is always
+ air-cooled, so this config is as simple as defining an `air_cooled_chassis`
+ condition based on the cooling type property.
+ ```
+ - name: air_cooled_chassis
+ type: getProperty
+ properties:
+ - property: WaterCooled
+ interface: xyz.openbmc_project.Inventory.Decorator.CoolingType
+ path: /xyz/openbmc_project/inventory/system/chassis
+ type: bool
+ value: false
+ ```
+* `zone-config` defines the cooling zones. Romulus has only one zone:
+ ```
+ zones:
+ - zone: 0
+ full_speed: 255
+ default_floor: 195
+ increase_delay: 5
+ decrease_interval: 30
+ ```
+ It defines that the zone full speed and default floor speed for the fans,
+ so the fan pwm will be set to 255 if it is in full speed, and set to 195 if
+ fans are in default floor speed.
+* `fan-config` defines which fans are controlled in which zone and which target
+ interface shall be used, e.g. below yaml config defines fan0 shall be
+ controlled in zone0 and it shall use `FanPwm` interface.
+ ```
+ - inventory: /system/chassis/motherboard/fan0
+ cooling_zone: 0
+ sensors:
+ - fan0
+ target_interface: xyz.openbmc_project.Control.FanPwm
+ ...
+ ```
+* `events-config` defines the various events and its handlers, e.g. which fan
+ targets shall be set in which temperature.
+ This config is a bit complicated, the [exmaple event yaml][17] provides
+ documents and examples.
+ Romulus example:
+ ```
+ - name: set_air_cooled_speed_boundaries_based_on_ambient
+ groups:
+ - name: zone0_ambient
+ interface: xyz.openbmc_project.Sensor.Value
+ property:
+ name: Value
+ type: int64_t
+ matches:
+ - name: propertiesChanged
+ actions:
+ - name: set_floor_from_average_sensor_value
+ map:
+ value:
+ - 27000: 85
+ - 32000: 112
+ - 37000: 126
+ - 40000: 141
+ type: std::map<int64_t, uint64_t>
+ - name: set_ceiling_from_average_sensor_value
+ map:
+ value:
+ - 25000: 175
+ - 27000: 255
+ type: std::map<int64_t, uint64_t>
+ ```
+ The above yaml config defines the fan floor and ceiling speed in
+ `zone0_ambient`'s different temperatures. E.g.
+ 1. When the temperature is lower than 27 degreesC, the floor speed (pwm)
+ shall be set to 85.
+ 2. When the temperature is between 27 and 32 degrees C, the floor speed
+ (pwm) shall be set to 112, etc.
+
+With above configs, phosphor-fan will run the fan presence/monitor/control
+logic as configured specifically for the machine.
+
+**Note**: Romulus fans are simple. For a more complicated example, refer to
+[Witherspoon fan configurations][18]. The following are the additional
+functions of Witherspoon fan configuration:
+
+* It checks GPIO for fan presence.
+* It checks GPIO to determine if the system is air or water cooled.
+* It has more sensors and more events in fan control.
+
+
+### GPIOs
+This section mainly focuses on the GPIOs in device tree that shall be
+monitored.
+E.g.:
+* A GPIO may represent a signal of host checkstop.
+* A GPIO may represent a button press.
+* A GPIO may represent if a device is attached or not.
+
+They are categorized as `phosphor-gpio-presence` for checking presences of a
+device, and `phosphor-gpio-monitor` for monitoring a GPIO.
+
+#### GPIOs in device tree
+All the GPIOs to be monitored shall be described in the device tree.
+E.g.
+```
+ gpio-keys {
+ compatible = "gpio-keys";
+ checkstop {
+ label = "checkstop";
+ gpios = <&gpio ASPEED_GPIO(J, 2) GPIO_ACTIVE_LOW>;
+ linux,code = <ASPEED_GPIO(J, 2)>;
+ };
+ id-button {
+ label = "id-button";
+ gpios = <&gpio ASPEED_GPIO(Q, 7) GPIO_ACTIVE_LOW>;
+ linux,code = <ASPEED_GPIO(Q, 7)>;
+ };
+ };
+```
+The following code describes two GPIO keys, one for `checkstop` and the other
+for `id-button`, where the key code is calculated from [aspeed-gpio.h][24]:
+```
+#define ASPEED_GPIO_PORT_A 0
+#define ASPEED_GPIO_PORT_B 1
+...
+#define ASPEED_GPIO_PORT_Y 24
+#define ASPEED_GPIO_PORT_Z 25
+#define ASPEED_GPIO_PORT_AA 26
+...
+
+#define ASPEED_GPIO(port, offset) \
+ ((ASPEED_GPIO_PORT_##port * 8) + offset)
+```
+
+#### GPIO Presence
+Witherspoon and Zaius have examples for gpio presence.
+
+* [Witherspoon][19]:
+ ```
+ INVENTORY=/system/chassis/motherboard/powersupply0
+ DEVPATH=/dev/input/by-path/platform-gpio-keys-event
+ KEY=104
+ NAME=powersupply0
+ DRIVERS=/sys/bus/i2c/drivers/ibm-cffps,3-0069
+ ```
+ It checks GPIO key 104 for `powersupply0`'s presence, creates the inventory
+ object and bind or unbind the driver.
+* [Zaius][20]:
+ ```
+ INVENTORY=/system/chassis/pcie_card_e2b
+ DEVPATH=/dev/input/by-path/platform-gpio-keys-event
+ KEY=39
+ NAME=pcie_card_e2b
+ ```
+ It checks GPIO key 39 for `pcie_card_e2b`'s presence, and creates the
+ inventory object.
+
+#### GPIO monitor
+Typical usage of GPIO monitor is to monitor the checkstop event from the host,
+or button presses.
+
+* [checkstop monitor][21] is a common service for OpenPOWER machines.
+ ```
+ DEVPATH=/dev/input/by-path/platform-gpio-keys-event
+ KEY=74
+ POLARITY=1
+ TARGET=obmc-host-crash@0.target
+ ```
+ By default it monitors GPIO key 74, and if it is triggered, it tells
+ systemd to start `obmc-host-crash@0.target`.
+ For systems using a different GPIO pin for checkstop, it simply overrides
+ the default one by specifying its own config file in meta-machine layer.
+ E.g. [Zaius's checkstop config][22].
+ **Note**: when the key is pressed, `phosphor-gpio-monitor` starts the target
+ unit and exits.
+* [id-button monitor][23] is an example service on Romulus to monitor ID
+ button press.
+ ```
+ DEVPATH=/dev/input/by-path/platform-gpio-keys-event
+ KEY=135
+ POLARITY=1
+ TARGET=id-button-pressed.service
+ EXTRA_ARGS=--continue
+ ```
+ It monitors GPIO key 135 for the button press and starts
+ `id-button-pressed.service`, that handles the event by setting the identify
+ LED group's `Assert` property.
+ **Note**: It has an extra argument, `--continue`, that tells
+ `phosphor-gpio-monitor` to not exit and continue running when the key is
+ pressed.
+
+[1]: https://github.com/openbmc/linux/blob/dev-4.13/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts
+[2]: https://lists.ozlabs.org/listinfo/openbmc
+[3]: https://github.com/openbmc/skeleton
+[4]: https://github.com/openbmc/openbmc/tree/master/meta-quanta/meta-q71l/recipes-phosphor/workbook
+[5]: https://github.com/openbmc/skeleton/blob/master/configs/Romulus.py
+[6]: https://github.com/openbmc/docs/blob/master/sensor-architecture.md
+[7]: https://github.com/openbmc/openbmc/tree/master/meta-ibm/meta-romulus/recipes-phosphor/sensors
+[8]: https://github.com/openbmc/openbmc/blob/298c4328fd20fcd7645da1565c143b1b668ef541/meta-ibm/meta-romulus/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/i2c%401e78a000/i2c-bus%40440/w83773g%404c.conf
+[9]: https://github.com/openbmc/linux/blob/aca92be80c008bceeb6fb62fd1d450b5be5d0a4f/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts#L208
+[10]: https://github.com/openbmc/openbmc/blob/298c4328fd20fcd7645da1565c143b1b668ef541/meta-ibm/meta-romulus/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/ahb/apb/pwm-tacho-controller%401e786000.conf
+[11]: https://github.com/openbmc/openbmc/blob/298c4328fd20fcd7645da1565c143b1b668ef541/meta-ibm/meta-romulus/recipes-phosphor/sensors/phosphor-hwmon/obmc/hwmon/devices/platform/gpio-fsi/fsi0/slave%4000--00/00--00--00--06/sbefifo1-dev0/occ-hwmon.1.conf
+[12]: https://github.com/openbmc/linux/blob/aca92be80c008bceeb6fb62fd1d450b5be5d0a4f/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts#L42
+[13]: https://github.com/openbmc/phosphor-mrw-tools
+[14]: https://github.com/openbmc/openbmc/blob/764b88f4056cc98082e233216704e94613499e64/meta-ibm/meta-witherspoon/conf/distro/openbmc-witherspoon.conf#L4
+[15]: https://github.com/openbmc/openbmc/tree/master/meta-ibm/meta-romulus/recipes-phosphor/ipmi
+[16]: https://github.com/openbmc/phosphor-fan-presence
+[17]: https://github.com/openbmc/phosphor-fan-presence/blob/master/control/example/events.yaml
+[18]: https://github.com/openbmc/openbmc/tree/master/meta-ibm/meta-witherspoon/recipes-phosphor/fans
+[19]: https://github.com/openbmc/openbmc/blob/master/meta-ibm/meta-witherspoon/recipes-phosphor/gpio/phosphor-gpio-monitor/obmc/gpio/phosphor-power-supply-0.conf
+[20]: https://github.com/openbmc/openbmc/blob/master/meta-ingrasys/meta-zaius/recipes-phosphor/gpio/phosphor-gpio-monitor/obmc/gpio/phosphor-pcie-card-e2b.conf
+[21]: https://github.com/openbmc/openbmc/blob/master/meta-openpower/recipes-phosphor/host/checkstop-monitor.bb
+[22]: https://github.com/openbmc/openbmc/blob/master/meta-ingrasys/meta-zaius/recipes-phosphor/host/checkstop-monitor/obmc/gpio/checkstop
+[23]: https://github.com/openbmc/openbmc/tree/master/meta-ibm/meta-romulus/recipes-phosphor/gpio
+[24]: https://github.com/openbmc/linux/blob/dev-4.13/include/dt-bindings/gpio/aspeed-gpio.h
+[25]: https://github.com/openbmc/docs/blob/master/development/add-new-system.md
+[26]: https://github.com/openbmc/openbmc/commit/e0e69beab7c268e4ad98972016c78b0d7d5769ac
+[27]: https://github.com/openbmc/openbmc/commit/2a80da2262bf13aa1ddb589cf3f2b672d26b0975
+[28]: https://github.com/openbmc/openbmc/blob/3cce45a96f0416b4c3d8f2b698cb830662a29227/meta-ibm/meta-romulus/recipes-phosphor/leds/romulus-led-manager-config/led.yaml
+[29]: https://github.com/openbmc/phosphor-led-manager/tree/master/fault-monitor
+[30]: https://github.com/openbmc/docs/blob/master/development/dev-environment.md
+[31]: https://github.com/openbmc/docs/blob/master/kernel-development.md
+[32]: https://github.com/openbmc/docs/blob/master/development/dev-environment.md
OpenPOWER on IntegriCloud