diff mbox

[RFC,v3,1/3] runtime interpreted power sequences

Message ID 1343390750-3642-2-git-send-email-acourbot@nvidia.com (mailing list archive)
State New, archived
Headers show

Commit Message

Alexandre Courbot July 27, 2012, 12:05 p.m. UTC
Some device drivers (panel backlights especially) need to follow precise
sequences for powering on and off, involving gpios, regulators, PWMs
with a precise powering order and delays to respect between each steps.
These sequences are board-specific, and do not belong to a particular
driver - therefore they have been performed by board-specific hook
functions to far.

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

Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
---
 Documentation/power/power_seq.txt | 120 +++++++++++++++
 drivers/base/Kconfig              |   4 +
 drivers/base/Makefile             |   1 +
 drivers/base/power_seq.c          | 300 ++++++++++++++++++++++++++++++++++++++
 include/linux/power_seq.h         | 139 ++++++++++++++++++
 5 files changed, 564 insertions(+)
 create mode 100644 Documentation/power/power_seq.txt
 create mode 100644 drivers/base/power_seq.c
 create mode 100644 include/linux/power_seq.h

Comments

Greg KH July 27, 2012, 6:19 p.m. UTC | #1
On Fri, Jul 27, 2012 at 09:05:48PM +0900, Alexandre Courbot wrote:
> Some device drivers (panel backlights especially) need to follow precise
> sequences for powering on and off, involving gpios, regulators, PWMs
> with a precise powering order and delays to respect between each steps.
> These sequences are board-specific, and do not belong to a particular
> driver - therefore they have been performed by board-specific hook
> functions to far.
> 
> With the advent of the device tree and of ARM kernels that are not
> board-tied, we cannot rely on these board-specific hooks anymore but
> need a way to implement these sequences in a portable manner. This patch
> introduces a simple interpreter that can execute such power sequences
> encoded either as platform data or within the device tree.
> 
> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
> ---
>  Documentation/power/power_seq.txt | 120 +++++++++++++++
>  drivers/base/Kconfig              |   4 +
>  drivers/base/Makefile             |   1 +
>  drivers/base/power_seq.c          | 300 ++++++++++++++++++++++++++++++++++++++
>  include/linux/power_seq.h         | 139 ++++++++++++++++++

What's wrong with drivers/power/?  I sure don't want to maintain this
code, and it seems to not be part of the "driver core" infrastructure.

thanks,

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Greg KH July 27, 2012, 6:20 p.m. UTC | #2
On Fri, Jul 27, 2012 at 09:05:48PM +0900, Alexandre Courbot wrote:
> +++ b/include/linux/power_seq.h
> @@ -0,0 +1,139 @@
> +/*
> + * power_seq.h
> + *
> + * Simple interpreter for defining power sequences as platform data or device
> + * tree properties. Initially designed for use with backlight drivers.
> + *
> + * Power sequences are designed to replace the callbacks typically used in
> + * board-specific files that implement board-specific power sequences of devices
> + * such as backlights. A power sequence is an array of resources (which can a
> + * regulator, a GPIO, a PWM, ...) with an action to perform on it (enable or
> + * disable) and optional pre and post step delays. By having them interpreted
> + * instead of arbitrarily executed, it is possible to describe these in the
> + * device tree and thus remove board-specific code from the kernel.
> + *
> + * Author: Alexandre Courbot <acourbot@nvidia.com>
> + *
> + * Copyright (c) 2012 NVIDIA Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

As I always say:
	Unless you want to track the office movements of the FSF for the
	next 40 years, and keep this file up to date, drop that last
	paragraph, it's pointless.

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alexandre Courbot July 30, 2012, 1:51 a.m. UTC | #3
On 07/28/2012 03:19 AM, Greg Kroah-Hartman wrote:
> On Fri, Jul 27, 2012 at 09:05:48PM +0900, Alexandre Courbot wrote:
>> Some device drivers (panel backlights especially) need to follow precise
>> sequences for powering on and off, involving gpios, regulators, PWMs
>> with a precise powering order and delays to respect between each steps.
>> These sequences are board-specific, and do not belong to a particular
>> driver - therefore they have been performed by board-specific hook
>> functions to far.
>>
>> With the advent of the device tree and of ARM kernels that are not
>> board-tied, we cannot rely on these board-specific hooks anymore but
>> need a way to implement these sequences in a portable manner. This patch
>> introduces a simple interpreter that can execute such power sequences
>> encoded either as platform data or within the device tree.
>>
>> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
>> ---
>>   Documentation/power/power_seq.txt | 120 +++++++++++++++
>>   drivers/base/Kconfig              |   4 +
>>   drivers/base/Makefile             |   1 +
>>   drivers/base/power_seq.c          | 300 ++++++++++++++++++++++++++++++++++++++
>>   include/linux/power_seq.h         | 139 ++++++++++++++++++
>
> What's wrong with drivers/power/?  I sure don't want to maintain this
> code, and it seems to not be part of the "driver core" infrastructure.

I thought about drivers/power/ initially, but quickly realized it was 
only about the power supply class and its drivers - so I felt like it 
would be out of place there, as the power sequences have nothing to do 
with power supply but instead control gpios, regulators and pwms.

On the other hand I have just noticed that the apparently unrelated 
Adaptive Voltage Scaling driver just appeared in drivers/power/avs. So 
if Anton and David are ok with this, maybe I could put the power 
sequences code in its own subdirectory within drivers/power.

Thanks,
Alex.

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Anton Vorontsov July 30, 2012, 2:40 a.m. UTC | #4
On Mon, Jul 30, 2012 at 10:51:42AM +0900, Alex Courbot wrote:
[...]
> On the other hand I have just noticed that the apparently unrelated
> Adaptive Voltage Scaling driver just appeared in drivers/power/avs.
> So if Anton and David are ok with this, maybe I could put the power
> sequences code in its own subdirectory within drivers/power.

Well, currently drivers/power/ is indeed just for power supply class
subsystem and drivers. But if the trend is to gather power management
("policy") stuff under one directory, i.e.

drivers/
  power/
    supplies/    <- former "power supply class and drivers"
    regulators/
    idle/
    cpuidle/
    cpufreq/
    devfreq/
    avs/
    ...

That would probably make sense, we could easily see the big picture.
But if we're not going to do this long-term, I would suggest to stick
to just a new directory under drivers (and move drivers/power/avs/ to
drivers/avs).

Cc'ing some more people...

Thanks,

p.s. Jean, why am I the last person who discovers drivers/power/avs/?
Would be nice to Cc me on such patches; by moving AVS under
drivers/power/ you effectively nominated me as its maintainer. :-)
Simon Glass July 30, 2012, 11 a.m. UTC | #5
Hi,

On Fri, Jul 27, 2012 at 1:05 PM, Alexandre Courbot <acourbot@nvidia.com> wrote:
> Some device drivers (panel backlights especially) need to follow precise
> sequences for powering on and off, involving gpios, regulators, PWMs
> with a precise powering order and delays to respect between each steps.
> These sequences are board-specific, and do not belong to a particular
> driver - therefore they have been performed by board-specific hook
> functions to far.
>
> With the advent of the device tree and of ARM kernels that are not
> board-tied, we cannot rely on these board-specific hooks anymore but
> need a way to implement these sequences in a portable manner. This patch
> introduces a simple interpreter that can execute such power sequences
> encoded either as platform data or within the device tree.

This all looks very reasonable to me, just a few comments.

>
> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
> ---
>  Documentation/power/power_seq.txt | 120 +++++++++++++++
>  drivers/base/Kconfig              |   4 +
>  drivers/base/Makefile             |   1 +
>  drivers/base/power_seq.c          | 300 ++++++++++++++++++++++++++++++++++++++
>  include/linux/power_seq.h         | 139 ++++++++++++++++++
>  5 files changed, 564 insertions(+)
>  create mode 100644 Documentation/power/power_seq.txt
>  create mode 100644 drivers/base/power_seq.c
>  create mode 100644 include/linux/power_seq.h
>
> diff --git a/Documentation/power/power_seq.txt b/Documentation/power/power_seq.txt
> new file mode 100644
> index 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:

For the delay, I think milliseconds is reasonable. I suppose there is
no reasonable need for microseconds?

> +
> +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";

Is there a reason not to put the phandle here, like:

                                   id = <&mydevice_reg>;

(or maybe 'device' instead of id?)

> +                               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.

For the regulator and gpio types I think you only have an enable. For
the pwm, what is the intended binding? Is that documented elsewhere?

Also it might be worth mentioning how you get a struct power_seq from
an fdt node, and perhaps given an example of a device which has an
attached node, so we can see how it is referenced from the device
(of_parse_power_seq I think). Do put the sequence inside the device
node or reference it with a phandle?

Finally, should you use typedefs?

Regards,
Simon
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thierry Reding July 30, 2012, 11:33 a.m. UTC | #6
On Fri, Jul 27, 2012 at 09:05:48PM +0900, Alexandre Courbot wrote:
> Some device drivers (panel backlights especially) need to follow precise
> sequences for powering on and off, involving gpios, regulators, PWMs
> with a precise powering order and delays to respect between each steps.
> These sequences are board-specific, and do not belong to a particular
> driver - therefore they have been performed by board-specific hook
> functions to far.
> 
> With the advent of the device tree and of ARM kernels that are not
> board-tied, we cannot rely on these board-specific hooks anymore but
> need a way to implement these sequences in a portable manner. This patch
> introduces a simple interpreter that can execute such power sequences
> encoded either as platform data or within the device tree.
> 
> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
> ---
>  Documentation/power/power_seq.txt | 120 +++++++++++++++
>  drivers/base/Kconfig              |   4 +
>  drivers/base/Makefile             |   1 +
>  drivers/base/power_seq.c          | 300 ++++++++++++++++++++++++++++++++++++++
>  include/linux/power_seq.h         | 139 ++++++++++++++++++
>  5 files changed, 564 insertions(+)
>  create mode 100644 Documentation/power/power_seq.txt
>  create mode 100644 drivers/base/power_seq.c
>  create mode 100644 include/linux/power_seq.h
> 
> diff --git a/Documentation/power/power_seq.txt b/Documentation/power/power_seq.txt
> new file mode 100644
> index 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.

I don't quite understand why the struct power_seq_resources is needed.
Can this not be stored within power_seq?

> +
> +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);

Why is the struct device required here? It already is passed during the
call to pwm_seq_build(), so perhaps you should keep a reference to it
within struct power_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);

Could this not also be handled by a managed version? If a power_seq is
always managed, then I would assume that it also takes care of freeing
the resources, even if the resources have no managed equivalents.

Perhaps it would also make sense to provide non-managed version of these
functions. I think that would make the managed versions easier and more
canonical to implement.

> +
> +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.

I think there has been quite some discussion regarding the naming of
subnodes and the conclusion seems to have been to name them uniformly
after what they represent. As such the power-on-sequence subnodes should
be called step@0, step@1, etc. However, that will require the addition
of a property to define the type of resource.

Also, is there some way we can make the id property for GPIOs not
require the -gpio suffix? If the resource type is already GPIO, then it
seems redundant to add -gpio to the ID.

> diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
> index 08b4c52..65bebfe 100644
> --- a/drivers/base/Kconfig
> +++ b/drivers/base/Kconfig
> @@ -282,4 +282,8 @@ config CMA_AREAS
>  
>  endif
>  
> +config POWER_SEQ
> +	bool
> +	default n
> +

"default n" is already the default, so you can drop that line.

>  endmenu
> diff --git a/drivers/base/Makefile b/drivers/base/Makefile
> index 5aa2d70..4c498c1 100644
> --- a/drivers/base/Makefile
> +++ b/drivers/base/Makefile
> @@ -18,6 +18,7 @@ obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o
>  ifeq ($(CONFIG_SYSFS),y)
>  obj-$(CONFIG_MODULES)	+= module.o
>  endif
> +obj-$(CONFIG_POWER_SEQ)	+= power_seq.o
>  obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
>  obj-$(CONFIG_REGMAP)	+= regmap/
>  obj-$(CONFIG_SOC_BUS) += soc.o
> diff --git a/drivers/base/power_seq.c b/drivers/base/power_seq.c
> new file mode 100644
> index 0000000..6ccefa1
> --- /dev/null
> +++ b/drivers/base/power_seq.c
> @@ -0,0 +1,300 @@
> +/*
> + * power_seq.c - A simple power sequence interpreter for platform devices
> + *               and device tree.
> + *
> + * Author: Alexandre Courbot <acourbot@nvidia.com>
> + *
> + * Copyright (c) 2012 NVIDIA Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
> + *
> + */
> +
> +#include <linux/power_seq.h>
> +#include <linux/module.h>
> +#include <linux/err.h>
> +#include <linux/device.h>
> +#include <linux/slab.h>
> +#include <linux/delay.h>
> +#include <linux/pwm.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/gpio.h>
> +
> +#ifdef CONFIG_OF
> +#include <linux/of.h>
> +#include <linux/of_gpio.h>
> +#endif

I think you don't need the CONFIG_OF guard around these. Both of.h and
of_gpio.h can be included unconditionally and actually contain dummy
definitions for the public functions in the !OF case.

