Some device drivers (panel backlights especially) need to follow precisesequences for powering on and off, involving gpios, regulators, PWMswith a precise powering order and delays to respect between each steps.These sequences are board-specific, and do not belong to a particulardriver - therefore they have been performed by board-specific hookfunctions to far.

With the advent of the device tree and of ARM kernels that are notboard-tied, we cannot rely on these board-specific hooks anymore butneed a way to implement these sequences in a portable manner. This patchintroduces a simple interpreter that can execute such power sequencesencoded either as platform data or within the device tree.

diff --git a/Documentation/power/power_seq.txt b/Documentation/power/power_seq.txtnew file mode 100644index 0000000..aa2ceb5--- /dev/null+++ b/Documentation/power/power_seq.txt@@ -0,0 +1,120 @@+Runtime Interpreted Power Sequences+-----------------------------------++Problem+-------+One very common board-dependent code is the out-of-driver code that is used to+turn a device on or off. For instance, SoC boards very commonly use a GPIO+(abstracted to a regulator or not) to control the power supply of a backlight,+disabling it when the backlight is not used in order to save power. The GPIO+that should be used, however, as well as the exact power sequence that may+involve different resources, is board-dependent and thus unknown of the driver.++This has been addressed so far by using hooks in the device's platform data that+are called whenever the state of the device might reflect a power change. This+approach, however, introduces board-dependant code into the kernel and is not+compatible with the device tree.++The Runtime Interpreted Power Sequences (or power sequences for short) aim at+turning this code into platform data or device tree nodes. Power sequences are+described using a simple format and run by a simple interpreter whenever needed.+This allows to remove the callback mechanism and makes the kernel less+board-dependant.++Sequences Format+----------------+Power sequences are a series of sequential steps during which an action is+performed on a resource. The supported resources so far are:+- GPIOs+- Regulators+- PWMs++Each step designates a resource and the following parameters:+- Whether the step should enable or disable the resource,+- Delay to wait before performing the action,+- Delay to wait after performing the action.++Both new resources and parameters can be introduced, but the goal is of course+to keep things as simple and compact as possible.++The platform data is a simple array of platform_power_seq_step instances, each+instance describing a step. The type as well as one of id or gpio members+(depending on the type) must be specified. The last step must be of type+POWER_SEQ_STOP. Regulator and PWM resources are identified by name. GPIO are+identified by number. For example, the following sequence will turn on the+"power" regulator of the device, wait 10ms, and set GPIO number 110 to 1:++struct platform_power_seq_step power_on_seq[] = {+ {+ .type = POWER_SEQ_REGULATOR,+ .id = "power",+ .params = {+ .enable = 1,+ .post_delay = 10,+ },+ },+ {+ .type = POWER_SEQ_GPIO,+ .gpio = 110,+ .params = {+ .enable = 1,+ },+ },+ {+ .type = POWER_SEQ_STOP,+ },+};++Usage by Drivers and Resources Management+-----------------------------------------+Power sequences make use of resources that must be properly allocated and+managed. The power_seq_build() function takes care of resolving the resources as+they are met in the sequence and to allocate them if needed:++power_seq *power_seq_build(struct device *dev, power_seq_resources *ress,+ platform_power_seq *pseq);++You will need an instance of power_seq_resources to keep track of the resources+that are already allocated. On success, the function returns a devm allocated+resolved sequence that is ready to be passed to power_seq_run(). In case of+failure, and error code is returned.++A resolved power sequence returned by power_seq_build can be run by+power_run_run():++int power_seq_run(struct device *dev, power_seq *seq);++It returns 0 if the sequence has successfully been run, or an error code if a+problem occured.++Finally, some resources that cannot be allocated through devm need to be freed+manually. Therefore, be sure to call power_seq_free_resources() in your device+remove function:++void power_seq_free_resources(power_seq_resources *ress);++Device tree+-----------+All the same, power sequences can be encoded as device tree nodes. The following+properties and nodes are equivalent to the platform data defined previously:++ power-supply = <&mydevice_reg>;+ enable-gpio = <&gpio 6 0>;++ power-on-sequence {+ regulator@0 {+ id = "power";+ enable;+ post-delay = <10>;+ };+ gpio@1 {+ id = "enable-gpio";+ enable;+ };+ };++Note that first, the phandles of the regulator and gpio used in the sequences+are defined as properties. Then the sequence references them through the id+property of every step. The name of sub-properties defines the type of the step.+Valid names are "regulator", "gpio" and "pwm". Steps must be numbered+sequentially.diff --git a/drivers/base/Kconfig b/drivers/base/Kconfigindex 08b4c52..65bebfe 100644--- a/drivers/base/Kconfig+++ b/drivers/base/Kconfig@@ -282,4 +282,8 @@ config CMA_AREAS