Design: Voltage regulator configuration

Proposal for a new application that would configure voltage regulators.
Application would read JSON file at run-time containing the regulator
configuration changes.  Changes would be applied prior to the regulators
being enabled during the boot.

Change-Id: I2a26d42fdf5cd97b2ff6365dfdad78c87b47ebe1
Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
diff --git a/designs/voltage-regulator-configuration.md b/designs/voltage-regulator-configuration.md
new file mode 100644
index 0000000..fc7ed6f
--- /dev/null
+++ b/designs/voltage-regulator-configuration.md
@@ -0,0 +1,246 @@
+# Voltage Regulator Configuration
+
+Author: Shawn McCarney (IRC ShawnMcCarney)
+
+Primary assignee: Shawn McCarney
+
+Other contributors: Derek Howard (IRC derekh55), Matt Spinler (IRC mspinler)
+
+Created: 2019-07-13
+
+
+## Problem Description
+[Voltage regulators][1] have many configurable properties such as output
+voltage, over-current limit, and pgood thresholds.  The configuration is often
+dependent on the system type and rail type.  Regulators have a hardware default
+configuration that is defined by hardware engineers early in system design.
+However, this default configuration sometimes must be modified by firmware.  A
+new application is needed to configure regulators.  It should be data-driven to
+support a variety of regulator types and to avoid hard-coded logic.
+
+
+## Background and References
+
+### Regulator Configuration Data ("Config File")
+Hardware engineers must specify many low-level configuration values for a
+regulator.  Some simple examples include output voltage, over-current limit,
+and pgood thresholds.  These values often vary depending on the system type and
+rail type.
+
+Depending on the regulator type, the hardware engineer may enter the
+configuration values into a tool that produces a "config file".
+
+The regulator configuration information is sent to manufacturing and stored in
+non-volatile memory on the regulator.  This provides the hardware/power-on
+default configuration.
+
+The default configuration values often need to be changed later.  This can be
+due to factors such as the following:
+* New information found during hardware testing.  For example, downstream
+  hardware requires a higher voltage or is drawing more current than expected.
+* Hardware workarounds.  Problems in the regulator hardware or related hardware
+  sometimes require new configuration values to work around the issue.  The
+  problem may be resolved in newer versions of the hardware, but firmware still
+  must support the older hardware.  For this reason, hardware workarounds are
+  sometimes conditional, applied only to regulators with a certain version
+  register value or [Vital Product Data (VPD)][2] keyword value.
+* Improve manufacturing yields.  Sometimes regulator configuration values must
+  be changed to allow more hardware to pass manufacturing tests.  For example,
+  the voltage may need to be increased to overcome minor manufacturing defects.
+
+### OpenBMC Regulator Configuration Scripts
+Regulator configuration changes are performed on some OpenBMC systems using
+shell scripts.  For example, the following scripts configure regulators on
+Witherspoon systems:
+* [vrm-control.sh][3]
+* [power-workarounds.sh][4]
+
+### Hwmon and IIO Device Driver Frameworks
+The Linux [Hardware Monitoring Kernel API (hwmon)][5] and [Industrial I/O
+Subsystem (IIO)][6] provide device driver frameworks for monitoring hardware
+and making sensor values available to applications.  They do not provide an
+interface for performing low-level regulator configuration.
+
+### Voltage and Current Regulator Device Framework
+The Linux [Voltage and Current Regulator API][7] provides a device driver
+framework for voltage and current regulators.  It provides a mechanism for the
+device drivers of "consumer" devices to request a voltage or current level from
+the regulator.  It does not provide an interface for performing low-level
+regulator configuration.
+
+
+## Requirements
+* Provide ability to modify configuration of any voltage regulator with a PMBus
+  or I2C connection to the BMC.
+* Apply the configuration changes early in the boot before the regulators are
+  enabled.
+* If an error occurs trying to configure a regulator, log the error and
+  continue with the next regulator.
+* Read configuration changes from a data file that is read at run-time.
+* Provide a method for testing new configuration changes by copying a new data
+  file to the BMC.
+
+### Non-Requirements
+* Enable/disable voltage regulators and monitor their pgood signals.
+  * This is handled by the power sequencer chip and related firmware.
+* Modify regulator configuration after regulator has been enabled.
+  * Modifying regulator configuration while the system is running
+    is often done by the host using a different bus connection.
+* Validate that the correct number and types of regulators are present in the
+  system.
+* Concurrent maintenance or hot-plugging of regulators, where a regulator is
+  removed/added/replaced while the system is running.
+
+
+## Proposed Design
+
+### Application
+A new application named `phosphor-regulators` will be created to configure
+voltage regulators.  The application will be located in the proposed new
+`phosphor-power` repository.
+
+*Statement of direction: This application will provide other regulator-based
+functionality in the future, such as detecting redundant phase faults.*
+
+### Application Data File
+The application will read a JSON file at runtime that defines the configuration
+changes for all regulators.  The JSON file will be specific to a system type,
+so it will be stored in the GitHub repository for the appropriate build layer
+(such as meta-ibm).
+
+JSON file location on the BMC:
+* Standard directory: `/usr/share/phosphor-regulators` (read-only)
+* Test directory: `/etc/phosphor-regulators` (writable)
+
+A new version of the JSON file can be tested by copying it to the test
+directory.  The application will search both directories, and the file in the
+test directory will override the file in the standard directory.  If the
+application receives a SIGHUP signal, it will re-read the JSON file.
+
+A document will be provided that describes the objects and properties that can
+appear in the JSON file.  A validation tool will also be provided to verify the
+syntax and contents of the JSON file.
+
+*Statement of direction: This JSON file will be used in the future to define
+other regulator operations, such as how to detect a redundant phase fault.*
+
+### D-Bus Interfaces
+The following new D-Bus interface will be created:
+* Name: `xyz.openbmc_project.Regulator.Collection.Configure`
+* Description: Configures all voltage regulators.
+* Properties: None
+* Methods: Configure()
+
+*Statement of direction: New interfaces that apply to all regulators would use
+the same xyz.openbmc_project.Regulator.Collection namespace.  New interfaces
+that apply to a single regulator would use the xyz.openbmc_project.Regulator
+namespace.*
+
+### D-Bus Paths
+The new `xyz.openbmc_project.Regulator.Collection.Configure` interface will be
+implemented on the object path `/xyz/openbmc_project/regulators`.
+
+*Statement of direction: New interfaces that apply to all regulators would be
+implemented on the same object path.  Individual regulators would be
+represented by the object path
+`/xyz/openbmc_project/regulators/<regulator_name>`, and interfaces that apply
+to a single regulator would be implemented on that path.*
+
+### Systemd
+The application will be started using systemd when the BMC is at standby.  The
+service file will be named `xyz.openbmc_project.Regulators.service`.
+
+During the boot when the chassis is being powered on, the Configure() method on
+the new `xyz.openbmc_project.Regulator.Collection.Configure` interface will be
+called.  This must be done prior to the systemd target that enables the
+regulators (powers them on).
+
+### Regulator Device Interface
+The application will communicate with the voltage regulators directly using the
+[i2c-dev][8] userspace I2C interface.  Direct communication will be used rather
+than device drivers because the current Linux device driver frameworks do not
+provide the necessary functionality.  See the [Alternatives
+Considered](#alternatives-considered) section for more information.
+
+Voltage regulators that are configured using this application will not be bound
+to device drivers in the Linux device tree.  When the system is powered on, the
+application will obtain the regulator sensor values and store them on D-Bus in
+the same format as `phosphor-hwmon`.
+
+*Statement of direction: If a driver framework is developed in the future that
+supports low-level regulator configuration, then this application will be
+enhanced to utilize those drivers.  The goal is for the application to support
+a flexible device interface, where drivers are used if possible and i2c-dev is
+used if necessary.*
+
+
+## Alternatives Considered
+
+### Using Standard Linux Device Drivers to Configure Regulators
+Ideally one of the following device driver frameworks could be used rather than
+i2c-dev to configure the regulators:
+* [Hardware Monitoring Kernel API][5]
+* [Industrial I/O Subsystem][6]
+* [Voltage and Current Regulator API][7]
+
+Unfortunately none of these provide the required functionality:
+* Ability to perform system-specific and rail-specific, low-level
+  configuration.
+* Ability to perform dynamic configuration based on regulator version register
+  values or [VPD][2] values.
+* Ability to test new configuration values iteratively and quickly without
+  needing to modify a device driver or rebuild the kernel.
+
+A meeting was held with Joel Stanley and Andrew Jeffery to discuss this issue.
+They believe long term a new driver framework could be designed that would
+provide this functionality and would be acceptable to the Linux upstream
+community.  If this occurs, this application will be modified to utilize the
+new driver framework rather than performing direct I2C communication from
+userspace.
+
+### Using Shell Scripts to Configure Regulators
+Currently shell scripts are used to configure regulators on some OpenBMC
+systems, such as Witherspoon.  During boot, the shell scripts unbind device
+drivers, perform `i2cset` commands to configure regulators, and then re-bind
+device drivers.
+
+Using shell scripts has the following disadvantages:
+* Typically no error checking is performed to verify the `i2cset` command
+  worked.  If error checking were added based on return code, it would be
+  difficult to log an appropriate error with all the necessary information.
+* On a large system with many regulators and register updates, a shell
+  script would run more slowly than an application and negatively impact boot
+  speed.  Each `i2cset` command requires starting a separate child process.
+* Scripts are usually hard-coded to one system type and do not provide a
+  common, data-driven solution.
+
+
+## Impacts
+* No major impacts are expected to existing APIs, security, documentation,
+  performance, or upgradability.
+* The new D-Bus interface is documented in the [Proposed
+  Design](#proposed-design) section.
+* The application should be able to configure regulators using
+  i2c-dev as fast or faster than equivalent shell scripts using `i2cset`.
+* The regulator sensor values will be stored on D-Bus in a way that is
+  consistent with `phosphor-hwmon`.
+
+
+## Testing
+* Automated test cases will be written to test as much of the application code
+  as possible.
+* A mock device interface will be used to test that the correct I2C reads and
+  writes are occurring without accessing real hardware.
+* End-to-end boot testing will be performed to ensure that the correct I2C
+  reads/writes occurred, that the system boots, and that no errors occur.
+* CI tests that boot a system will indirectly test this application.
+
+
+[1]: https://en.wikipedia.org/wiki/Voltage_regulator_module
+[2]: https://en.wikipedia.org/wiki/Vital_Product_Data
+[3]: https://github.com/openbmc/meta-ibm/blob/master/meta-witherspoon/recipes-phosphor/chassis/vrm-control/vrm-control.sh
+[4]: https://github.com/openbmc/meta-ibm/blob/master/meta-witherspoon/recipes-phosphor/chassis/power-workarounds/witherspoon/power-workarounds.sh
+[5]: https://www.kernel.org/doc/html/latest/hwmon/hwmon-kernel-api.html
+[6]: https://www.kernel.org/doc/html/latest/driver-api/iio/index.html
+[7]: https://www.kernel.org/doc/html/latest/driver-api/regulator.html
+[8]: https://www.kernel.org/doc/Documentation/i2c/dev-interface