> +
> +static int power_seq_step_run(struct power_seq_step *step)
> +{
> +	int err = 0;
> +
> +	if (step->params.pre_delay)
> +		mdelay(step->params.pre_delay);
> +
> +	switch (step->resource->type) {
> +#ifdef CONFIG_REGULATOR
> +	case POWER_SEQ_REGULATOR:
> +		if (step->params.enable)
> +			err = regulator_enable(step->resource->regulator);
> +		else
> +			err = regulator_disable(step->resource->regulator);
> +		break;
> +#endif
> +#ifdef CONFIG_PWM
> +	case POWER_SEQ_PWM:
> +		if (step->params.enable)
> +			err = pwm_enable(step->resource->pwm);
> +		else
> +			pwm_disable(step->resource->pwm);
> +		break;
> +#endif
> +#ifdef CONFIG_GPIOLIB
> +	case POWER_SEQ_GPIO:
> +		gpio_set_value_cansleep(step->resource->gpio,
> +					step->params.enable);
> +		break;
> +#endif

This kind of #ifdef'ery is quite ugly. I don't know if adding separate
*_run() functions for each type of resource would be any better, though.
Alternatively, maybe POWER_SEQ should depend on the REGULATOR, PWM and
GPIOLIB symbols to side-step the issue completely?

> +	/*
> +	 * should never happen unless the sequence includes a step which
> +	 * type does not have support compiled in
> +	 */
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	if (err < 0)
> +		return err;
> +
> +	if (step->params.post_delay)
> +		mdelay(step->params.post_delay);
> +
> +	return 0;
> +}
> +
> +int power_seq_run(struct device *dev, power_seq *seq)
> +{
> +	int err;
> +
> +	if (!seq) return 0;

I don't think this is acceptable according to the coding style. Also,
perhaps returning -EINVAL would be more meaningful?

> +
> +	while (seq->resource) {

Perhaps this should check for POWER_SEQ_STOP instead?

> +		if ((err = power_seq_step_run(seq++))) {
> +			dev_err(dev, "error %d while running power sequence!\n",
> +				err);

For this kind of diagnostics it could be useful to have a name
associated with the power sequence. But I'm not sure that making the
power sequence code output an error here is the best solution. I find it
to be annoying when core code starts outputting too many error codes. In
this case it's particularily easy to catch the errors in the caller.

> +			return err;
> +		}
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(power_seq_run);
> +
> +#ifdef CONFIG_OF
> +static int of_parse_power_seq_step(struct device *dev, struct device_node *node,
> +				   struct platform_power_seq_step *step)
> +{
> +	if (of_property_read_string(node, "id", &step->id)) {
> +		dev_err(dev, "missing id property!\n");
> +		return -EINVAL;
> +	}
> +
> +	if (!strcmp(node->name, "regulator")) {
> +		step->type = POWER_SEQ_REGULATOR;
> +#ifdef CONFIG_OF_GPIO
> +	} else if (!strcmp(node->name, "gpio")) {
> +		int gpio;
> +
> +		step->type = POWER_SEQ_GPIO;
> +		gpio = of_get_named_gpio(dev->of_node, step->id, 0);
> +		if (gpio < 0) {
> +			dev_err(dev, "cannot resolve gpio \"%s\"\n", step->id);
> +			return gpio;
> +		}
> +		step->gpio = gpio;
> +#endif /* CONFIG_OF_GPIO */
> +	} else if (!strcmp(node->name, "pwm")) {
> +		step->type = POWER_SEQ_PWM;
> +	} else {
> +		dev_err(dev, "invalid power seq step type!\n");
> +		return -EINVAL;
> +	}
> +
> +	if (of_find_property(node, "enable", NULL)) {
> +		step->params.enable = 1;
> +	} else if (!of_find_property(node, "disable", NULL)) {
> +		dev_err(dev, "missing enable or disable property!\n");
> +		return -EINVAL;
> +	}
> +
> +	of_property_read_u32(node, "pre-delay", &step->params.pre_delay);
> +	of_property_read_u32(node, "post-delay", &step->params.post_delay);
> +
> +	return 0;
> +}
> +
> +platform_power_seq *of_parse_power_seq(struct device *dev,
> +				       struct device_node *node)
> +{
> +	struct device_node *child = NULL;
> +	platform_power_seq *ret;
> +	int cpt = 0;
> +	int err;
> +
> +	if (!node) return NULL;

Again, this should probably be split across two lines.

> +
> +	while ((child = of_get_next_child(node, child)))
> +		cpt++;

for_each_child_of_node()?

> +
> +	/* allocate one more step to signal end of sequence */
> +	ret = devm_kzalloc(dev, sizeof(*ret) * (cpt + 1), GFP_KERNEL);
> +	if (!ret)
> +		return ERR_PTR(-ENOMEM);
> +
> +	cpt = 0;
> +	while ((child = of_get_next_child(node, child))) {

Here as well.

> +		if ((err = of_parse_power_seq_step(dev, child, &ret[cpt++])))
> +			return ERR_PTR(err);
> +	}
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(of_parse_power_seq);
> +#endif /* CONFIG_OF */
> +
> +static
> +struct power_seq_resource * power_seq_find_resource(power_seq_resources *ress,
> +					struct platform_power_seq_step *res)
> +{
> +	struct power_seq_resource *step;
> +
> +	list_for_each_entry(step, ress, list) {
> +		if (step->type != res->type) continue;
> +		switch (res->type) {
> +		case POWER_SEQ_GPIO:
> +			if (step->gpio == res->gpio)
> +				return step;
> +			break;
> +		default:
> +			if (!strcmp(step->id, res->id))
> +				return step;
> +			break;
> +		}
> +	}
> +
> +	return NULL;
> +}
> +
> +static int power_seq_allocate_resource(struct device *dev,
> +				       struct power_seq_resource *res)
> +{
> +	int err;
> +
> +	switch (res->type) {
> +#ifdef CONFIG_REGULATOR
> +	case POWER_SEQ_REGULATOR:
> +		res->regulator = devm_regulator_get(dev, res->id);
> +		if (IS_ERR(res->regulator)) {
> +			dev_err(dev, "cannot get regulator \"%s\"\n", res->id);
> +			return PTR_ERR(res->regulator);
> +		}
> +		break;
> +#endif
> +#ifdef CONFIG_PWM
> +	case POWER_SEQ_PWM:
> +		res->pwm = pwm_get(dev, res->id);
> +		if (IS_ERR(res->pwm)) {
> +			dev_err(dev, "cannot get pwm \"%s\"\n", res->id);
> +			return PTR_ERR(res->pwm);
> +		}
> +		break;
> +#endif
> +#ifdef CONFIG_GPIOLIB
> +	case POWER_SEQ_GPIO:
> +		err = devm_gpio_request_one(dev, res->gpio, GPIOF_OUT_INIT_HIGH,
> +					    "backlight_gpio");
> +		if (err) {
> +			dev_err(dev, "cannot get gpio %d\n", res->gpio);
> +			return err;
> +		}
> +		break;
> +#endif
> +	default:
> +		dev_err(dev, "invalid resource type %d\n", res->type);
> +		return -EINVAL;
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +power_seq *power_seq_build(struct device *dev, power_seq_resources *ress,
> +			   platform_power_seq *pseq)
> +{
> +	struct power_seq_step *seq = NULL, *ret;
> +	struct power_seq_resource *res;
> +	int cpt, err;
> +
> +	/* first pass to count the number of steps to allocate */
> +	for (cpt = 0; pseq[cpt].type != POWER_SEQ_STOP; cpt++);

Wouldn't it be easier to pass around the number of steps in the sequence
instead of having to count in various places? This would be more along
the lines of how struct platform_device defines associated resources.

> +
> +	if (!cpt)
> +		return seq;

Perhaps this should return an error-code as well? I find it nice to not
have to handle NULL specially when using ERR_PTR et al.

> +
> +	/* 1 more for the STOP step */
> +	ret = seq = devm_kzalloc(dev, sizeof(*seq) * (cpt + 1), GFP_KERNEL);
> +	if (!seq)
> +		return ERR_PTR(-ENOMEM);
> +
> +	for (; pseq->type != POWER_SEQ_STOP; pseq++, seq++) {
> +		/* create resource node if not referenced already */
> +		if (!(res = power_seq_find_resource(ress, pseq))) {
> +			res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
> +			if (!res)
> +				return ERR_PTR(-ENOMEM);
> +			res->type = pseq->type;
> +
> +			if (res->type == POWER_SEQ_GPIO)
> +				res->gpio = pseq->gpio;
> +			else
> +				res->id = pseq->id;
> +
> +			if ((err = power_seq_allocate_resource(dev, res)) < 0)
> +				return ERR_PTR(err);
> +
> +			list_add(&res->list, ress);
> +		}
> +		seq->resource = res;
> +		memcpy(&seq->params, &pseq->params, sizeof(seq->params));
> +	}
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(power_seq_build);
> +
> +void power_seq_free_resources(power_seq_resources *ress) {

The brace needs to go on a line by itself.

> +	struct power_seq_resource *res;
> +
> +#ifdef CONFIG_PWM
> +	list_for_each_entry(res, ress, list) {
> +		if (res->type == POWER_SEQ_PWM)
> +			pwm_put(res->pwm);
> +	}
> +#endif
> +}
> +EXPORT_SYMBOL_GPL(power_seq_free_resources);
> +
> +MODULE_AUTHOR("Alexandre Courbot <acourbot@nvidia.com>");
> +MODULE_DESCRIPTION("Runtime Interpreted Power Sequences");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/power_seq.h b/include/linux/power_seq.h
> new file mode 100644
> index 0000000..da0593a
> --- /dev/null
> +++ b/include/linux/power_seq.h
> @@ -0,0 +1,139 @@
> +/*
> + * power_seq.h
> + *
> + * Simple interpreter for defining power sequences as platform data or device
> + * tree properties. Initially designed for use with backlight drivers.
> + *
> + * Power sequences are designed to replace the callbacks typically used in
> + * board-specific files that implement board-specific power sequences of devices
> + * such as backlights. A power sequence is an array of resources (which can a
> + * regulator, a GPIO, a PWM, ...) with an action to perform on it (enable or
> + * disable) and optional pre and post step delays. By having them interpreted
> + * instead of arbitrarily executed, it is possible to describe these in the
> + * device tree and thus remove board-specific code from the kernel.
> + *
> + * Author: Alexandre Courbot <acourbot@nvidia.com>
> + *
> + * Copyright (c) 2012 NVIDIA Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
> + *
> + */
> +
> +#ifndef __LINUX_POWER_SEQ_H
> +#define __LINUX_POWER_SEQ_H
> +
> +#include <linux/types.h>
> +
> +struct device;
> +struct regulator;
> +struct pwm_device;
> +struct device_node;
> +
> +/**
> + * The different kinds of resources that can be controlled during the sequences.
> + */
> +typedef enum {
> +	POWER_SEQ_STOP = 0,
> +	POWER_SEQ_REGULATOR,
> +	POWER_SEQ_PWM,
> +	POWER_SEQ_GPIO,
> +	POWER_SEQ_MAX,
> +} power_res_type;

Maybe the prefix power_seq should be used here as well, so:
power_seq_res_type.

> +
> +struct power_seq_resource {
> +	power_res_type type;
> +	/* name to resolve for resources with a name (regulator, pwm) */
> +	const char *id;
> +	/* resolved resource */
> +	union {
> +		struct regulator *regulator;
> +		struct pwm_device *pwm;
> +		int gpio;
> +	};
> +	/* used to maintain the list of resources used by the driver */
> +	struct list_head list;
> +};
> +typedef struct list_head power_seq_resources;

No type definitions like this, please. Also, why define this particular
type globally?

> +
> +struct power_step_params {
> +	/* enable the resource if 1, disable if 0 */
> +	bool enable;
> +	/* delay (in ms) to wait before executing the step */
> +	int  pre_delay;
> +	/* delay (in ms) to wait after executing the step */
> +	int post_delay;

unsigned int for the delays?

> +};
> +
> +/**
> + * Platform definition of power sequences. A sequence is an array of these,
> + * terminated by a STOP instance.
> + */
> +struct platform_power_seq_step {
> +	power_res_type type;
> +	union {
> +		/* Used by REGULATOR and PWM types to name the resource */
> +		const char *id;
> +		/* Used by GPIO */
> +		int gpio;
> +	};
> +	struct power_step_params params;
> +};
> +typedef struct platform_power_seq_step platform_power_seq;

Why are the parameters kept in a separate structure? What are the
disadvantages of keeping the in the sequence step structure directly?

> +
> +/**
> + * Power sequence steps resolved against their resource. Built by
> + * power_seq_build and used to run the sequence.
> + */
> +struct power_seq_step {
> +	struct power_seq_resource *resource;
> +	struct power_step_params params;
> +};
> +typedef struct power_seq_step power_seq;

Would it make sense to make the struct power_seq opaque? I don't see why
anyone but the power_seq code should access the internals. For resource
managing it might also be easier to separate struct power_seq_step and
struct power_seq, making the power_seq basically something like:

	struct power_seq {
		struct power_seq_step *steps;
		unsigned int num_steps;
	};

Perhaps a name field can be included for diagnostic purposes.

> +
> +#ifdef CONFIG_OF
> +/**
> + * Build a platform data sequence from a device tree node. Memory for the
> + * sequence is allocated using devm_kzalloc on dev.
> + */
> +platform_power_seq *of_parse_power_seq(struct device *dev,
> +				       struct device_node *node);
> +#else
> +platform_power_seq *of_parse_power_seq(struct device *dev,
> +				       struct device_node *node)
> +{
> +	return NULL;
> +}
> +#endif
> +
> +/**
> + * Build a runnable power sequence from platform data, and add the resources
> + * it uses into ress. Memory for the sequence is allocated using devm_kzalloc
> + * on dev.
> + */
> +power_seq *power_seq_build(struct device *dev, power_seq_resources *ress,
> +			   platform_power_seq *pseq);

I already mentioned this above: I fail to see why the ress parameter is
needed here. It is an internal implementation detail of the power
sequence code. Maybe a better place would be to include it within the
struct power_seq.

> +/**
> + * Free all the resources previously allocated by power_seq_allocate_resources.
> + */
> +void power_seq_free_resources(power_seq_resources *ress);
> +
> +/**
> + * Run the given power sequence. Returns 0 on success, error code in case of
> + * failure.
> + */
> +int power_seq_run(struct device *dev, power_seq *seq);

I think the API is too fine grained here. From a user's point of view,
I'd expect a sequence like this:

	seq = power_seq_build(dev, sequence);
	...
	power_seq_run(seq);
	...
	power_seq_free(seq);

Perhaps with managed variants where the power_seq_free() is executed
automatically:

	seq = devm_power_seq_build(dev, sequence);
	...
	power_seq_run(seq);

Generally I really like where this is going.

Thierry
Rob Herring July 30, 2012, 3:44 p.m. UTC | #7
On 07/27/2012 07:05 AM, Alexandre Courbot wrote:
> Some device drivers (panel backlights especially) need to follow precise
> sequences for powering on and off, involving gpios, regulators, PWMs
> with a precise powering order and delays to respect between each steps.
> These sequences are board-specific, and do not belong to a particular
> driver - therefore they have been performed by board-specific hook
> functions to far.
> 
> With the advent of the device tree and of ARM kernels that are not
> board-tied, we cannot rely on these board-specific hooks anymore but
> need a way to implement these sequences in a portable manner. This patch
> introduces a simple interpreter that can execute such power sequences
> encoded either as platform data or within the device tree.
> 

Why not? We'll always have some amount of board code. The key is to
limit parts that are just data. I'm not sure this is something that
should be in devicetree.

Perhaps what is needed is a better way to hook into the driver like
notifiers?

> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
> ---
>  Documentation/power/power_seq.txt | 120 +++++++++++++++
>  drivers/base/Kconfig              |   4 +
>  drivers/base/Makefile             |   1 +
>  drivers/base/power_seq.c          | 300 ++++++++++++++++++++++++++++++++++++++
>  include/linux/power_seq.h         | 139 ++++++++++++++++++
>  5 files changed, 564 insertions(+)
>  create mode 100644 Documentation/power/power_seq.txt
>  create mode 100644 drivers/base/power_seq.c
>  create mode 100644 include/linux/power_seq.h
> 
> diff --git a/Documentation/power/power_seq.txt b/Documentation/power/power_seq.txt
> new file mode 100644
> index 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

Bindings need to documented in Documentation/devicetree

> +-----------
> +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;

What do this mean? Isn't this implied for a regulator?

> +				post-delay = <10>;
> +			};
> +			gpio@1 {
> +				id = "enable-gpio";
> +				enable;
> +			};
> +		};

This looks like you designed the platform_data structs first and then
came up with device nodes to mirror the struct.

Rob
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown July 30, 2012, 3:47 p.m. UTC | #8
On Mon, Jul 30, 2012 at 10:44:29AM -0500, Rob Herring wrote:
> On 07/27/2012 07:05 AM, Alexandre Courbot wrote:

> > +		power-on-sequence {
> > +			regulator@0 {
> > +				id = "power";
> > +				enable;

> What do this mean? Isn't this implied for a regulator?

I assume you might have some sequences which need some things to be
turned off for some reason; it at least seems to be something you'd want
to design for.

> This looks like you designed the platform_data structs first and then
> came up with device nodes to mirror the struct.

Judging by most of the DT I review this seems idiomatic :)
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rafael Wysocki July 30, 2012, 8:59 p.m. UTC | #9
On Monday, July 30, 2012, Anton Vorontsov wrote:
> On Mon, Jul 30, 2012 at 10:51:42AM +0900, Alex Courbot wrote:
> [...]
> > On the other hand I have just noticed that the apparently unrelated
> > Adaptive Voltage Scaling driver just appeared in drivers/power/avs.
> > So if Anton and David are ok with this, maybe I could put the power
> > sequences code in its own subdirectory within drivers/power.
> 
> Well, currently drivers/power/ is indeed just for power supply class
> subsystem and drivers. But if the trend is to gather power management
> ("policy") stuff under one directory, i.e.
> 
> drivers/
>   power/
>     supplies/    <- former "power supply class and drivers"
>     regulators/
>     idle/
>     cpuidle/
>     cpufreq/
>     devfreq/
>     avs/
>     ...
> 
> That would probably make sense, we could easily see the big picture.
> But if we're not going to do this long-term,

Yes, we may do this eventually, but surely not right now.

Thanks,
Rafael
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Stephen Warren July 30, 2012, 10:26 p.m. UTC | #10
On 07/30/2012 09:44 AM, Rob Herring wrote:
> On 07/27/2012 07:05 AM, Alexandre Courbot wrote:
>> Some device drivers (panel backlights especially) need to follow precise
>> sequences for powering on and off, involving gpios, regulators, PWMs
>> with a precise powering order and delays to respect between each steps.
>> These sequences are board-specific, and do not belong to a particular
>> driver - therefore they have been performed by board-specific hook
>> functions to far.
>>
>> With the advent of the device tree and of ARM kernels that are not
>> board-tied, we cannot rely on these board-specific hooks anymore but
>> need a way to implement these sequences in a portable manner. This patch
>> introduces a simple interpreter that can execute such power sequences
>> encoded either as platform data or within the device tree.
>>
> 
> Why not? We'll always have some amount of board code. The key is to
> limit parts that are just data. I'm not sure this is something that
> should be in devicetree.
> 
> Perhaps what is needed is a better way to hook into the driver like
> notifiers?

I would answer that by asking the reverse question - why should we have
to put some data in DT, and some data into board files still?

I'd certainly argue that the sequence of which GPIOs/regulators/PWMs to
manipulate is just data.

To be honest, if we're going to have to put some parts of a board's
configuration into board files anyway, then the entirety of DT seems
useless; I'd far rather see all the configuration in one cohesive place
than arbitrarily split into two/n different locations - that would make
everything harder to maintain.
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Stephen Warren July 30, 2012, 10:45 p.m. UTC | #11
On 07/27/2012 06:05 AM, Alexandre Courbot wrote:
> Some device drivers (panel backlights especially) need to follow precise
> sequences for powering on and off, involving gpios, regulators, PWMs
> with a precise powering order and delays to respect between each steps.
> These sequences are board-specific, and do not belong to a particular
> driver - therefore they have been performed by board-specific hook
> functions to far.

> diff --git a/Documentation/power/power_seq.txt b/Documentation/power/power_seq.txt

> +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,

At the highest level, i.e. what's being describe here, I wouldn't even
talk about enable/disable, but rather the action to perform on the
resource. The set of legal actions may be specific to the type of
resource in question. Admittedly enable/disable are common though.

> +- Delay to wait before performing the action,
> +- Delay to wait after performing the action.

I don't see a need to have a delay both before and after an action;
except at the start of the sequence, step n's post-delay is at the same
point in the sequence as step n+1's pre-delay. Perhaps make a "delay"
step type?

> +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

Rather than jumping straight into platform data here, I'd expect an
enumeration of legal resource types, and what actions can be performed
on each, followed by a description of a sequence (very simply, just a
list of actions and their parameters). This could be followed by a
section describing the mapping of the abstract concepts to concrete
platform data representation (and concrete device tree representation).

> +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.

I'd certainly suggest having a step count rather than a sentinel value
in the list.

> Regulator and PWM resources are identified by name. GPIO are
> +identified by number.

That's a little implementation-specific. I guess it's entirely true for
a platform data representation, but not when mapping this into device tree.

> +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.

If the result is devm-allocated, the function probably should be named
devm_power_seq_build().

I wonder if using the same structure/array as input and output would
simplify the API; the platform data would fill in the fields mentioned
above, and power_seq_build() would parse those, then set other fields in
the same structs to the looked-up handle values?

> +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);

You can make a custom devm free routine for the power_seq_resources
itself, so the overall free'ing of the content can be triggered by devm,
but the free'ing function can then call whatever non-devm APIs it wants
for the non-devm-allocated members.

> +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 {

As Thierry mentioned, the step nodes should be named for the type of
object they are (a "step") not the type or name of resource they act
upon ("regulator" or "gpio").

If the nodes have a unit address (i.e. end in "@n"), which they will
have to if all named "step" and there's more than one of them, then they
will need a matching reg property. Equally, the parent node will need
#address-cells and #size-cells too. So, the last couple lines would be:

		power-on-sequence {
			#address-cells = <1>;
			#size-cells = <0>;
			step@0 {
				reg = <0>;

> +				id = "power";

"id" is usually a name or identifier. I think you mean "type" or perhaps
"action" here:

				type = "regulator";
				action = "enable";

or:

				action = "enable-regulator";

I wish we had integer constants in DT so we didn't have to do all this
with strings. Sigh.

> +				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.

Oh I see. That's a little confusing. Why not just reference the relevant
resources directly in each step; something more like:

		gpio@1 {
			action = "enable-gpio";
			gpio = <&gpio 1 0>;
		};

I guess that might make parsing/building a little harder, since you'd
have to detect when you'd already done gpio_request() on a given GPIO
and not repeat it or something like that, but to me this makes the DT a
lot easier to comprehend.
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alexandre Courbot July 31, 2012, 8:37 a.m. UTC | #12
Hi Simon,

On 07/30/2012 08:00 PM, Simon Glass wrote:
> For the delay, I think milliseconds is reasonable. I suppose there is
> no reasonable need for microseconds?

I don't see any need for microseconds myself - anybody sees use for 
finer-grained delays?

Btw, I noticed I was using mdelay instead of msleep - caught and fixed that.

>> +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";
>
> Is there a reason not to put the phandle here, like:
>
>                                     id = <&mydevice_reg>;
>
> (or maybe 'device' instead of id?)

There is one reason, but it might be a bad one. On Tegra, PWM phandle 
uses an extra cell to encode the duty-cycle the PWM should have when we 
call get_pwm(). This makes it possible to address the same PWM with 
different phandles (and different duty cycles), which causes an issue to 
know whether a PWM is already used in a sequence (potentially resulting 
in multiple get_pwm calls on the same PWM, and also opens the door to 
ambiguities in behavior (what is the correct duty-cycle to use if 
several different values are passed?)

Maybe the problem lies in how PWM phandles are handled - if duty-cycle 
was not part of the information, we would not have this problem.

>> +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.
>
> For the regulator and gpio types I think you only have an enable. For
> the pwm, what is the intended binding? Is that documented elsewhere?

Same thing, enable/disable which would call pwm_enable and pwm_disable. 
One could also image an additional property to set the duty cycle if it 
can be taken off the phandle.

> Also it might be worth mentioning how you get a struct power_seq from
> an fdt node, and perhaps given an example of a device which has an
> attached node, so we can see how it is referenced from the device
> (of_parse_power_seq I think). Do put the sequence inside the device
> node or reference it with a phandle?

Yes, this definitely needs more documentation - especially the DT part.

Thanks,
Alex.

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thierry Reding July 31, 2012, 9:13 a.m. UTC | #13
On Tue, Jul 31, 2012 at 05:37:07PM +0900, Alex Courbot wrote:
> Hi Simon,
> 
> On 07/30/2012 08:00 PM, Simon Glass wrote:
> >For the delay, I think milliseconds is reasonable. I suppose there is
> >no reasonable need for microseconds?
> 
> I don't see any need for microseconds myself - anybody sees use for
> finer-grained delays?
> 
> Btw, I noticed I was using mdelay instead of msleep - caught and fixed that.

You might want to take a look at Documentation/timers/timers-howto.txt.
msleep() isn't very accurate for periods shorter than 20 ms.

> >>+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";
> >
> >Is there a reason not to put the phandle here, like:
> >
> >                                    id = <&mydevice_reg>;
> >
> >(or maybe 'device' instead of id?)
> 
> There is one reason, but it might be a bad one. On Tegra, PWM
> phandle uses an extra cell to encode the duty-cycle the PWM should
> have when we call get_pwm().

This is not only the case on Tegra, but it is the default unless a
driver specifically overrides it. The second cell specifies the index of
the PWM device within the PWM chip. The third cell doesn't specify the
duty cycle but the period of the PWM.

> This makes it possible to address the
> same PWM with different phandles (and different duty cycles),

How so? A phandle will always refer to a PWM chip. Paired with the
second cell, of_pwm_request() will resolve that into the correct PWM
device.

> which
> causes an issue to know whether a PWM is already used in a sequence
> (potentially resulting in multiple get_pwm calls on the same PWM,
> and also opens the door to ambiguities in behavior (what is the
> correct duty-cycle to use if several different values are passed?)

You can't request a PWM multiple times. The second call well return
-EBUSY, or rather ERR_PTR(-EBUSY).

Thierry
Thierry Reding July 31, 2012, 9:16 a.m. UTC | #14
On Mon, Jul 30, 2012 at 04:47:06PM +0100, Mark Brown wrote:
> On Mon, Jul 30, 2012 at 10:44:29AM -0500, Rob Herring wrote:
> > On 07/27/2012 07:05 AM, Alexandre Courbot wrote:
> 
> > > +		power-on-sequence {
> > > +			regulator@0 {
> > > +				id = "power";
> > > +				enable;
> 
> > What do this mean? Isn't this implied for a regulator?
> 
> I assume you might have some sequences which need some things to be
> turned off for some reason; it at least seems to be something you'd want
> to design for.

Furthermore there is the power-off-sequence equivalent, which you use
for instance when you turn off the panel. Typically they would do the
inverse of the power-on-sequence, so turning off a regulator is
definitiely required.

Thierry
Alexandre Courbot July 31, 2012, 9:51 a.m. UTC | #15
On 07/30/2012 08:33 PM, Thierry Reding wrote:
>> +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.
>
> I don't quite understand why the struct power_seq_resources is needed.
> Can this not be stored within power_seq?

power_seq_resources serves two purposes:
1) When parsing sequences, it keeps track of the resources we have 
already allocated to avoid getting the same resource twice
2) On cleanup, it cleans the resources that needs to be freed (i.e. 
those that are not devm-handled).

2) can certainly be removed either by enforcing use of devm, or by doing 
reference counting. 1) seems more difficult to avoid - we need to keep 
track of the resources we already own between calls to 
power_seq_build(). I'd certainly be glad to remove that structure from 
public view and simplify the code if that is possible though.

>> +
>> +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);
>
> Why is the struct device required here? It already is passed during the
> call to pwm_seq_build(), so perhaps you should keep a reference to it
> within struct power_seq?

The device is only needed for printing error messages. But as you point 
later, maybe messages should not be printed there at all. I will try to 
remove that parameter.

>> +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);
>
> Could this not also be handled by a managed version? If a power_seq is
> always managed, then I would assume that it also takes care of freeing
> the resources, even if the resources have no managed equivalents.

Right.

> Perhaps it would also make sense to provide non-managed version of these
> functions. I think that would make the managed versions easier and more
> canonical to implement.

A power_seq is a single block of memory, so that should be reasonnably 
doable indeed. Let me think a little bit more about that.

>> +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.
>
> I think there has been quite some discussion regarding the naming of
> subnodes and the conclusion seems to have been to name them uniformly
> after what they represent. As such the power-on-sequence subnodes should
> be called step@0, step@1, etc. However, that will require the addition
> of a property to define the type of resource.

That's fine I guess - just adds some footprint to the DT, but nothing crazy.

> Also, is there some way we can make the id property for GPIOs not
> require the -gpio suffix? If the resource type is already GPIO, then it
> seems redundant to add -gpio to the ID.

There is unfortunately an inconsistency between the way regulators and 
GPIOs are gotten by name. regulator_get(id) will expect to find a 
property named "id-supply", while gpio_request_one(id) expects a 
property named exactly "id". To workaround this we could sprintf the 
correct property name from a non-suffixed property name within the 
driver, but I think this actually speaks more in favor of having 
phandles directly into the sequences.

>> +config POWER_SEQ
>> +     bool
>> +     default n
>> +
>
> "default n" is already the default, so you can drop that line.

Did that, thanks.

>> +#ifdef CONFIG_OF
>> +#include <linux/of.h>
>> +#include <linux/of_gpio.h>
>> +#endif
>
> I think you don't need the CONFIG_OF guard around these. Both of.h and
> of_gpio.h can be included unconditionally and actually contain dummy
> definitions for the public functions in the !OF case.

Fixed, thanks.

>> +static int power_seq_step_run(struct power_seq_step *step)
>> +{
>> +     int err = 0;
>> +
>> +     if (step->params.pre_delay)
>> +             mdelay(step->params.pre_delay);
>> +
>> +     switch (step->resource->type) {
>> +#ifdef CONFIG_REGULATOR
>> +     case POWER_SEQ_REGULATOR:
>> +             if (step->params.enable)
>> +                     err = regulator_enable(step->resource->regulator);
>> +             else
>> +                     err = regulator_disable(step->resource->regulator);
>> +             break;
>> +#endif
>> +#ifdef CONFIG_PWM
>> +     case POWER_SEQ_PWM:
>> +             if (step->params.enable)
>> +                     err = pwm_enable(step->resource->pwm);
>> +             else
>> +                     pwm_disable(step->resource->pwm);
>> +             break;
>> +#endif
>> +#ifdef CONFIG_GPIOLIB
>> +     case POWER_SEQ_GPIO:
>> +             gpio_set_value_cansleep(step->resource->gpio,
>> +                                     step->params.enable);
>> +             break;
>> +#endif
>
> This kind of #ifdef'ery is quite ugly. I don't know if adding separate
> *_run() functions for each type of resource would be any better, though.
> Alternatively, maybe POWER_SEQ should depend on the REGULATOR, PWM and
> GPIOLIB symbols to side-step the issue completely?

If it is not realistic to consider a kernel built without regulator, pwm 
or gpiolib support, then we might as well do that. But isn't that a 
possibility?

>> +     if (!seq) return 0;
>
> I don't think this is acceptable according to the coding style. Also,
> perhaps returning -EINVAL would be more meaningful?

I neglected running checkpatch before submitting, apologies for that. 
The return value seems correct to me, a NULL sequence has no effect.

>> +
>> +     while (seq->resource) {
>
> Perhaps this should check for POWER_SEQ_STOP instead?

There is no resource for POWER_SEQ_STOP - therefore, a NULL resource is 
used instead.

>> +             if ((err = power_seq_step_run(seq++))) {
>> +                     dev_err(dev, "error %d while running power sequence!\n",
>> +                             err);
>
> For this kind of diagnostics it could be useful to have a name
> associated with the power sequence. But I'm not sure that making the
> power sequence code output an error here is the best solution. I find it
> to be annoying when core code starts outputting too many error codes. In
> this case it's particularily easy to catch the errors in the caller.

Giving names to power sequences sounds like a good idea. Let me see how 
this can be done. It might require some more data structuring.

>> +
>> +     while ((child = of_get_next_child(node, child)))
>> +             cpt++;
>
> for_each_child_of_node()?
>
>> +
>> +     /* allocate one more step to signal end of sequence */
>> +     ret = devm_kzalloc(dev, sizeof(*ret) * (cpt + 1), GFP_KERNEL);
>> +     if (!ret)
>> +             return ERR_PTR(-ENOMEM);
>> +
>> +     cpt = 0;
>> +     while ((child = of_get_next_child(node, child))) {
>
> Here as well.

Ah, didn't know that. Thanks.

>> +     /* first pass to count the number of steps to allocate */
>> +     for (cpt = 0; pseq[cpt].type != POWER_SEQ_STOP; cpt++);
>
> Wouldn't it be easier to pass around the number of steps in the sequence
> instead of having to count in various places? This would be more along
> the lines of how struct platform_device defines associated resources.

My goal was to limit the number of data structures, but if we add a name 
to power sequences, we can add a steps count as well.

>> +
>> +     if (!cpt)
>> +             return seq;
>
> Perhaps this should return an error-code as well? I find it nice to not
> have to handle NULL specially when using ERR_PTR et al.

Agreed.


>> +typedef enum {
>> +     POWER_SEQ_STOP = 0,
>> +     POWER_SEQ_REGULATOR,
>> +     POWER_SEQ_PWM,
>> +     POWER_SEQ_GPIO,
>> +     POWER_SEQ_MAX,
>> +} power_res_type;
>
> Maybe the prefix power_seq should be used here as well, so:
> power_seq_res_type.

Definitely.

>> +typedef struct list_head power_seq_resources;
>
> No type definitions like this, please. Also, why define this particular
> type globally?

I will move that into a proper structure with a name and number of steps.

>> +
>> +struct power_step_params {
>> +     /* enable the resource if 1, disable if 0 */
>> +     bool enable;
>> +     /* delay (in ms) to wait before executing the step */
>> +     int  pre_delay;
>> +     /* delay (in ms) to wait after executing the step */
>> +     int post_delay;
>
> unsigned int for the delays?

Yup.

>> +typedef struct platform_power_seq_step platform_power_seq;
>
> Why are the parameters kept in a separate structure? What are the
> disadvantages of keeping the in the sequence step structure directly?

This ensures the same parameters are used for the platform data and 
resolved sequences, and also ensures they are all copied correctly using 
memcpy. But maybe I am just making something complex out of something 
that ought to be simpler.

>> +struct power_seq_step {
>> +     struct power_seq_resource *resource;
>> +     struct power_step_params params;
>> +};
>> +typedef struct power_seq_step power_seq;
>
> Would it make sense to make the struct power_seq opaque? I don't see why
> anyone but the power_seq code should access the internals.

I would like to do that actually. The issue is that it did not work go 
well with the legacy pwm_backlight behavior: a power sequence needs to 
be constructed out of a PWM obtained through pwm_request(int pwm_id, 
char *label) and this behavior cannot be emulated using the new platform 
data interface (which only works with pwm_get()). But if I remove this 
old behavior, then I could make power_seq opaque. I don't think many 
drivers are using it. What do you think?

> For resource
> managing it might also be easier to separate struct power_seq_step and
> struct power_seq, making the power_seq basically something like:
>
>          struct power_seq {
>                  struct power_seq_step *steps;
>                  unsigned int num_steps;
>          };
>
> Perhaps a name field can be included for diagnostic purposes.

Yes, looks like we are going in that direction. If this can be made 
private then the number of public data structures will not be too 
confusing (platform data only, basically).

>> +power_seq *power_seq_build(struct device *dev, power_seq_resources *ress,
>> +                        platform_power_seq *pseq);
>
> I already mentioned this above: I fail to see why the ress parameter is
> needed here. It is an internal implementation detail of the power
> sequence code. Maybe a better place would be to include it within the
> struct power_seq.

Problem is that I need to track which resources are already allocated 
between calls to power_seq_build(). Even if I attach the resources into 
struct power_seq, they won't be attainable by the next call. So I'm 
afraid we are bound to pass a tracking structure at least to 
power_seq_build.

>> +/**
>> + * Free all the resources previously allocated by power_seq_allocate_resources.
>> + */
>> +void power_seq_free_resources(power_seq_resources *ress);
>> +
>> +/**
>> + * Run the given power sequence. Returns 0 on success, error code in case of
>> + * failure.
>> + */
>> +int power_seq_run(struct device *dev, power_seq *seq);
>
> I think the API is too fine grained here. From a user's point of view,
> I'd expect a sequence like this:
>
>          seq = power_seq_build(dev, sequence);
>          ...
>          power_seq_run(seq);
>          ...
>          power_seq_free(seq);
>
> Perhaps with managed variants where the power_seq_free() is executed
> automatically:
>
>          seq = devm_power_seq_build(dev, sequence);
>          ...
>          power_seq_run(seq);

I agree. On top of that, of_parse_power_seq() should directly return a 
resolved power sequence, not the platform data.

> Generally I really like where this is going.

Thanks - I really appreciate your review.

Alex.

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alexandre Courbot July 31, 2012, 10:11 a.m. UTC | #16
On 07/31/2012 06:13 PM, Thierry Reding wrote:
>> I don't see any need for microseconds myself - anybody sees use for
>> finer-grained delays?
>>
>> Btw, I noticed I was using mdelay instead of msleep - caught and fixed that.
>
> You might want to take a look at Documentation/timers/timers-howto.txt.
> msleep() isn't very accurate for periods shorter than 20 ms.

Ok, looks like usleep_range is the way to go here. In that case it would 
probably not hurt to specify delays in microseconds in the DT and 
platform data as well.

>>>> +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";
>>>
>>> Is there a reason not to put the phandle here, like:
>>>
>>>                                     id = <&mydevice_reg>;
>>>
>>> (or maybe 'device' instead of id?)
>>
>> There is one reason, but it might be a bad one. On Tegra, PWM
>> phandle uses an extra cell to encode the duty-cycle the PWM should
>> have when we call get_pwm().
>
> This is not only the case on Tegra, but it is the default unless a
> driver specifically overrides it. The second cell specifies the index of
> the PWM device within the PWM chip.  The third cell doesn't specify the
> duty cycle but the period of the PWM.

Then I think there is a mistake in 
Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt:

"the second cell is the duty cycle in nanoseconds."

>> This makes it possible to address the
>> same PWM with different phandles (and different duty cycles),
>
> How so? A phandle will always refer to a PWM chip. Paired with the
> second cell, of_pwm_request() will resolve that into the correct PWM
> device.

For tegra, we can only address PWMs this way IIRC:

pwm = <&pwm 2 5000000>;

If we had <&pwm 2>, I agree that there would be no problem. But here the 
period of the PWM is also given - and in practice, we can request the 
same PWM using different phandles. For instance, if the above property 
was part of the power-on sequence, and the following

pwm = <&pwm 2 0>;

was part of power-off, how can I know that these two different phandles 
refer to the same PWM without calling pwm_get a second time and getting 
-EBUSY?

Of course if the same period is specified for both, I will not have this 
issue as the phandles will be identical, but the possibility remains 
open that we are given a faulty tree here.

More generally speaking, wouldn't it make more sense to have the 
period/duty cycle of a PWM encoded into separate properties when needed 
and have the phandle just reference the PWM instance? This also seems to 
stand from an API point of view, since the period is not specified when 
invoking pwm_request or pwm_get, but set by its own pwm_set_period function?

On an unrelated note, I also don't understand why the period is also a 
parameter of pwm_config and why pwm_set_period does not do anything 
beyond setting a struct member that is returned by pwm_get_period (but 
maybe I am missing something here).

Alex.

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alexandre Courbot July 31, 2012, 10:15 a.m. UTC | #17
On 07/31/2012 07:26 AM, Stephen Warren wrote:
> On 07/30/2012 09:44 AM, Rob Herring wrote:
>> On 07/27/2012 07:05 AM, Alexandre Courbot wrote:
>>> Some device drivers (panel backlights especially) need to follow precise
>>> sequences for powering on and off, involving gpios, regulators, PWMs
>>> with a precise powering order and delays to respect between each steps.
>>> These sequences are board-specific, and do not belong to a particular
>>> driver - therefore they have been performed by board-specific hook
>>> functions to far.
>>>
>>> With the advent of the device tree and of ARM kernels that are not
>>> board-tied, we cannot rely on these board-specific hooks anymore but
>>> need a way to implement these sequences in a portable manner. This patch
>>> introduces a simple interpreter that can execute such power sequences
>>> encoded either as platform data or within the device tree.
>>>
>>
>> Why not? We'll always have some amount of board code. The key is to
>> limit parts that are just data. I'm not sure this is something that
>> should be in devicetree.
>>
>> Perhaps what is needed is a better way to hook into the driver like
>> notifiers?
>
> I would answer that by asking the reverse question - why should we have
> to put some data in DT, and some data into board files still?
>
> I'd certainly argue that the sequence of which GPIOs/regulators/PWMs to
> manipulate is just data.
>
> To be honest, if we're going to have to put some parts of a board's
> configuration into board files anyway, then the entirety of DT seems
> useless; I'd far rather see all the configuration in one cohesive place
> than arbitrarily split into two/n different locations - that would make
> everything harder to maintain.

Also, having these sequences into the DT would allow an older kernel to 
boot on and correctly initialize a newer board with - which is also part 
of the DT's purpose if I am not mistaken.

Alex.

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thierry Reding July 31, 2012, 10:19 a.m. UTC | #18
On Tue, Jul 31, 2012 at 06:51:03PM +0900, Alex Courbot wrote:
> On 07/30/2012 08:33 PM, Thierry Reding wrote:
> >>+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.
> >
> >I don't quite understand why the struct power_seq_resources is needed.
> >Can this not be stored within power_seq?
> 
> power_seq_resources serves two purposes:
> 1) When parsing sequences, it keeps track of the resources we have
> already allocated to avoid getting the same resource twice
> 2) On cleanup, it cleans the resources that needs to be freed (i.e.
> those that are not devm-handled).
> 
> 2) can certainly be removed either by enforcing use of devm, or by
> doing reference counting. 1) seems more difficult to avoid - we need
> to keep track of the resources we already own between calls to
> power_seq_build(). I'd certainly be glad to remove that structure
> from public view and simplify the code if that is possible though.

I still don't see the problem. Managing the resources should be part of
the power_seq core and shouldn't be visible to users. Maybe what you are
worried about is that you may need the same resource both for a power-up
and a power-down sequence? I can see how that would require a global
list of resources.

However I still think it would be easier to encapsulate that completely.
Maybe another level of abstraction is required. You could for example
add another type to encapsulate several power sequences and that could
keep a list of used resources. I can't think of a good name, but maybe
the following DT snippet clarifies what I mean:

	power-sequences {
		#address-cells = <1>;
		#size-cells = <0>;

		sequence@0 {
			name = "up";

			#address-cells = <1>;
			#size-cells = <0>;

			step@0 {
				...
			};

			...
		};

		sequence@1 {
			name = "down";

			#address-cells = <1>;
			#size-cells = <0>;

			step@0 {
				...
			};

			...
		};
	};

If you add a name property like this, you could extend the API to
support running a named sequence:

	power_seq_run(seq, "up");
	...
	power_seq_run(seq, "down);

> >Also, is there some way we can make the id property for GPIOs not
> >require the -gpio suffix? If the resource type is already GPIO, then it
> >seems redundant to add -gpio to the ID.
> 
> There is unfortunately an inconsistency between the way regulators
> and GPIOs are gotten by name. regulator_get(id) will expect to find
> a property named "id-supply", while gpio_request_one(id) expects a
> property named exactly "id". To workaround this we could sprintf the
> correct property name from a non-suffixed property name within the
> driver, but I think this actually speaks more in favor of having
> phandles directly into the sequences.

Yes, if it can be made to work by specifying the phandle directly that
is certainly better.

> >>+static int power_seq_step_run(struct power_seq_step *step)
> >>+{
> >>+     int err = 0;
> >>+
> >>+     if (step->params.pre_delay)
> >>+             mdelay(step->params.pre_delay);
> >>+
> >>+     switch (step->resource->type) {
> >>+#ifdef CONFIG_REGULATOR
> >>+     case POWER_SEQ_REGULATOR:
> >>+             if (step->params.enable)
> >>+                     err = regulator_enable(step->resource->regulator);
> >>+             else
> >>+                     err = regulator_disable(step->resource->regulator);
> >>+             break;
> >>+#endif
> >>+#ifdef CONFIG_PWM
> >>+     case POWER_SEQ_PWM:
> >>+             if (step->params.enable)
> >>+                     err = pwm_enable(step->resource->pwm);
> >>+             else
> >>+                     pwm_disable(step->resource->pwm);
> >>+             break;
> >>+#endif
> >>+#ifdef CONFIG_GPIOLIB
> >>+     case POWER_SEQ_GPIO:
> >>+             gpio_set_value_cansleep(step->resource->gpio,
> >>+                                     step->params.enable);
> >>+             break;
> >>+#endif
> >
> >This kind of #ifdef'ery is quite ugly. I don't know if adding separate
> >*_run() functions for each type of resource would be any better, though.
> >Alternatively, maybe POWER_SEQ should depend on the REGULATOR, PWM and
> >GPIOLIB symbols to side-step the issue completely?
> 
> If it is not realistic to consider a kernel built without regulator,
> pwm or gpiolib support, then we might as well do that. But isn't
> that a possibility?

I'd say that anything complex enough to make use of power-sequencing
probably has all of these enabled anyway. But maybe I'm not very
qualified to judge.

> 
> >>+     if (!seq) return 0;
> >
> >I don't think this is acceptable according to the coding style. Also,
> >perhaps returning -EINVAL would be more meaningful?
> 
> I neglected running checkpatch before submitting, apologies for
> that. The return value seems correct to me, a NULL sequence has no
> effect.

But seq == NULL should never happen anyway, right?

> 
> >>+
> >>+     while (seq->resource) {
> >
> >Perhaps this should check for POWER_SEQ_STOP instead?
> 
> There is no resource for POWER_SEQ_STOP - therefore, a NULL resource
> is used instead.

Still, you use POWER_SEQ_STOP as an explicit sentinel to mark the end of
a sequence, so intuitively I'd be looking for that as a stop condition.

> >>+typedef struct platform_power_seq_step platform_power_seq;
> >
> >Why are the parameters kept in a separate structure? What are the
> >disadvantages of keeping the in the sequence step structure directly?
> 
> This ensures the same parameters are used for the platform data and
> resolved sequences, and also ensures they are all copied correctly
> using memcpy. But maybe I am just making something complex out of
> something that ought to be simpler.
> 
> >>+struct power_seq_step {
> >>+     struct power_seq_resource *resource;
> >>+     struct power_step_params params;
> >>+};
> >>+typedef struct power_seq_step power_seq;
> >
> >Would it make sense to make the struct power_seq opaque? I don't see why
> >anyone but the power_seq code should access the internals.
> 
> I would like to do that actually. The issue is that it did not work
> go well with the legacy pwm_backlight behavior: a power sequence
> needs to be constructed out of a PWM obtained through
> pwm_request(int pwm_id, char *label) and this behavior cannot be
> emulated using the new platform data interface (which only works
> with pwm_get()). But if I remove this old behavior, then I could
> make power_seq opaque. I don't think many drivers are using it. What
> do you think?

I don't see how that is relevant here, since this power-sequencing code
is supposed to be generic and not tied to any specific implementation.
Can you explain further?

In any case you shouldn't be using pwm_request() in new code.

> >For resource
> >managing it might also be easier to separate struct power_seq_step and
> >struct power_seq, making the power_seq basically something like:
> >
> >         struct power_seq {
> >                 struct power_seq_step *steps;
> >                 unsigned int num_steps;
> >         };
> >
> >Perhaps a name field can be included for diagnostic purposes.
> 
> Yes, looks like we are going in that direction. If this can be made
> private then the number of public data structures will not be too
> confusing (platform data only, basically).

Yes, that sounds like a much cleaner approach.

> 
> >>+power_seq *power_seq_build(struct device *dev, power_seq_resources *ress,
> >>+                        platform_power_seq *pseq);
> >
> >I already mentioned this above: I fail to see why the ress parameter is
> >needed here. It is an internal implementation detail of the power
> >sequence code. Maybe a better place would be to include it within the
> >struct power_seq.
> 
> Problem is that I need to track which resources are already
> allocated between calls to power_seq_build(). Even if I attach the
> resources into struct power_seq, they won't be attainable by the
> next call. So I'm afraid we are bound to pass a tracking structure
> at least to power_seq_build.

I think this could be solved nicely by what I proposed earlier.

> >>+/**
> >>+ * Free all the resources previously allocated by power_seq_allocate_resources.
> >>+ */
> >>+void power_seq_free_resources(power_seq_resources *ress);
> >>+
> >>+/**
> >>+ * Run the given power sequence. Returns 0 on success, error code in case of
> >>+ * failure.
> >>+ */
> >>+int power_seq_run(struct device *dev, power_seq *seq);
> >
> >I think the API is too fine grained here. From a user's point of view,
> >I'd expect a sequence like this:
> >
> >         seq = power_seq_build(dev, sequence);
> >         ...
> >         power_seq_run(seq);
> >         ...
> >         power_seq_free(seq);
> >
> >Perhaps with managed variants where the power_seq_free() is executed
> >automatically:
> >
> >         seq = devm_power_seq_build(dev, sequence);
> >         ...
> >         power_seq_run(seq);
> 
> I agree. On top of that, of_parse_power_seq() should directly return
> a resolved power sequence, not the platform data.

I'm not sure. The idiom seems to be to use DT as an alternative source
for platform data, which I guess is due to most drivers already using
platform data. But it has the advantage that after you have the platform
data, be it from DT or directly specified, the subsequent code remains
the same.

Of course you could provide a separate of_build_power_seq() that wraps
both steps for convenience.

Thierry
Alexandre Courbot July 31, 2012, 10:32 a.m. UTC | #19
On 07/31/2012 07:45 AM, Stephen Warren wrote:
>> +- Delay to wait before performing the action,
>> +- Delay to wait after performing the action.
>
> I don't see a need to have a delay both before and after an action;
> except at the start of the sequence, step n's post-delay is at the same
> point in the sequence as step n+1's pre-delay. Perhaps make a "delay"
> step type?

My first version used this actually - and you're right, having a "delay" 
step type would be more flexible and less redundant.

>> +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
>
> Rather than jumping straight into platform data here, I'd expect an
> enumeration of legal resource types, and what actions can be performed
> on each, followed by a description of a sequence (very simply, just a
> list of actions and their parameters). This could be followed by a
> section describing the mapping of the abstract concepts to concrete
> platform data representation (and concrete device tree representation).

Keeping that in mind for the next revision.

>> +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.
>
> I'd certainly suggest having a step count rather than a sentinel value
> in the list.

As Thierry did - I think I will go that way.

>> Regulator and PWM resources are identified by name. GPIO are
>> +identified by number.
>
> That's a little implementation-specific. I guess it's entirely true for
> a platform data representation, but not when mapping this into device tree.

If we can come with a way to properly use phandles within DT sequences 
(and we should), then this will only apply to platform data.

>> +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.
>
> If the result is devm-allocated, the function probably should be named
> devm_power_seq_build().

Right - more generally this needs to have both devm and non-devm variants.

> I wonder if using the same structure/array as input and output would
> simplify the API; the platform data would fill in the fields mentioned
> above, and power_seq_build() would parse those, then set other fields in
> the same structs to the looked-up handle values?

The thing is that I am not sure what happens to the platform data once 
probe() is done. Isn't it customary to mark it with __devinit and have 
it freed after probing is successful?

More generally, I think it is a good practice to have data structures 
tailored right for what they need to do - code with members that are 
meaningful only at given points of an instance's life tends to be more 
confusing.

> You can make a custom devm free routine for the power_seq_resources
> itself, so the overall free'ing of the content can be triggered by devm,
> but the free'ing function can then call whatever non-devm APIs it wants
> for the non-devm-allocated members.

That sounds good.

>> +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 {
>
> As Thierry mentioned, the step nodes should be named for the type of
> object they are (a "step") not the type or name of resource they act
> upon ("regulator" or "gpio").

Will fix that.

> If the nodes have a unit address (i.e. end in "@n"), which they will
> have to if all named "step" and there's more than one of them, then they
> will need a matching reg property. Equally, the parent node will need
> #address-cells and #size-cells too. So, the last couple lines would be:
>
> 		power-on-sequence {
> 			#address-cells = <1>;
> 			#size-cells = <0>;
> 			step@0 {
> 				reg = <0>;

That's precisely what I would like to avoid - I don't need the steps to 
be numbered and I certainly have no use for a reg property. Isn't there 
a way to make it simpler?

>> +				id = "power";
>
> "id" is usually a name or identifier. I think you mean "type" or perhaps
> "action" here:
>
> 				type = "regulator";
> 				action = "enable";
>
> or:
>
> 				action = "enable-regulator";

Right, that was a clear misuse.

> Oh I see. That's a little confusing. Why not just reference the relevant
> resources directly in each step; something more like:
>
> 		gpio@1 {
> 			action = "enable-gpio";
> 			gpio = <&gpio 1 0>;
> 		};
>
> I guess that might make parsing/building a little harder, since you'd
> have to detect when you'd already done gpio_request() on a given GPIO
> and not repeat it or something like that, but to me this makes the DT a
> lot easier to comprehend.

You can see my reply to Thierry for the reason - the only issue with 
that is caused by PWM phandles. If we overcome this, then I agree we 
should use phandles. The code should not even get more complex as I have 
to check whether a resource is already allocated with strings as well.

Thanks,
Alex.

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thierry Reding July 31, 2012, 10:46 a.m. UTC | #20
On Tue, Jul 31, 2012 at 07:11:41PM +0900, Alex Courbot wrote:
> On 07/31/2012 06:13 PM, Thierry Reding wrote:
> >>I don't see any need for microseconds myself - anybody sees use for
> >>finer-grained delays?
> >>
> >>Btw, I noticed I was using mdelay instead of msleep - caught and fixed that.
> >
> >You might want to take a look at Documentation/timers/timers-howto.txt.
> >msleep() isn't very accurate for periods shorter than 20 ms.
> 
> Ok, looks like usleep_range is the way to go here. In that case it
> would probably not hurt to specify delays in microseconds in the DT
> and platform data as well.


> 
> >>>>+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";
> >>>
> >>>Is there a reason not to put the phandle here, like:
> >>>
> >>>                                    id = <&mydevice_reg>;
> >>>
> >>>(or maybe 'device' instead of id?)
> >>
> >>There is one reason, but it might be a bad one. On Tegra, PWM
> >>phandle uses an extra cell to encode the duty-cycle the PWM should
> >>have when we call get_pwm().
> >
> >This is not only the case on Tegra, but it is the default unless a
> >driver specifically overrides it. The second cell specifies the index of
> >the PWM device within the PWM chip.  The third cell doesn't specify the
> >duty cycle but the period of the PWM.
> 
> Then I think there is a mistake in
> Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt:
> 
> "the second cell is the duty cycle in nanoseconds."

Yes, that's a mistake. =\

> >>This makes it possible to address the
> >>same PWM with different phandles (and different duty cycles),
> >
> >How so? A phandle will always refer to a PWM chip. Paired with the
> >second cell, of_pwm_request() will resolve that into the correct PWM
> >device.
> 
> For tegra, we can only address PWMs this way IIRC:
> 
> pwm = <&pwm 2 5000000>;
> 
> If we had <&pwm 2>, I agree that there would be no problem. But here
> the period of the PWM is also given - and in practice, we can
> request the same PWM using different phandles. For instance, if the
> above property was part of the power-on sequence, and the following
> 
> pwm = <&pwm 2 0>;
> 
> was part of power-off, how can I know that these two different
> phandles refer to the same PWM without calling pwm_get a second time
> and getting -EBUSY?

You should specify the same period regardless of the sequence. But you
are right, you still cannot request the device twice.

> Of course if the same period is specified for both, I will not have
> this issue as the phandles will be identical, but the possibility
> remains open that we are given a faulty tree here.

I think the phandle is in fact only the reference to the PWM chip, that
is: &pwm. The second cell, the PWM index, is part of the PWM specifier.

However the issue doesn't go away if you drop the period cell because
you still won't be able to request the PWM device a second time. How is
this solved for regulators and GPIOs? At least for GPIOs I'm pretty sure
that you can't request them more than once either.

> More generally speaking, wouldn't it make more sense to have the
> period/duty cycle of a PWM encoded into separate properties when
> needed and have the phandle just reference the PWM instance? This
> also seems to stand from an API point of view, since the period is
> not specified when invoking pwm_request or pwm_get, but set by its
> own pwm_set_period function?

The problem with specifying the period in a separate property is how to
map them to the correct PWM device. From a hardware description point of
view, making the period part of the specifier makes a lot of sense and
hardware description is what DT is about.

> On an unrelated note, I also don't understand why the period is also
> a parameter of pwm_config and why pwm_set_period does not do
> anything beyond setting a struct member that is returned by
> pwm_get_period (but maybe I am missing something here).

pwm_config() is the legacy API that we need to support for compatibility
reasons. Eventually this interface should probably be changed.
pwm_get_period() and pwm_set_period() were merely introduced to support
DT, but I could imagine them becoming the canonical way for configuring
PWM devices in the future, perhaps with a complementary
pwm_set_duty_cycle().

But first we need to convert drivers and users.

Thierry
Thierry Reding July 31, 2012, 10:56 a.m. UTC | #21
On Tue, Jul 31, 2012 at 07:32:20PM +0900, Alex Courbot wrote:
> On 07/31/2012 07:45 AM, Stephen Warren wrote:
> >I wonder if using the same structure/array as input and output would
> >simplify the API; the platform data would fill in the fields mentioned
> >above, and power_seq_build() would parse those, then set other fields in
> >the same structs to the looked-up handle values?
> 
> The thing is that I am not sure what happens to the platform data
> once probe() is done. Isn't it customary to mark it with __devinit
> and have it freed after probing is successful?

No, platform data should stay around forever. Otherwise, consider what
would happen if your driver is built as a module and you unload and load
it again.

> More generally, I think it is a good practice to have data
> structures tailored right for what they need to do - code with
> members that are meaningful only at given points of an instance's
> life tends to be more confusing.

I agree. Furthermore the driver unload/reload would be another reason
not to reuse platform data as the output of the build() function.

But maybe what Stephen meant was more like filling a structure with data
taken from the platform data and pass that to a resolve() function which
would fill in the missing pieces like pointers to actual resources. I
imagine a managed interface would become a little trickier to do using
such an approach.

> >If the nodes have a unit address (i.e. end in "@n"), which they will
> >have to if all named "step" and there's more than one of them, then they
> >will need a matching reg property. Equally, the parent node will need
> >#address-cells and #size-cells too. So, the last couple lines would be:
> >
> >		power-on-sequence {
> >			#address-cells = <1>;
> >			#size-cells = <0>;
> >			step@0 {
> >				reg = <0>;
> 
> That's precisely what I would like to avoid - I don't need the steps
> to be numbered and I certainly have no use for a reg property. Isn't
> there a way to make it simpler?

It's not technically valid to not have the reg property. Or
#address-cells and #size-cells properties for that matter.

Thierry
Mitch Bradley July 31, 2012, 12:22 p.m. UTC | #22
On 7/31/2012 6:56 PM, Thierry Reding wrote:
> On Tue, Jul 31, 2012 at 07:32:20PM +0900, Alex Courbot wrote:
>> On 07/31/2012 07:45 AM, Stephen Warren wrote:
>>> I wonder if using the same structure/array as input and output would
>>> simplify the API; the platform data would fill in the fields mentioned
>>> above, and power_seq_build() would parse those, then set other fields in
>>> the same structs to the looked-up handle values?
>>
>> The thing is that I am not sure what happens to the platform data
>> once probe() is done. Isn't it customary to mark it with __devinit
>> and have it freed after probing is successful?
> 
> No, platform data should stay around forever. Otherwise, consider what
> would happen if your driver is built as a module and you unload and load
> it again.
> 
>> More generally, I think it is a good practice to have data
>> structures tailored right for what they need to do - code with
>> members that are meaningful only at given points of an instance's
>> life tends to be more confusing.
> 
> I agree. Furthermore the driver unload/reload would be another reason
> not to reuse platform data as the output of the build() function.
> 
> But maybe what Stephen meant was more like filling a structure with data
> taken from the platform data and pass that to a resolve() function which
> would fill in the missing pieces like pointers to actual resources. I
> imagine a managed interface would become a little trickier to do using
> such an approach.
> 
>>> If the nodes have a unit address (i.e. end in "@n"), which they will
>>> have to if all named "step" and there's more than one of them, then they
>>> will need a matching reg property. Equally, the parent node will need
>>> #address-cells and #size-cells too. So, the last couple lines would be:
>>>
>>> 		power-on-sequence {
>>> 			#address-cells = <1>;
>>> 			#size-cells = <0>;
>>> 			step@0 {
>>> 				reg = <0>;
>>
>> That's precisely what I would like to avoid - I don't need the steps
>> to be numbered and I certainly have no use for a reg property. Isn't
>> there a way to make it simpler?
> 
> It's not technically valid to not have the reg property. Or
> #address-cells and #size-cells properties for that matter.

I'm not keen on this representation where individual steps are nodes.
That seems like it could end up being too "heavyweight" for a long sequence.


> 
> Thierry
> 
> 
> 
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thierry Reding July 31, 2012, 12:38 p.m. UTC | #23
On Tue, Jul 31, 2012 at 08:22:17PM +0800, Mitch Bradley wrote:
> On 7/31/2012 6:56 PM, Thierry Reding wrote:
> > On Tue, Jul 31, 2012 at 07:32:20PM +0900, Alex Courbot wrote:
> >> On 07/31/2012 07:45 AM, Stephen Warren wrote:
> >>> I wonder if using the same structure/array as input and output would
> >>> simplify the API; the platform data would fill in the fields mentioned
> >>> above, and power_seq_build() would parse those, then set other fields in
> >>> the same structs to the looked-up handle values?
> >>
> >> The thing is that I am not sure what happens to the platform data
> >> once probe() is done. Isn't it customary to mark it with __devinit
> >> and have it freed after probing is successful?
> > 
> > No, platform data should stay around forever. Otherwise, consider what
> > would happen if your driver is built as a module and you unload and load
> > it again.
> > 
> >> More generally, I think it is a good practice to have data
> >> structures tailored right for what they need to do - code with
> >> members that are meaningful only at given points of an instance's
> >> life tends to be more confusing.
> > 
> > I agree. Furthermore the driver unload/reload would be another reason
> > not to reuse platform data as the output of the build() function.
> > 
> > But maybe what Stephen meant was more like filling a structure with data
> > taken from the platform data and pass that to a resolve() function which
> > would fill in the missing pieces like pointers to actual resources. I
> > imagine a managed interface would become a little trickier to do using
> > such an approach.
> > 
> >>> If the nodes have a unit address (i.e. end in "@n"), which they will
> >>> have to if all named "step" and there's more than one of them, then they
> >>> will need a matching reg property. Equally, the parent node will need
> >>> #address-cells and #size-cells too. So, the last couple lines would be:
> >>>
> >>> 		power-on-sequence {
> >>> 			#address-cells = <1>;
> >>> 			#size-cells = <0>;
> >>> 			step@0 {
> >>> 				reg = <0>;
> >>
> >> That's precisely what I would like to avoid - I don't need the steps
> >> to be numbered and I certainly have no use for a reg property. Isn't
> >> there a way to make it simpler?
> > 
> > It's not technically valid to not have the reg property. Or
> > #address-cells and #size-cells properties for that matter.
> 
> I'm not keen on this representation where individual steps are nodes.
> That seems like it could end up being too "heavyweight" for a long sequence.

The other alternative would involve using a single property to encode
one sequence. I think that was the initial proposal, though using proper
phandle encoding it could probably be enhanced a bit. However anything
that involves a single property has the problem that we need to encode
the type of resource as an integer, and that makes things very hard to
read.

So it would look something like this:

	power-on = <1  &gpio 6 0            1
		    0                   10000
		    2  &reg                 1
		    3  &pwm  0 5000000      1>;

	power-off = <3  &pwm  0 5000000      0
		     2  &reg                 0
		     0                   10000
		     1  &gpio 6 0            0>;

So the first cell would encode the type:
  0: delay
  1: gpio
  2: regulator
  3: PWM

The next n cells would be the phandle and the specifier, while the last
cell would encode a resource-specific parameter:
  delay: time in microseconds
  gpio: set level (0: low, 1: high)
  regulator: 0: disable, 1: enable
  pwm: 0: disable, 1: enable

I guess this would be more compact, but it is also very hard to read. Is
that something you would be happier with? Perhaps you were thinking of
something completely different?

Thierry
Mitch Bradley July 31, 2012, 12:55 p.m. UTC | #24
On 7/31/2012 8:38 PM, Thierry Reding wrote:
> On Tue, Jul 31, 2012 at 08:22:17PM +0800, Mitch Bradley wrote:
>> On 7/31/2012 6:56 PM, Thierry Reding wrote:
>>> On Tue, Jul 31, 2012 at 07:32:20PM +0900, Alex Courbot wrote:
>>>> On 07/31/2012 07:45 AM, Stephen Warren wrote:
>>>>> I wonder if using the same structure/array as input and output would
>>>>> simplify the API; the platform data would fill in the fields mentioned
>>>>> above, and power_seq_build() would parse those, then set other fields in
>>>>> the same structs to the looked-up handle values?
>>>>
>>>> The thing is that I am not sure what happens to the platform data
>>>> once probe() is done. Isn't it customary to mark it with __devinit
>>>> and have it freed after probing is successful?
>>>
>>> No, platform data should stay around forever. Otherwise, consider what
>>> would happen if your driver is built as a module and you unload and load
>>> it again.
>>>
>>>> More generally, I think it is a good practice to have data
>>>> structures tailored right for what they need to do - code with
>>>> members that are meaningful only at given points of an instance's
>>>> life tends to be more confusing.
>>>
>>> I agree. Furthermore the driver unload/reload would be another reason
>>> not to reuse platform data as the output of the build() function.
>>>
>>> But maybe what Stephen meant was more like filling a structure with data
>>> taken from the platform data and pass that to a resolve() function which
>>> would fill in the missing pieces like pointers to actual resources. I
>>> imagine a managed interface would become a little trickier to do using
>>> such an approach.
>>>
>>>>> If the nodes have a unit address (i.e. end in "@n"), which they will
>>>>> have to if all named "step" and there's more than one of them, then they
>>>>> will need a matching reg property. Equally, the parent node will need
>>>>> #address-cells and #size-cells too. So, the last couple lines would be:
>>>>>
>>>>> 		power-on-sequence {
>>>>> 			#address-cells = <1>;
>>>>> 			#size-cells = <0>;
>>>>> 			step@0 {
>>>>> 				reg = <0>;
>>>>
>>>> That's precisely what I would like to avoid - I don't need the steps
>>>> to be numbered and I certainly have no use for a reg property. Isn't
>>>> there a way to make it simpler?
>>>
>>> It's not technically valid to not have the reg property. Or
>>> #address-cells and #size-cells properties for that matter.
>>
>> I'm not keen on this representation where individual steps are nodes.
>> That seems like it could end up being too "heavyweight" for a long sequence.
> 
> The other alternative would involve using a single property to encode
> one sequence. I think that was the initial proposal, though using proper
> phandle encoding it could probably be enhanced a bit. However anything
> that involves a single property has the problem that we need to encode
> the type of resource as an integer, and that makes things very hard to
> read.
> 
> So it would look something like this:
> 
> 	power-on = <1  &gpio 6 0            1
> 		    0                   10000
> 		    2  &reg                 1
> 		    3  &pwm  0 5000000      1>;
> 
> 	power-off = <3  &pwm  0 5000000      0
> 		     2  &reg                 0
> 		     0                   10000
> 		     1  &gpio 6 0            0>;
> 
> So the first cell would encode the type:
>   0: delay
>   1: gpio
>   2: regulator
>   3: PWM
> 
> The next n cells would be the phandle and the specifier, while the last
> cell would encode a resource-specific parameter:
>   delay: time in microseconds
>   gpio: set level (0: low, 1: high)
>   regulator: 0: disable, 1: enable
>   pwm: 0: disable, 1: enable
> 
> I guess this would be more compact, but it is also very hard to read. Is
> that something you would be happier with? Perhaps you were thinking of
> something completely different?


Perhaps a compact/flexible encoding could be designed, with a textual
encoding that is easy to read.  A separate tool could convert the text
encoding to the integer format, annotated with comments containing
the "source text".  A file containing that output could be #included
into the dts file.

> 
> Thierry
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown July 31, 2012, 2:11 p.m. UTC | #25
On Tue, Jul 31, 2012 at 06:51:03PM +0900, Alex Courbot wrote:

> 2) On cleanup, it cleans the resources that needs to be freed (i.e.
> those that are not devm-handled).

> 2) can certainly be removed either by enforcing use of devm, or by
> doing reference counting. 1) seems more difficult to avoid - we need

I'd just add devm_ for everything that's not got it.
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown July 31, 2012, 2:13 p.m. UTC | #26
On Tue, Jul 31, 2012 at 12:56:40PM +0200, Thierry Reding wrote:
> On Tue, Jul 31, 2012 at 07:32:20PM +0900, Alex Courbot wrote:

> > The thing is that I am not sure what happens to the platform data
> > once probe() is done. Isn't it customary to mark it with __devinit
> > and have it freed after probing is successful?

> No, platform data should stay around forever. Otherwise, consider what
> would happen if your driver is built as a module and you unload and load
> it again.

__devinit can be discarded if you disable enough kernel features,
HOTPLUG is the main one IIRC, modules might also need to go - drivers
really ought to take a copy of platform data they plan to use at
runtime, though practically speaking you have to try to trigger any
problems.
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thierry Reding July 31, 2012, 2:22 p.m. UTC | #27
On Tue, Jul 31, 2012 at 03:13:29PM +0100, Mark Brown wrote:
> On Tue, Jul 31, 2012 at 12:56:40PM +0200, Thierry Reding wrote:
> > On Tue, Jul 31, 2012 at 07:32:20PM +0900, Alex Courbot wrote:
> 
> > > The thing is that I am not sure what happens to the platform data
> > > once probe() is done. Isn't it customary to mark it with __devinit
> > > and have it freed after probing is successful?
> 
> > No, platform data should stay around forever. Otherwise, consider what
> > would happen if your driver is built as a module and you unload and load
> > it again.
> 
> __devinit can be discarded if you disable enough kernel features,
> HOTPLUG is the main one IIRC, modules might also need to go - drivers
> really ought to take a copy of platform data they plan to use at
> runtime, though practically speaking you have to try to trigger any
> problems.

HOTPLUG is marked EXPERT and explicitly states that it should only be
disabled if you're not using modules or dynamic device discovery. I
think if you've ignored all of that you're no longer entitled to
complain.

Thierry
Mark Brown July 31, 2012, 2:23 p.m. UTC | #28
On Tue, Jul 31, 2012 at 05:37:07PM +0900, Alex Courbot wrote:
> On 07/30/2012 08:00 PM, Simon Glass wrote:

> >For the delay, I think milliseconds is reasonable. I suppose there is
> >no reasonable need for microseconds?

> I don't see any need for microseconds myself - anybody sees use for
> finer-grained delays?

Bouncing reset lines, often the time required for reset is down in the
microseconds.
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown July 31, 2012, 2:26 p.m. UTC | #29
On Tue, Jul 31, 2012 at 04:22:17PM +0200, Thierry Reding wrote:
> On Tue, Jul 31, 2012 at 03:13:29PM +0100, Mark Brown wrote:

> > __devinit can be discarded if you disable enough kernel features,
> > HOTPLUG is the main one IIRC, modules might also need to go - drivers
> > really ought to take a copy of platform data they plan to use at
> > runtime, though practically speaking you have to try to trigger any
> > problems.

> HOTPLUG is marked EXPERT and explicitly states that it should only be
> disabled if you're not using modules or dynamic device discovery. I
> think if you've ignored all of that you're no longer entitled to
> complain.

This is framework code - it doesn't have much option.  Disabling HOTPLUG
is totally reasonable on space constrained systems, there's no reason
for the code to break things for people.
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thierry Reding July 31, 2012, 2:32 p.m. UTC | #30
On Tue, Jul 31, 2012 at 03:26:07PM +0100, Mark Brown wrote:
> On Tue, Jul 31, 2012 at 04:22:17PM +0200, Thierry Reding wrote:
> > On Tue, Jul 31, 2012 at 03:13:29PM +0100, Mark Brown wrote:
> 
> > > __devinit can be discarded if you disable enough kernel features,
> > > HOTPLUG is the main one IIRC, modules might also need to go - drivers
> > > really ought to take a copy of platform data they plan to use at
> > > runtime, though practically speaking you have to try to trigger any
> > > problems.
> 
> > HOTPLUG is marked EXPERT and explicitly states that it should only be
> > disabled if you're not using modules or dynamic device discovery. I
> > think if you've ignored all of that you're no longer entitled to
> > complain.
> 
> This is framework code - it doesn't have much option.  Disabling HOTPLUG
> is totally reasonable on space constrained systems, there's no reason
> for the code to break things for people.

Still if you use this code and disable HOTPLUG, then you shouldn't be
using modules either. I mean there is no way you can write a driver that
can gracefully handle its platform data being discarded.

Thierry
Mark Brown July 31, 2012, 3:39 p.m. UTC | #31
On Tue, Jul 31, 2012 at 04:32:35PM +0200, Thierry Reding wrote:
> On Tue, Jul 31, 2012 at 03:26:07PM +0100, Mark Brown wrote:

> > This is framework code - it doesn't have much option.  Disabling HOTPLUG
> > is totally reasonable on space constrained systems, there's no reason
> > for the code to break things for people.

> Still if you use this code and disable HOTPLUG, then you shouldn't be
> using modules either. I mean there is no way you can write a driver that

Of course.

> can gracefully handle its platform data being discarded.

Sure there is - take a copy of the platform data in probe().
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Greg KH July 31, 2012, 4:19 p.m. UTC | #32
On Tue, Jul 31, 2012 at 04:39:41PM +0100, Mark Brown wrote:
> On Tue, Jul 31, 2012 at 04:32:35PM +0200, Thierry Reding wrote:
> > On Tue, Jul 31, 2012 at 03:26:07PM +0100, Mark Brown wrote:
> 
> > > This is framework code - it doesn't have much option.  Disabling HOTPLUG
> > > is totally reasonable on space constrained systems, there's no reason
> > > for the code to break things for people.
> 
> > Still if you use this code and disable HOTPLUG, then you shouldn't be
> > using modules either. I mean there is no way you can write a driver that
> 
> Of course.
> 
> > can gracefully handle its platform data being discarded.
> 
> Sure there is - take a copy of the platform data in probe().

Ick ick ick, devdata needs to die as it's pretty much pointless these
days.

It's on my TODO list actually...

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown July 31, 2012, 4:22 p.m. UTC | #33
On Tue, Jul 31, 2012 at 09:19:54AM -0700, Greg Kroah-Hartman wrote:
> On Tue, Jul 31, 2012 at 04:39:41PM +0100, Mark Brown wrote:
> > On Tue, Jul 31, 2012 at 04:32:35PM +0200, Thierry Reding wrote:

> > > can gracefully handle its platform data being discarded.

> > Sure there is - take a copy of the platform data in probe().

> Ick ick ick, devdata needs to die as it's pretty much pointless these
> days.

Hrm?  I'm not sure I understand the direct relevance here - we're
talking about platform data.
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Stephen Warren July 31, 2012, 4:34 p.m. UTC | #34
On 07/31/2012 04:32 AM, Alex Courbot wrote:
> On 07/31/2012 07:45 AM, Stephen Warren wrote:
...
>> If the nodes have a unit address (i.e. end in "@n"), which they will
>> have to if all named "step" and there's more than one of them, then they
>> will need a matching reg property. Equally, the parent node will need
>> #address-cells and #size-cells too. So, the last couple lines would be:
>>
>>         power-on-sequence {
>>             #address-cells = <1>;
>>             #size-cells = <0>;
>>             step@0 {
>>                 reg = <0>;
> 
> That's precisely what I would like to avoid - I don't need the steps to
> be numbered and I certainly have no use for a reg property. Isn't there
> a way to make it simpler?

You may be able to get away without using the reg values in the code.
However, to have a semantically correct device tree, you really do need
all of those properties.

That said, I think you might need to use the reg values in code. I
believe there's no guarantee of the order in which nodes enumerate in
device tree, so you need to look at the reg property in order to find
the order in which to execute the nodes/steps.

... although perhaps the desire to avoid a dependency on DT ordering
applies more to the order in which devices instantiated from DT get
probed, rather than the order of low-level node enumeration, so I may be
wrong here. I've definitely seen Grant caution people not to rely on
device probe order, but perhaps he didn't make the same comment about
node order.
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Greg KH July 31, 2012, 4:42 p.m. UTC | #35
On Tue, Jul 31, 2012 at 05:22:30PM +0100, Mark Brown wrote:
> On Tue, Jul 31, 2012 at 09:19:54AM -0700, Greg Kroah-Hartman wrote:
> > On Tue, Jul 31, 2012 at 04:39:41PM +0100, Mark Brown wrote:
> > > On Tue, Jul 31, 2012 at 04:32:35PM +0200, Thierry Reding wrote:
> 
> > > > can gracefully handle its platform data being discarded.
> 
> > > Sure there is - take a copy of the platform data in probe().
> 
> > Ick ick ick, devdata needs to die as it's pretty much pointless these
> > days.
> 
> Hrm?  I'm not sure I understand the direct relevance here - we're
> talking about platform data.

The platform data was marked __devdata, and you said it could be thrown
away after init so you should keep it around somehow.

Anyway, not really the main point here at all, sorry for the noise...

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown July 31, 2012, 4:50 p.m. UTC | #36
On Tue, Jul 31, 2012 at 09:42:45AM -0700, Greg Kroah-Hartman wrote:
> On Tue, Jul 31, 2012 at 05:22:30PM +0100, Mark Brown wrote:

> > Hrm?  I'm not sure I understand the direct relevance here - we're
> > talking about platform data.

> The platform data was marked __devdata, and you said it could be thrown
> away after init so you should keep it around somehow.

Ah, sorry - I was thinking __devinitdata.
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Anton Vorontsov Aug. 1, 2012, 12:51 a.m. UTC | #37
On Mon, Jul 30, 2012 at 10:59:39PM +0200, Rafael J. Wysocki wrote:
[...]
> > Well, currently drivers/power/ is indeed just for power supply class
> > subsystem and drivers. But if the trend is to gather power management
> > ("policy") stuff under one directory, i.e.
> > 
> > drivers/
> >   power/
> >     supplies/    <- former "power supply class and drivers"
> >     regulators/
> >     idle/
> >     cpuidle/
> >     cpufreq/
> >     devfreq/
> >     avs/
> >     ...
> > 
> > That would probably make sense, we could easily see the big picture.
> > But if we're not going to do this long-term,
> 
> Yes, we may do this eventually, but surely not right now.

OK, great! Then I'll probably start thinking about moving power supply
drivers into its own directory, maybe in 3.7.

Thanks!
Alexandre Courbot Aug. 1, 2012, 1:42 a.m. UTC | #38
On 07/31/2012 09:22 PM, Mitch Bradley wrote:
> On 7/31/2012 6:56 PM, Thierry Reding wrote:
>> On Tue, Jul 31, 2012 at 07:32:20PM +0900, Alex Courbot wrote:
>>> On 07/31/2012 07:45 AM, Stephen Warren wrote:
>>>> I wonder if using the same structure/array as input and output would
>>>> simplify the API; the platform data would fill in the fields mentioned
>>>> above, and power_seq_build() would parse those, then set other fields in
>>>> the same structs to the looked-up handle values?
>>>
>>> The thing is that I am not sure what happens to the platform data
>>> once probe() is done. Isn't it customary to mark it with __devinit
>>> and have it freed after probing is successful?
>>
>> No, platform data should stay around forever. Otherwise, consider what
>> would happen if your driver is built as a module and you unload and load
>> it again.
>>
>>> More generally, I think it is a good practice to have data
>>> structures tailored right for what they need to do - code with
>>> members that are meaningful only at given points of an instance's
>>> life tends to be more confusing.
>>
>> I agree. Furthermore the driver unload/reload would be another reason
>> not to reuse platform data as the output of the build() function.
>>
>> But maybe what Stephen meant was more like filling a structure with data
>> taken from the platform data and pass that to a resolve() function which
>> would fill in the missing pieces like pointers to actual resources. I
>> imagine a managed interface would become a little trickier to do using
>> such an approach.
>>
>>>> If the nodes have a unit address (i.e. end in "@n"), which they will
>>>> have to if all named "step" and there's more than one of them, then they
>>>> will need a matching reg property. Equally, the parent node will need
>>>> #address-cells and #size-cells too. So, the last couple lines would be:
>>>>
>>>> 		power-on-sequence {
>>>> 			#address-cells = <1>;
>>>> 			#size-cells = <0>;
>>>> 			step@0 {
>>>> 				reg = <0>;
>>>
>>> That's precisely what I would like to avoid - I don't need the steps
>>> to be numbered and I certainly have no use for a reg property. Isn't
>>> there a way to make it simpler?
>>
>> It's not technically valid to not have the reg property. Or
>> #address-cells and #size-cells properties for that matter.
>
> I'm not keen on this representation where individual steps are nodes.
> That seems like it could end up being too "heavyweight" for a long sequence.

Using nodes has a big advantage though: we can use any arbitrary 
property to add extra parameters to the resource being controlled. Right 
now we only use enable/disable, but for example one can imagine an 
optional voltage setting for a regulator. It is much more future-proof 
than a design where the number of parameters would be fixed and could 
not be extended without breaking compatibility.

I experimented encoding the whole sequence within a single property. It 
works of course, but is not really flexible, hard to read, and quite 
error-prone overall. The memory footprint gain was not so obvious 
neither (although it was indeed more compact).

What bothers me is to have to specify the cells layout and reg property 
for *every single sequence*, but well, I guess we can live with that.

Alex.
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alexandre Courbot Aug. 1, 2012, 1:47 a.m. UTC | #39
On 07/31/2012 09:55 PM, Mitch Bradley wrote:
> On 7/31/2012 8:38 PM, Thierry Reding wrote:
>> On Tue, Jul 31, 2012 at 08:22:17PM +0800, Mitch Bradley wrote:
>>> On 7/31/2012 6:56 PM, Thierry Reding wrote:
>>>> On Tue, Jul 31, 2012 at 07:32:20PM +0900, Alex Courbot wrote:
>>>>> On 07/31/2012 07:45 AM, Stephen Warren wrote:
>>>>>> I wonder if using the same structure/array as input and output would
>>>>>> simplify the API; the platform data would fill in the fields mentioned
>>>>>> above, and power_seq_build() would parse those, then set other fields in
>>>>>> the same structs to the looked-up handle values?
>>>>>
>>>>> The thing is that I am not sure what happens to the platform data
>>>>> once probe() is done. Isn't it customary to mark it with __devinit
>>>>> and have it freed after probing is successful?
>>>>
>>>> No, platform data should stay around forever. Otherwise, consider what
>>>> would happen if your driver is built as a module and you unload and load
>>>> it again.
>>>>
>>>>> More generally, I think it is a good practice to have data
>>>>> structures tailored right for what they need to do - code with
>>>>> members that are meaningful only at given points of an instance's
>>>>> life tends to be more confusing.
>>>>
>>>> I agree. Furthermore the driver unload/reload would be another reason
>>>> not to reuse platform data as the output of the build() function.
>>>>
>>>> But maybe what Stephen meant was more like filling a structure with data
>>>> taken from the platform data and pass that to a resolve() function which
>>>> would fill in the missing pieces like pointers to actual resources. I
>>>> imagine a managed interface would become a little trickier to do using
>>>> such an approach.
>>>>
>>>>>> If the nodes have a unit address (i.e. end in "@n"), which they will
>>>>>> have to if all named "step" and there's more than one of them, then they
>>>>>> will need a matching reg property. Equally, the parent node will need
>>>>>> #address-cells and #size-cells too. So, the last couple lines would be:
>>>>>>
>>>>>> 		power-on-sequence {
>>>>>> 			#address-cells = <1>;
>>>>>> 			#size-cells = <0>;
>>>>>> 			step@0 {
>>>>>> 				reg = <0>;
>>>>>
>>>>> That's precisely what I would like to avoid - I don't need the steps
>>>>> to be numbered and I certainly have no use for a reg property. Isn't
>>>>> there a way to make it simpler?
>>>>
>>>> It's not technically valid to not have the reg property. Or
>>>> #address-cells and #size-cells properties for that matter.
>>>
>>> I'm not keen on this representation where individual steps are nodes.
>>> That seems like it could end up being too "heavyweight" for a long sequence.
>>
>> The other alternative would involve using a single property to encode
>> one sequence. I think that was the initial proposal, though using proper
>> phandle encoding it could probably be enhanced a bit. However anything
>> that involves a single property has the problem that we need to encode
>> the type of resource as an integer, and that makes things very hard to
>> read.
>>
>> So it would look something like this:
>>
>> 	power-on = <1  &gpio 6 0            1
>> 		    0                   10000
>> 		    2  &reg                 1
>> 		    3  &pwm  0 5000000      1>;
>>
>> 	power-off = <3  &pwm  0 5000000      0
>> 		     2  &reg                 0
>> 		     0                   10000
>> 		     1  &gpio 6 0            0>;
>>
>> So the first cell would encode the type:
>>    0: delay
>>    1: gpio
>>    2: regulator
>>    3: PWM
>>
>> The next n cells would be the phandle and the specifier, while the last
>> cell would encode a resource-specific parameter:
>>    delay: time in microseconds
>>    gpio: set level (0: low, 1: high)
>>    regulator: 0: disable, 1: enable
>>    pwm: 0: disable, 1: enable
>>
>> I guess this would be more compact, but it is also very hard to read. Is
>> that something you would be happier with? Perhaps you were thinking of
>> something completely different?
>
>
> Perhaps a compact/flexible encoding could be designed, with a textual
> encoding that is easy to read.  A separate tool could convert the text
> encoding to the integer format, annotated with comments containing
> the "source text".  A file containing that output could be #included
> into the dts file.

Do you mean having a external compiler that would run before dtc just 
for producing the power sequences? That sounds a little bit overkill for 
something that ough to remain simple.

Also, although I admit I don't have the whole picture of where they 
could be used, I don't expect the power sequences to grow to sizes that 
would make us bother about their footprint.

Alex.

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mitch Bradley Aug. 1, 2012, 2:15 a.m. UTC | #40
On 8/1/2012 9:47 AM, Alex Courbot wrote:
> On 07/31/2012 09:55 PM, Mitch Bradley wrote:
>> On 7/31/2012 8:38 PM, Thierry Reding wrote:
>>> On Tue, Jul 31, 2012 at 08:22:17PM +0800, Mitch Bradley wrote:
>>>> On 7/31/2012 6:56 PM, Thierry Reding wrote:
>>>>> On Tue, Jul 31, 2012 at 07:32:20PM +0900, Alex Courbot wrote:
>>>>>> On 07/31/2012 07:45 AM, Stephen Warren wrote:
>>>>>>> I wonder if using the same structure/array as input and output would
>>>>>>> simplify the API; the platform data would fill in the fields mentioned
>>>>>>> above, and power_seq_build() would parse those, then set other fields in
>>>>>>> the same structs to the looked-up handle values?
>>>>>>
>>>>>> The thing is that I am not sure what happens to the platform data
>>>>>> once probe() is done. Isn't it customary to mark it with __devinit
>>>>>> and have it freed after probing is successful?
>>>>>
>>>>> No, platform data should stay around forever. Otherwise, consider what
>>>>> would happen if your driver is built as a module and you unload and load
>>>>> it again.
>>>>>
>>>>>> More generally, I think it is a good practice to have data
>>>>>> structures tailored right for what they need to do - code with
>>>>>> members that are meaningful only at given points of an instance's
>>>>>> life tends to be more confusing.
>>>>>
>>>>> I agree. Furthermore the driver unload/reload would be another reason
>>>>> not to reuse platform data as the output of the build() function.
>>>>>
>>>>> But maybe what Stephen meant was more like filling a structure with data
>>>>> taken from the platform data and pass that to a resolve() function which
>>>>> would fill in the missing pieces like pointers to actual resources. I
>>>>> imagine a managed interface would become a little trickier to do using
>>>>> such an approach.
>>>>>
>>>>>>> If the nodes have a unit address (i.e. end in "@n"), which they will
>>>>>>> have to if all named "step" and there's more than one of them, then they
>>>>>>> will need a matching reg property. Equally, the parent node will need
>>>>>>> #address-cells and #size-cells too. So, the last couple lines would be:
>>>>>>>
>>>>>>> 		power-on-sequence {
>>>>>>> 			#address-cells = <1>;
>>>>>>> 			#size-cells = <0>;
>>>>>>> 			step@0 {
>>>>>>> 				reg = <0>;
>>>>>>
>>>>>> That's precisely what I would like to avoid - I don't need the steps
>>>>>> to be numbered and I certainly have no use for a reg property. Isn't
>>>>>> there a way to make it simpler?
>>>>>
>>>>> It's not technically valid to not have the reg property. Or
>>>>> #address-cells and #size-cells properties for that matter.
>>>>
>>>> I'm not keen on this representation where individual steps are nodes.
>>>> That seems like it could end up being too "heavyweight" for a long sequence.
>>>
>>> The other alternative would involve using a single property to encode
>>> one sequence. I think that was the initial proposal, though using proper
>>> phandle encoding it could probably be enhanced a bit. However anything
>>> that involves a single property has the problem that we need to encode
>>> the type of resource as an integer, and that makes things very hard to
>>> read.
>>>
>>> So it would look something like this:
>>>
>>> 	power-on = <1  &gpio 6 0            1
>>> 		    0                   10000
>>> 		    2  &reg                 1
>>> 		    3  &pwm  0 5000000      1>;
>>>
>>> 	power-off = <3  &pwm  0 5000000      0
>>> 		     2  &reg                 0
>>> 		     0                   10000
>>> 		     1  &gpio 6 0            0>;
>>>
>>> So the first cell would encode the type:
>>>    0: delay
>>>    1: gpio
>>>    2: regulator
>>>    3: PWM
>>>
>>> The next n cells would be the phandle and the specifier, while the last
>>> cell would encode a resource-specific parameter:
>>>    delay: time in microseconds
>>>    gpio: set level (0: low, 1: high)
>>>    regulator: 0: disable, 1: enable
>>>    pwm: 0: disable, 1: enable
>>>
>>> I guess this would be more compact, but it is also very hard to read. Is
>>> that something you would be happier with? Perhaps you were thinking of
>>> something completely different?
>>
>>
>> Perhaps a compact/flexible encoding could be designed, with a textual
>> encoding that is easy to read.  A separate tool could convert the text
>> encoding to the integer format, annotated with comments containing
>> the "source text".  A file containing that output could be #included
>> into the dts file.
> 
> Do you mean having a external compiler that would run before dtc just 
> for producing the power sequences? That sounds a little bit overkill for 
> something that ough to remain simple.
> 
> Also, although I admit I don't have the whole picture of where they 
> could be used, I don't expect the power sequences to grow to sizes that 
> would make us bother about their footprint.

It is axiomatic that every "language", if it succeeds at all, eventually
grows into a complete programming language.  The more special-purpose
that it starts as, the uglier that it ends up.

> 
> Alex.
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alexandre Courbot Aug. 1, 2012, 2:50 a.m. UTC | #41
On 07/31/2012 07:19 PM, Thierry Reding wrote:
> * PGP Signed by an unknown key
>
> On Tue, Jul 31, 2012 at 06:51:03PM +0900, Alex Courbot wrote:
>> On 07/30/2012 08:33 PM, Thierry Reding wrote:
>>>> +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.
>>>
>>> I don't quite understand why the struct power_seq_resources is needed.
>>> Can this not be stored within power_seq?
>>
>> power_seq_resources serves two purposes:
>> 1) When parsing sequences, it keeps track of the resources we have
>> already allocated to avoid getting the same resource twice
>> 2) On cleanup, it cleans the resources that needs to be freed (i.e.
>> those that are not devm-handled).
>>
>> 2) can certainly be removed either by enforcing use of devm, or by
>> doing reference counting. 1) seems more difficult to avoid - we need
>> to keep track of the resources we already own between calls to
>> power_seq_build(). I'd certainly be glad to remove that structure
>> from public view and simplify the code if that is possible though.
>
> I still don't see the problem. Managing the resources should be part of
> the power_seq core and shouldn't be visible to users. Maybe what you are
> worried about is that you may need the same resource both for a power-up
> and a power-down sequence? I can see how that would require a global
> list of resources.

Yes, that is precisely my concern. Sorry for not stating that more clearly.

> However I still think it would be easier to encapsulate that completely.
> Maybe another level of abstraction is required. You could for example
> add another type to encapsulate several power sequences and that could
> keep a list of used resources. I can't think of a good name, but maybe
> the following DT snippet clarifies what I mean:
>
>          power-sequences {
>                  #address-cells = <1>;
>                  #size-cells = <0>;
>
>                  sequence@0 {
>                          name = "up";
>
>                          #address-cells = <1>;
>                          #size-cells = <0>;
>
>                          step@0 {
>                                  ...
>                          };
>
>                          ...
>                  };
>
>                  sequence@1 {
>                          name = "down";
>
>                          #address-cells = <1>;
>                          #size-cells = <0>;
>
>                          step@0 {
>                                  ...
>                          };
>
>                          ...
>                  };
>          };
>
> If you add a name property like this, you could extend the API to
> support running a named sequence:
>
>          power_seq_run(seq, "up");
>          ...
>          power_seq_run(seq, "down);

Mmm, that's something to consider. Forcing power sequences to be grouped 
within a "power-sequences" node would also make parsing easier from the 
driver side since it would not have to explicitly parse every sequence. 
We could even imagine some tighter integration with the device subsystem 
to automatically run specifically-named sequences during suspend/resume. 
But maybe I'm thinking too much here.

>
>>> Also, is there some way we can make the id property for GPIOs not
>>> require the -gpio suffix? If the resource type is already GPIO, then it
>>> seems redundant to add -gpio to the ID.
>>
>> There is unfortunately an inconsistency between the way regulators
>> and GPIOs are gotten by name. regulator_get(id) will expect to find
>> a property named "id-supply", while gpio_request_one(id) expects a
>> property named exactly "id". To workaround this we could sprintf the
>> correct property name from a non-suffixed property name within the
>> driver, but I think this actually speaks more in favor of having
>> phandles directly into the sequences.
>
> Yes, if it can be made to work by specifying the phandle directly that
> is certainly better.

Let's do that then - as for the PWM issue I had, let's address that by 
clearly stating in the documentation that phandles referring to a same 
device *must* be identical.

>>>> +     if (!seq) return 0;
>>>
>>> I don't think this is acceptable according to the coding style. Also,
>>> perhaps returning -EINVAL would be more meaningful?
>>
>> I neglected running checkpatch before submitting, apologies for
>> that. The return value seems correct to me, a NULL sequence has no
>> effect.
>
> But seq == NULL should never happen anyway, right?

It could if you are parsing a NULL node. It seems safe to me to consider 
that a NULL sequence is an empty sequence, but if I go for your solution 
involving another data structure to encapsulate the sequence, then this 
might change.

>>> Perhaps this should check for POWER_SEQ_STOP instead?
>>
>> There is no resource for POWER_SEQ_STOP - therefore, a NULL resource
>> is used instead.
>
> Still, you use POWER_SEQ_STOP as an explicit sentinel to mark the end of
> a sequence, so intuitively I'd be looking for that as a stop condition.

That is for platform data - resolved sequences get their type from their 
resource, and a STOP sequence does not have a resource. But the STOP 
type will go away too since we will have a steps count in the platform 
data instead.

>> I would like to do that actually. The issue is that it did not work
>> go well with the legacy pwm_backlight behavior: a power sequence
>> needs to be constructed out of a PWM obtained through
>> pwm_request(int pwm_id, char *label) and this behavior cannot be
>> emulated using the new platform data interface (which only works
>> with pwm_get()). But if I remove this old behavior, then I could
>> make power_seq opaque. I don't think many drivers are using it. What
>> do you think?
>
> I don't see how that is relevant here, since this power-sequencing code
> is supposed to be generic and not tied to any specific implementation.
> Can you explain further?
>
> In any case you shouldn't be using pwm_request() in new code.

Power sequences only rely on pwm_get, and never call pwm_request since 
it is, as you stated, deprecated. However there are still boards that 
use the old pwm_id member of the pwm_backlight_platform_data. For these, 
we must call pwm_request from the pwm_backlight driver in order to 
resolve the PWM (see pwm_backlight_legacy_probe of the seconds patch). 
As the PWM is being resolved by the backlight driver, and not within the 
power sequences parser, the resolved data structure must be visible to 
pwm_backlight so it can construct it. There are two ways to solve this 
and keep the power sequences structure private:

1) Add a way to resolve a PWM by id using pwm_request in the power 
sequences (we probably should not do that)
2) Port the old platform pwm_request code to use pwm_add_table and 
pwm_get instead.

Do I get points if I do 2)? :)

Thanks,
Alex.

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thierry Reding Aug. 1, 2012, 7:17 a.m. UTC | #42
On Wed, Aug 01, 2012 at 11:50:35AM +0900, Alex Courbot wrote:
> On 07/31/2012 07:19 PM, Thierry Reding wrote:
> >* PGP Signed by an unknown key
> >
> >On Tue, Jul 31, 2012 at 06:51:03PM +0900, Alex Courbot wrote:
> >>I would like to do that actually. The issue is that it did not work
> >>go well with the legacy pwm_backlight behavior: a power sequence
> >>needs to be constructed out of a PWM obtained through
> >>pwm_request(int pwm_id, char *label) and this behavior cannot be
> >>emulated using the new platform data interface (which only works
> >>with pwm_get()). But if I remove this old behavior, then I could
> >>make power_seq opaque. I don't think many drivers are using it. What
> >>do you think?
> >
> >I don't see how that is relevant here, since this power-sequencing code
> >is supposed to be generic and not tied to any specific implementation.
> >Can you explain further?
> >
> >In any case you shouldn't be using pwm_request() in new code.
> 
> Power sequences only rely on pwm_get, and never call pwm_request
> since it is, as you stated, deprecated. However there are still
> boards that use the old pwm_id member of the
> pwm_backlight_platform_data. For these, we must call pwm_request
> from the pwm_backlight driver in order to resolve the PWM (see
> pwm_backlight_legacy_probe of the seconds patch). As the PWM is
> being resolved by the backlight driver, and not within the power
> sequences parser, the resolved data structure must be visible to
> pwm_backlight so it can construct it. There are two ways to solve
> this and keep the power sequences structure private:
> 
> 1) Add a way to resolve a PWM by id using pwm_request in the power
> sequences (we probably should not do that)

No. But I think we don't need that either. If you use power sequences,
then you shouldn't be using the pwm_id member. Both methods should be
exclusive.

> 2) Port the old platform pwm_request code to use pwm_add_table and
> pwm_get instead.

In the long term, every PWM user should move to pwm_add_table() and
pwm_get(), but there are quite a lot of boards that need conversion.

> Do I get points if I do 2)? :)

Yes. =) I have a sample patch for PXA EZX, but as I said, many more
boards need conversion.

Thierry
Thierry Reding Aug. 1, 2012, 7:41 a.m. UTC | #43
On Tue, Jul 31, 2012 at 04:39:41PM +0100, Mark Brown wrote:
> On Tue, Jul 31, 2012 at 04:32:35PM +0200, Thierry Reding wrote:
> > On Tue, Jul 31, 2012 at 03:26:07PM +0100, Mark Brown wrote:
> 
> > > This is framework code - it doesn't have much option.  Disabling HOTPLUG
> > > is totally reasonable on space constrained systems, there's no reason
> > > for the code to break things for people.
> 
> > Still if you use this code and disable HOTPLUG, then you shouldn't be
> > using modules either. I mean there is no way you can write a driver that
> 
> Of course.
> 
> > can gracefully handle its platform data being discarded.
> 
> Sure there is - take a copy of the platform data in probe().

Yes, but that will only work for built-in drivers. If you unload the
module and that causes the platform data to be discarded, reloading
won't work.

Thierry
Mark Brown Aug. 1, 2012, 1:26 p.m. UTC | #44
On Wed, Aug 01, 2012 at 09:41:13AM +0200, Thierry Reding wrote:
> On Tue, Jul 31, 2012 at 04:39:41PM +0100, Mark Brown wrote:

> > Sure there is - take a copy of the platform data in probe().

> Yes, but that will only work for built-in drivers. If you unload the
> module and that causes the platform data to be discarded, reloading
> won't work.

This is why __devinit data will only be discarded when this is not
possible.
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thierry Reding Aug. 1, 2012, 1:38 p.m. UTC | #45
On Wed, Aug 01, 2012 at 02:26:51PM +0100, Mark Brown wrote:
> On Wed, Aug 01, 2012 at 09:41:13AM +0200, Thierry Reding wrote:
> > On Tue, Jul 31, 2012 at 04:39:41PM +0100, Mark Brown wrote:
> 
> > > Sure there is - take a copy of the platform data in probe().
> 
> > Yes, but that will only work for built-in drivers. If you unload the
> > module and that causes the platform data to be discarded, reloading
> > won't work.
> 
> This is why __devinit data will only be discarded when this is not
> possible.

That's exactly my point. But I seem to have miserably failed to get that
across. =)

Thierry
Mark Brown Aug. 1, 2012, 1:55 p.m. UTC | #46
On Wed, Aug 01, 2012 at 03:38:14PM +0200, Thierry Reding wrote:
> On Wed, Aug 01, 2012 at 02:26:51PM +0100, Mark Brown wrote:

> > This is why __devinit data will only be discarded when this is not
> > possible.

> That's exactly my point. But I seem to have miserably failed to get that
> across. =)

We must be talking at cross purposes then.  What I'm saying is that the
framework shouldn't rely on platform data and should assume that the
kernel might be configured so it can be discarded (by copying most
likely).
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thierry Reding Aug. 1, 2012, 2:01 p.m. UTC | #47
On Wed, Aug 01, 2012 at 02:55:31PM +0100, Mark Brown wrote:
> On Wed, Aug 01, 2012 at 03:38:14PM +0200, Thierry Reding wrote:
> > On Wed, Aug 01, 2012 at 02:26:51PM +0100, Mark Brown wrote:
> 
> > > This is why __devinit data will only be discarded when this is not
> > > possible.
> 
> > That's exactly my point. But I seem to have miserably failed to get that
> > across. =)
> 
> We must be talking at cross purposes then.  What I'm saying is that the
> framework shouldn't rely on platform data and should assume that the
> kernel might be configured so it can be discarded (by copying most
> likely).

Yes. I think this should be solved by the power_seq_build() function
which uses the platform data description of the sequence and builds it
into something for internal use that doesn't rely on anything in the
platform data.

Thierry
Alexandre Courbot Aug. 2, 2012, 8 a.m. UTC | #48
On 07/31/2012 07:45 AM, Stephen Warren wrote:
> Oh I see. That's a little confusing. Why not just reference the relevant
> resources directly in each step; something more like:
>
> 		gpio@1 {
> 			action = "enable-gpio";
> 			gpio = <&gpio 1 0>;
> 		};
>
> I guess that might make parsing/building a little harder, since you'd
> have to detect when you'd already done gpio_request() on a given GPIO
> and not repeat it or something like that, but to me this makes the DT a
> lot easier to comprehend.

I tried to move towards having the phandles directly in the sequences 
themselves - that reminded me why I did not do that in the first place. 
Let's say we have a sequence like this (reg property omitted on purpose):

	power-on-sequence {
		step@0 {
			regulator = <&backlight_reg>;
			enable;
		};
		step@1 {
			delay = <10000>;
		};
		step@2 {
			pwm = <&pwm 2 5000000>;
			enable;
		};
		step@3 {
			gpio = <&gpio 28 0>;
			enable;
		};
	};

The problem is, how do we turn these phandles into the resource of 
interest. The type of the resource can be infered by the name of the 
property. The hard part is resolving the resource from the phandle - it 
seems like the API just does not allow to do this. GPIO has 
of_get_named_gpio, but AFAIK there are no equivalent for regulator 
consumer and PWM: the only way to use the DT with them is through 
get_regulator and get_pwm which work at the device level.

Or is there a way that I overlooked?

Thanks,
Alex.

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thierry Reding Aug. 2, 2012, 8:21 a.m. UTC | #49
On Thu, Aug 02, 2012 at 05:00:13PM +0900, Alex Courbot wrote:
> On 07/31/2012 07:45 AM, Stephen Warren wrote:
> >Oh I see. That's a little confusing. Why not just reference the relevant
> >resources directly in each step; something more like:
> >
> >		gpio@1 {
> >			action = "enable-gpio";
> >			gpio = <&gpio 1 0>;
> >		};
> >
> >I guess that might make parsing/building a little harder, since you'd
> >have to detect when you'd already done gpio_request() on a given GPIO
> >and not repeat it or something like that, but to me this makes the DT a
> >lot easier to comprehend.
> 
> I tried to move towards having the phandles directly in the
> sequences themselves - that reminded me why I did not do that in the
> first place. Let's say we have a sequence like this (reg property
> omitted on purpose):
> 
> 	power-on-sequence {
> 		step@0 {
> 			regulator = <&backlight_reg>;
> 			enable;
> 		};
> 		step@1 {
> 			delay = <10000>;
> 		};
> 		step@2 {
> 			pwm = <&pwm 2 5000000>;
> 			enable;
> 		};
> 		step@3 {
> 			gpio = <&gpio 28 0>;
> 			enable;
> 		};
> 	};
> 
> The problem is, how do we turn these phandles into the resource of
> interest. The type of the resource can be infered by the name of the
> property. The hard part is resolving the resource from the phandle -
> it seems like the API just does not allow to do this. GPIO has
> of_get_named_gpio, but AFAIK there are no equivalent for regulator
> consumer and PWM: the only way to use the DT with them is through
> get_regulator and get_pwm which work at the device level.
> 
> Or is there a way that I overlooked?

No, you are right. Perhaps we should add exported functions that do the
equivalent of of_pwm_request() or the regulator_dev_lookup() and
of_get_regulator() pair.

Thierry
Alexandre Courbot Aug. 2, 2012, 8:27 a.m. UTC | #50
On Thu 02 Aug 2012 05:21:57 PM JST, Thierry Reding wrote:
> * PGP Signed by an unknown key
>
> On Thu, Aug 02, 2012 at 05:00:13PM +0900, Alex Courbot wrote:
>> On 07/31/2012 07:45 AM, Stephen Warren wrote:
>>> Oh I see. That's a little confusing. Why not just reference the relevant
>>> resources directly in each step; something more like:
>>>
>>> 		gpio@1 {
>>> 			action = "enable-gpio";
>>> 			gpio = <&gpio 1 0>;
>>> 		};
>>>
>>> I guess that might make parsing/building a little harder, since you'd
>>> have to detect when you'd already done gpio_request() on a given GPIO
>>> and not repeat it or something like that, but to me this makes the DT a
>>> lot easier to comprehend.
>>
>> I tried to move towards having the phandles directly in the
>> sequences themselves - that reminded me why I did not do that in the
>> first place. Let's say we have a sequence like this (reg property
>> omitted on purpose):
>>
>> 	power-on-sequence {
>> 		step@0 {
>> 			regulator = <&backlight_reg>;
>> 			enable;
>> 		};
>> 		step@1 {
>> 			delay = <10000>;
>> 		};
>> 		step@2 {
>> 			pwm = <&pwm 2 5000000>;
>> 			enable;
>> 		};
>> 		step@3 {
>> 			gpio = <&gpio 28 0>;
>> 			enable;
>> 		};
>> 	};
>>
>> The problem is, how do we turn these phandles into the resource of
>> interest. The type of the resource can be infered by the name of the
>> property. The hard part is resolving the resource from the phandle -
>> it seems like the API just does not allow to do this. GPIO has
>> of_get_named_gpio, but AFAIK there are no equivalent for regulator
>> consumer and PWM: the only way to use the DT with them is through
>> get_regulator and get_pwm which work at the device level.
>>
>> Or is there a way that I overlooked?
>
> No, you are right. Perhaps we should add exported functions that do the
> equivalent of of_pwm_request() or the regulator_dev_lookup() and
> of_get_regulator() pair.

How would that be looked with respect to "good DT practices"? I can 
somehow understand the wish to restrain DT access to these functions 
that integrate well with current workflows. Aren't we going to be 
frowned upon if we make more low-level functions public?

Alex.
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thierry Reding Aug. 2, 2012, 8:45 a.m. UTC | #51
On Thu, Aug 02, 2012 at 05:27:44PM +0900, Alex Courbot wrote:
> On Thu 02 Aug 2012 05:21:57 PM JST, Thierry Reding wrote:
> >* PGP Signed by an unknown key
> >
> >On Thu, Aug 02, 2012 at 05:00:13PM +0900, Alex Courbot wrote:
> >>On 07/31/2012 07:45 AM, Stephen Warren wrote:
> >>>Oh I see. That's a little confusing. Why not just reference the relevant
> >>>resources directly in each step; something more like:
> >>>
> >>>		gpio@1 {
> >>>			action = "enable-gpio";
> >>>			gpio = <&gpio 1 0>;
> >>>		};
> >>>
> >>>I guess that might make parsing/building a little harder, since you'd
> >>>have to detect when you'd already done gpio_request() on a given GPIO
> >>>and not repeat it or something like that, but to me this makes the DT a
> >>>lot easier to comprehend.
> >>
> >>I tried to move towards having the phandles directly in the
> >>sequences themselves - that reminded me why I did not do that in the
> >>first place. Let's say we have a sequence like this (reg property
> >>omitted on purpose):
> >>
> >>	power-on-sequence {
> >>		step@0 {
> >>			regulator = <&backlight_reg>;
> >>			enable;
> >>		};
> >>		step@1 {
> >>			delay = <10000>;
> >>		};
> >>		step@2 {
> >>			pwm = <&pwm 2 5000000>;
> >>			enable;
> >>		};
> >>		step@3 {
> >>			gpio = <&gpio 28 0>;
> >>			enable;
> >>		};
> >>	};
> >>
> >>The problem is, how do we turn these phandles into the resource of
> >>interest. The type of the resource can be infered by the name of the
> >>property. The hard part is resolving the resource from the phandle -
> >>it seems like the API just does not allow to do this. GPIO has
> >>of_get_named_gpio, but AFAIK there are no equivalent for regulator
> >>consumer and PWM: the only way to use the DT with them is through
> >>get_regulator and get_pwm which work at the device level.
> >>
> >>Or is there a way that I overlooked?
> >
> >No, you are right. Perhaps we should add exported functions that do the
> >equivalent of of_pwm_request() or the regulator_dev_lookup() and
> >of_get_regulator() pair.
> 
> How would that be looked with respect to "good DT practices"? I can
> somehow understand the wish to restrain DT access to these functions
> that integrate well with current workflows. Aren't we going to be
> frowned upon if we make more low-level functions public?

Yes, I think that's exactly what will happen.

Thierry
Alexandre Courbot Aug. 2, 2012, 9:20 a.m. UTC | #52
On Thu 02 Aug 2012 05:45:41 PM JST, Thierry Reding wrote:
> * PGP Signed by an unknown key
>
> On Thu, Aug 02, 2012 at 05:27:44PM +0900, Alex Courbot wrote:
>> On Thu 02 Aug 2012 05:21:57 PM JST, Thierry Reding wrote:
>>>> Old Signed by an unknown key
>>>
>>> On Thu, Aug 02, 2012 at 05:00:13PM +0900, Alex Courbot wrote:
>>>> On 07/31/2012 07:45 AM, Stephen Warren wrote:
>>>>> Oh I see. That's a little confusing. Why not just reference the relevant
>>>>> resources directly in each step; something more like:
>>>>>
>>>>> 		gpio@1 {
>>>>> 			action = "enable-gpio";
>>>>> 			gpio = <&gpio 1 0>;
>>>>> 		};
>>>>>
>>>>> I guess that might make parsing/building a little harder, since you'd
>>>>> have to detect when you'd already done gpio_request() on a given GPIO
>>>>> and not repeat it or something like that, but to me this makes the DT a
>>>>> lot easier to comprehend.
>>>>
>>>> I tried to move towards having the phandles directly in the
>>>> sequences themselves - that reminded me why I did not do that in the
>>>> first place. Let's say we have a sequence like this (reg property
>>>> omitted on purpose):
>>>>
>>>> 	power-on-sequence {
>>>> 		step@0 {
>>>> 			regulator = <&backlight_reg>;
>>>> 			enable;
>>>> 		};
>>>> 		step@1 {
>>>> 			delay = <10000>;
>>>> 		};
>>>> 		step@2 {
>>>> 			pwm = <&pwm 2 5000000>;
>>>> 			enable;
>>>> 		};
>>>> 		step@3 {
>>>> 			gpio = <&gpio 28 0>;
>>>> 			enable;
>>>> 		};
>>>> 	};
>>>>
>>>> The problem is, how do we turn these phandles into the resource of
>>>> interest. The type of the resource can be infered by the name of the
>>>> property. The hard part is resolving the resource from the phandle -
>>>> it seems like the API just does not allow to do this. GPIO has
>>>> of_get_named_gpio, but AFAIK there are no equivalent for regulator
>>>> consumer and PWM: the only way to use the DT with them is through
>>>> get_regulator and get_pwm which work at the device level.
>>>>
>>>> Or is there a way that I overlooked?
>>>
>>> No, you are right. Perhaps we should add exported functions that do the
>>> equivalent of of_pwm_request() or the regulator_dev_lookup() and
>>> of_get_regulator() pair.
>>
>> How would that be looked with respect to "good DT practices"? I can
>> somehow understand the wish to restrain DT access to these functions
>> that integrate well with current workflows. Aren't we going to be
>> frowned upon if we make more low-level functions public?
>
> Yes, I think that's exactly what will happen.

Probably not worth to try this then?

Alex.
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown Aug. 2, 2012, 6:11 p.m. UTC | #53
On Thu, Aug 02, 2012 at 10:21:57AM +0200, Thierry Reding wrote:
> On Thu, Aug 02, 2012 at 05:00:13PM +0900, Alex Courbot wrote:

> > The problem is, how do we turn these phandles into the resource of
> > interest. The type of the resource can be infered by the name of the
> > property. The hard part is resolving the resource from the phandle -
> > it seems like the API just does not allow to do this. GPIO has
> > of_get_named_gpio, but AFAIK there are no equivalent for regulator
> > consumer and PWM: the only way to use the DT with them is through
> > get_regulator and get_pwm which work at the device level.

> > Or is there a way that I overlooked?

> No, you are right. Perhaps we should add exported functions that do the
> equivalent of of_pwm_request() or the regulator_dev_lookup() and
> of_get_regulator() pair.

I missed some of the earlier bits of the thread here but why can't we do
device based lookups?
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alexandre Courbot Aug. 3, 2012, 1:15 a.m. UTC | #54
On Fri 03 Aug 2012 03:11:12 AM JST, Mark Brown wrote:
> On Thu, Aug 02, 2012 at 10:21:57AM +0200, Thierry Reding wrote:
>> On Thu, Aug 02, 2012 at 05:00:13PM +0900, Alex Courbot wrote:
>
>>> The problem is, how do we turn these phandles into the resource of
>>> interest. The type of the resource can be infered by the name of the
>>> property. The hard part is resolving the resource from the phandle -
>>> it seems like the API just does not allow to do this. GPIO has
>>> of_get_named_gpio, but AFAIK there are no equivalent for regulator
>>> consumer and PWM: the only way to use the DT with them is through
>>> get_regulator and get_pwm which work at the device level.
>
>>> Or is there a way that I overlooked?
>
>> No, you are right. Perhaps we should add exported functions that do the
>> equivalent of of_pwm_request() or the regulator_dev_lookup() and
>> of_get_regulator() pair.
>
> I missed some of the earlier bits of the thread here but why can't we do
> device based lookups?

That is because the phandles would not be properties of the device node 
but rather of its sub-nodes:

backlight {
     compatible = "pwm-backlight";
     ...
     power-on-sequence {
         step@0 {
             regulator = <&backlight_reg>;
             enable;
         };


So here simply using regulator_get on the backlight device would not work.

Alex.
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown Aug. 4, 2012, 2:12 p.m. UTC | #55
On Fri, Aug 03, 2012 at 10:15:46AM +0900, Alex Courbot wrote:
> On Fri 03 Aug 2012 03:11:12 AM JST, Mark Brown wrote:

> >I missed some of the earlier bits of the thread here but why can't we do
> >device based lookups?

> That is because the phandles would not be properties of the device
> node but rather of its sub-nodes:

> backlight {
>     compatible = "pwm-backlight";
>     ...
>     power-on-sequence {
>         step@0 {
>             regulator = <&backlight_reg>;
>             enable;
>         };
> 

> So here simply using regulator_get on the backlight device would not work.

Ah, right.  DT isn't being terribly helpful here...  I think the thing
I'd expect to work here is that you have a reference back to the supply
property of the backlight device rather than direct to the regulator so
you end up writing "enable supply X" rather than "enable regulator X".

Not quite sure how exactly you'd accomplish that - I guess if
regulator_get() would recursively follow phandles until it hits a node
that'd do the trick?
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alexandre Courbot Aug. 6, 2012, 2:27 a.m. UTC | #56
On 08/04/2012 11:12 PM, Mark Brown wrote:
> On Fri, Aug 03, 2012 at 10:15:46AM +0900, Alex Courbot wrote:
>> On Fri 03 Aug 2012 03:11:12 AM JST, Mark Brown wrote:
>
>>> I missed some of the earlier bits of the thread here but why can't we do
>>> device based lookups?
>
>> That is because the phandles would not be properties of the device
>> node but rather of its sub-nodes:
>
>> backlight {
>>      compatible = "pwm-backlight";
>>      ...
>>      power-on-sequence {
>>          step@0 {
>>              regulator = <&backlight_reg>;
>>              enable;
>>          };
>>
>
>> So here simply using regulator_get on the backlight device would not work.
>
> Ah, right.  DT isn't being terribly helpful here...  I think the thing
> I'd expect to work here is that you have a reference back to the supply
> property of the backlight device rather than direct to the regulator so
> you end up writing "enable supply X" rather than "enable regulator X".
>
> Not quite sure how exactly you'd accomplish that - I guess if
> regulator_get() would recursively follow phandles until it hits a node
> that'd do the trick?

Do you mean that regulator_get() would parse sub-nodes looking for a 
match? That seems rather dangerous and error-prone, especially if one 
has actual devices within the sub-nodes - their regulators could be 
stolen by the parent device.

I think we only have two choices for this:

1) Stick to the scheme where resources are declared at the device level, 
such as they can be referenced by name in the sub-nodes (basically what 
I did in this patch):

backlight {
      compatible = "pwm-backlight";
      ...
      backlight-supply = <&backlight_reg>;

      power-on-sequence {
          step@0 {
              regulator = "backlight";
              enable;
          };

This would translate by a get_regulator(dev, "backlight") in the code 
which would be properly resolved.

2) Export a lower-level DT API for resolving phandles directly from a 
property, similar to of_get_named_gpio. We would then have 
of_get_named_regulator and of_get_named_pwm.

If 2) is deemed acceptable, then I think we should go for it as it would 
provide the most compact and readable DT syntax. Otherwise 1) is still 
acceptable IMHO, as it should at least make sense to people already 
familiar with how the DT works.

Opinions from DT experts?

Alex.

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pihet-XID, Jean Aug. 6, 2012, 8:45 a.m. UTC | #57
Hi Anton,

Sorry for the late reply. I was away and back now.

On Mon, Jul 30, 2012 at 4:40 AM, Anton Vorontsov <cbouatmailru@gmail.com> wrote:
> On Mon, Jul 30, 2012 at 10:51:42AM +0900, Alex Courbot wrote:
> [...]
>> On the other hand I have just noticed that the apparently unrelated
>> Adaptive Voltage Scaling driver just appeared in drivers/power/avs.
>> So if Anton and David are ok with this, maybe I could put the power
>> sequences code in its own subdirectory within drivers/power.
>
> Well, currently drivers/power/ is indeed just for power supply class
> subsystem and drivers. But if the trend is to gather power management
> ("policy") stuff under one directory, i.e.
>
> drivers/
>   power/
>     supplies/    <- former "power supply class and drivers"
>     regulators/
>     idle/
>     cpuidle/
>     cpufreq/
>     devfreq/
>     avs/
>     ...
>
> That would probably make sense, we could easily see the big picture.
> But if we're not going to do this long-term, I would suggest to stick
> to just a new directory under drivers (and move drivers/power/avs/ to
> drivers/avs).
>
> Cc'ing some more people...
>
> Thanks,
>
> p.s. Jean, why am I the last person who discovers drivers/power/avs/?
> Would be nice to Cc me on such patches; by moving AVS under
> drivers/power/ you effectively nominated me as its maintainer. :-)
Oops, I am really sorry about that ;-( . I wrongly assumed Rafael and
Greg KH were the contact persons for drivers/power and so I contacted
them before moving the code.

Thanks for letting me know. Are you ok with the changes? Let me know
if some more changes are needed.

Regards,
Jean

>
> --
> Anton Vorontsov
> Email: cbouatmailru@gmail.com
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Stephen Warren Aug. 6, 2012, 4:16 p.m. UTC | #58
On 08/05/2012 08:27 PM, Alex Courbot wrote:
> On 08/04/2012 11:12 PM, Mark Brown wrote:
>> On Fri, Aug 03, 2012 at 10:15:46AM +0900, Alex Courbot wrote:
>>> On Fri 03 Aug 2012 03:11:12 AM JST, Mark Brown wrote:
>>
>>>> I missed some of the earlier bits of the thread here but why can't
>>>> we do
>>>> device based lookups?
...
> I think we only have two choices for this:
> 
> 1) Stick to the scheme where resources are declared at the device level,
> such as they can be referenced by name in the sub-nodes (basically what
> I did in this patch):
> 
> backlight {
>      compatible = "pwm-backlight";
>      ...
>      backlight-supply = <&backlight_reg>;
> 
>      power-on-sequence {
>          step@0 {
>              regulator = "backlight";
>              enable;
>          };
> 
> This would translate by a get_regulator(dev, "backlight") in the code
> which would be properly resolved.

Yes, upon reflection, that scheme does make sense. I withdraw the
comments I made re: whether it'd be better to just stick the phandles
into the steps.
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alexandre Courbot Aug. 7, 2012, 5:10 a.m. UTC | #59
On 08/07/2012 01:16 AM, Stephen Warren wrote:
> On 08/05/2012 08:27 PM, Alex Courbot wrote:
>> On 08/04/2012 11:12 PM, Mark Brown wrote:
>>> On Fri, Aug 03, 2012 at 10:15:46AM +0900, Alex Courbot wrote:
>>>> On Fri 03 Aug 2012 03:11:12 AM JST, Mark Brown wrote:
>>>
>>>>> I missed some of the earlier bits of the thread here but why can't
>>>>> we do
>>>>> device based lookups?
> ...
>> I think we only have two choices for this:
>>
>> 1) Stick to the scheme where resources are declared at the device level,
>> such as they can be referenced by name in the sub-nodes (basically what
>> I did in this patch):
>>
>> backlight {
>>       compatible = "pwm-backlight";
>>       ...
>>       backlight-supply = <&backlight_reg>;
>>
>>       power-on-sequence {
>>           step@0 {
>>               regulator = "backlight";
>>               enable;
>>           };
>>
>> This would translate by a get_regulator(dev, "backlight") in the code
>> which would be properly resolved.
>
> Yes, upon reflection, that scheme does make sense. I withdraw the
> comments I made re: whether it'd be better to just stick the phandles
> into the steps.

Right - having the phandles directly in the sequences has its merits, 
but logically speaking resources are related to a device, so this 
declarative approach is probably closer to reality anyway.

I will revise the patch according to all the feedback received and 
submit a new version soon.

Thanks,
Alex.


--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/Documentation/power/power_seq.txt b/Documentation/power/power_seq.txt
new file mode 100644
index 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/Kconfig
index 08b4c52..65bebfe 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -282,4 +282,8 @@  config CMA_AREAS
 
 endif
 
+config POWER_SEQ
+	bool
+	default n
+
 endmenu
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 5aa2d70..4c498c1 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -18,6 +18,7 @@  obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o
 ifeq ($(CONFIG_SYSFS),y)
 obj-$(CONFIG_MODULES)	+= module.o
 endif
+obj-$(CONFIG_POWER_SEQ)	+= power_seq.o
 obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
 obj-$(CONFIG_REGMAP)	+= regmap/
 obj-$(CONFIG_SOC_BUS) += soc.o
diff --git a/drivers/base/power_seq.c b/drivers/base/power_seq.c
new file mode 100644
index 0000000..6ccefa1
--- /dev/null
+++ b/drivers/base/power_seq.c
@@ -0,0 +1,300 @@ 
+/*
+ * power_seq.c - A simple power sequence interpreter for platform devices
+ *               and device tree.
+ *
+ * Author: Alexandre Courbot <acourbot@nvidia.com>
+ *
+ * Copyright (c) 2012 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#include <linux/power_seq.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/pwm.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio.h>
+
+#ifdef CONFIG_OF
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#endif
+
+static int power_seq_step_run(struct power_seq_step *step)
+{
+	int err = 0;
+
+	if (step->params.pre_delay)
+		mdelay(step->params.pre_delay);
+
+	switch (step->resource->type) {
+#ifdef CONFIG_REGULATOR
+	case POWER_SEQ_REGULATOR:
+		if (step->params.enable)
+			err = regulator_enable(step->resource->regulator);
+		else
+			err = regulator_disable(step->resource->regulator);
+		break;
+#endif
+#ifdef CONFIG_PWM
+	case POWER_SEQ_PWM:
+		if (step->params.enable)
+			err = pwm_enable(step->resource->pwm);
+		else
+			pwm_disable(step->resource->pwm);
+		break;
+#endif
+#ifdef CONFIG_GPIOLIB
+	case POWER_SEQ_GPIO:
+		gpio_set_value_cansleep(step->resource->gpio,
+					step->params.enable);
+		break;
+#endif
+	/*
+	 * should never happen unless the sequence includes a step which
+	 * type does not have support compiled in
+	 */
+	default:
+		return -EINVAL;
+	}
+
+	if (err < 0)
+		return err;
+
+	if (step->params.post_delay)
+		mdelay(step->params.post_delay);
+
+	return 0;
+}
+
+int power_seq_run(struct device *dev, power_seq *seq)
+{
+	int err;
+
+	if (!seq) return 0;
+
+	while (seq->resource) {
+		if ((err = power_seq_step_run(seq++))) {
+			dev_err(dev, "error %d while running power sequence!\n",
+				err);
+			return err;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(power_seq_run);
+
+#ifdef CONFIG_OF
+static int of_parse_power_seq_step(struct device *dev, struct device_node *node,
+				   struct platform_power_seq_step *step)
+{
+	if (of_property_read_string(node, "id", &step->id)) {
+		dev_err(dev, "missing id property!\n");
+		return -EINVAL;
+	}
+
+	if (!strcmp(node->name, "regulator")) {
+		step->type = POWER_SEQ_REGULATOR;
+#ifdef CONFIG_OF_GPIO
+	} else if (!strcmp(node->name, "gpio")) {
+		int gpio;
+
+		step->type = POWER_SEQ_GPIO;
+		gpio = of_get_named_gpio(dev->of_node, step->id, 0);
+		if (gpio < 0) {
+			dev_err(dev, "cannot resolve gpio \"%s\"\n", step->id);
+			return gpio;
+		}
+		step->gpio = gpio;
+#endif /* CONFIG_OF_GPIO */
+	} else if (!strcmp(node->name, "pwm")) {
+		step->type = POWER_SEQ_PWM;
+	} else {
+		dev_err(dev, "invalid power seq step type!\n");
+		return -EINVAL;
+	}
+
+	if (of_find_property(node, "enable", NULL)) {
+		step->params.enable = 1;
+	} else if (!of_find_property(node, "disable", NULL)) {
+		dev_err(dev, "missing enable or disable property!\n");
+		return -EINVAL;
+	}
+
+	of_property_read_u32(node, "pre-delay", &step->params.pre_delay);
+	of_property_read_u32(node, "post-delay", &step->params.post_delay);
+
+	return 0;
+}
+
+platform_power_seq *of_parse_power_seq(struct device *dev,
+				       struct device_node *node)
+{
+	struct device_node *child = NULL;
+	platform_power_seq *ret;
+	int cpt = 0;
+	int err;
+
+	if (!node) return NULL;
+
+	while ((child = of_get_next_child(node, child)))
+		cpt++;
+
+	/* allocate one more step to signal end of sequence */
+	ret = devm_kzalloc(dev, sizeof(*ret) * (cpt + 1), GFP_KERNEL);
+	if (!ret)
+		return ERR_PTR(-ENOMEM);
+
+	cpt = 0;
+	while ((child = of_get_next_child(node, child))) {
+		if ((err = of_parse_power_seq_step(dev, child, &ret[cpt++])))
+			return ERR_PTR(err);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(of_parse_power_seq);
+#endif /* CONFIG_OF */
+
+static
+struct power_seq_resource * power_seq_find_resource(power_seq_resources *ress,
+					struct platform_power_seq_step *res)
+{
+	struct power_seq_resource *step;
+
+	list_for_each_entry(step, ress, list) {
+		if (step->type != res->type) continue;
+		switch (res->type) {
+		case POWER_SEQ_GPIO:
+			if (step->gpio == res->gpio)
+				return step;
+			break;
+		default:
+			if (!strcmp(step->id, res->id))
+				return step;
+			break;
+		}
+	}
+
+	return NULL;
+}
+
+static int power_seq_allocate_resource(struct device *dev,
+				       struct power_seq_resource *res)
+{
+	int err;
+
+	switch (res->type) {
+#ifdef CONFIG_REGULATOR
+	case POWER_SEQ_REGULATOR:
+		res->regulator = devm_regulator_get(dev, res->id);
+		if (IS_ERR(res->regulator)) {
+			dev_err(dev, "cannot get regulator \"%s\"\n", res->id);
+			return PTR_ERR(res->regulator);
+		}
+		break;
+#endif
+#ifdef CONFIG_PWM
+	case POWER_SEQ_PWM:
+		res->pwm = pwm_get(dev, res->id);
+		if (IS_ERR(res->pwm)) {
+			dev_err(dev, "cannot get pwm \"%s\"\n", res->id);
+			return PTR_ERR(res->pwm);
+		}
+		break;
+#endif
+#ifdef CONFIG_GPIOLIB
+	case POWER_SEQ_GPIO:
+		err = devm_gpio_request_one(dev, res->gpio, GPIOF_OUT_INIT_HIGH,
+					    "backlight_gpio");
+		if (err) {
+			dev_err(dev, "cannot get gpio %d\n", res->gpio);
+			return err;
+		}
+		break;
+#endif
+	default:
+		dev_err(dev, "invalid resource type %d\n", res->type);
+		return -EINVAL;
+		break;
+	}
+
+	return 0;
+}
+
+power_seq *power_seq_build(struct device *dev, power_seq_resources *ress,
+			   platform_power_seq *pseq)
+{
+	struct power_seq_step *seq = NULL, *ret;
+	struct power_seq_resource *res;
+	int cpt, err;
+
+	/* first pass to count the number of steps to allocate */
+	for (cpt = 0; pseq[cpt].type != POWER_SEQ_STOP; cpt++);
+
+	if (!cpt)
+		return seq;
+
+	/* 1 more for the STOP step */
+	ret = seq = devm_kzalloc(dev, sizeof(*seq) * (cpt + 1), GFP_KERNEL);
+	if (!seq)
+		return ERR_PTR(-ENOMEM);
+
+	for (; pseq->type != POWER_SEQ_STOP; pseq++, seq++) {
+		/* create resource node if not referenced already */
+		if (!(res = power_seq_find_resource(ress, pseq))) {
+			res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
+			if (!res)
+				return ERR_PTR(-ENOMEM);
+			res->type = pseq->type;
+
+			if (res->type == POWER_SEQ_GPIO)
+				res->gpio = pseq->gpio;
+			else
+				res->id = pseq->id;
+
+			if ((err = power_seq_allocate_resource(dev, res)) < 0)
+				return ERR_PTR(err);
+
+			list_add(&res->list, ress);
+		}
+		seq->resource = res;
+		memcpy(&seq->params, &pseq->params, sizeof(seq->params));
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(power_seq_build);
+
+void power_seq_free_resources(power_seq_resources *ress) {
+	struct power_seq_resource *res;
+
+#ifdef CONFIG_PWM
+	list_for_each_entry(res, ress, list) {
+		if (res->type == POWER_SEQ_PWM)
+			pwm_put(res->pwm);
+	}
+#endif
+}
+EXPORT_SYMBOL_GPL(power_seq_free_resources);
+
+MODULE_AUTHOR("Alexandre Courbot <acourbot@nvidia.com>");
+MODULE_DESCRIPTION("Runtime Interpreted Power Sequences");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/power_seq.h b/include/linux/power_seq.h
new file mode 100644
index 0000000..da0593a
--- /dev/null
+++ b/include/linux/power_seq.h
@@ -0,0 +1,139 @@ 
+/*
+ * power_seq.h
+ *
+ * Simple interpreter for defining power sequences as platform data or device
+ * tree properties. Initially designed for use with backlight drivers.
+ *
+ * Power sequences are designed to replace the callbacks typically used in
+ * board-specific files that implement board-specific power sequences of devices
+ * such as backlights. A power sequence is an array of resources (which can a
+ * regulator, a GPIO, a PWM, ...) with an action to perform on it (enable or
+ * disable) and optional pre and post step delays. By having them interpreted
+ * instead of arbitrarily executed, it is possible to describe these in the
+ * device tree and thus remove board-specific code from the kernel.
+ *
+ * Author: Alexandre Courbot <acourbot@nvidia.com>
+ *
+ * Copyright (c) 2012 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#ifndef __LINUX_POWER_SEQ_H
+#define __LINUX_POWER_SEQ_H
+
+#include <linux/types.h>
+
+struct device;
+struct regulator;
+struct pwm_device;
+struct device_node;
+
+/**
+ * The different kinds of resources that can be controlled during the sequences.
+ */
+typedef enum {
+	POWER_SEQ_STOP = 0,
+	POWER_SEQ_REGULATOR,
+	POWER_SEQ_PWM,
+	POWER_SEQ_GPIO,
+	POWER_SEQ_MAX,
+} power_res_type;
+
+struct power_seq_resource {
+	power_res_type type;
+	/* name to resolve for resources with a name (regulator, pwm) */
+	const char *id;
+	/* resolved resource */
+	union {
+		struct regulator *regulator;
+		struct pwm_device *pwm;
+		int gpio;
+	};
+	/* used to maintain the list of resources used by the driver */
+	struct list_head list;
+};
+typedef struct list_head power_seq_resources;
+
+struct power_step_params {
+	/* enable the resource if 1, disable if 0 */
+	bool enable;
+	/* delay (in ms) to wait before executing the step */
+	int  pre_delay;
+	/* delay (in ms) to wait after executing the step */
+	int post_delay;
+};
+
+/**
+ * Platform definition of power sequences. A sequence is an array of these,
+ * terminated by a STOP instance.
+ */
+struct platform_power_seq_step {
+	power_res_type type;
+	union {
+		/* Used by REGULATOR and PWM types to name the resource */
+		const char *id;
+		/* Used by GPIO */
+		int gpio;
+	};
+	struct power_step_params params;
+};
+typedef struct platform_power_seq_step platform_power_seq;
+
+/**
+ * Power sequence steps resolved against their resource. Built by
+ * power_seq_build and used to run the sequence.
+ */
+struct power_seq_step {
+	struct power_seq_resource *resource;
+	struct power_step_params params;
+};
+typedef struct power_seq_step power_seq;
+
+#ifdef CONFIG_OF
+/**
+ * Build a platform data sequence from a device tree node. Memory for the
+ * sequence is allocated using devm_kzalloc on dev.
+ */
+platform_power_seq *of_parse_power_seq(struct device *dev,
+				       struct device_node *node);
+#else
+platform_power_seq *of_parse_power_seq(struct device *dev,
+				       struct device_node *node)
+{
+	return NULL;
+}
+#endif
+
+/**
+ * Build a runnable power sequence from platform data, and add the resources
+ * it uses into ress. Memory for the sequence is allocated using devm_kzalloc
+ * on dev.
+ */
+power_seq *power_seq_build(struct device *dev, power_seq_resources *ress,
+			   platform_power_seq *pseq);
+
+/**
+ * Free all the resources previously allocated by power_seq_allocate_resources.
+ */
+void power_seq_free_resources(power_seq_resources *ress);
+
+/**
+ * Run the given power sequence. Returns 0 on success, error code in case of
+ * failure.
+ */
+int power_seq_run(struct device *dev, power_seq *seq);
+
+#endif