+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.
+config POWER_SEQ
+ bool
+ default n
+
"default n" is already the default, so you can drop that line.
+#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?
+ 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.
+
+ 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.
+ /* 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.
+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.
+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?
+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?
+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.
+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.