On Friday, August 10, 2012, Shawn Guo wrote: > With a lot of devices booting from device tree nowadays, it requires > that OPP table can be initialized from device tree. The patch adds > a helper function of_init_opp_table together with a binding doc for > that purpose. > > Signed-off-by: Shawn Guo <shawn.guo@xxxxxxxxxx> I need an ACK from whoever maintains the DT bindings for that. Thanks, Rafael > --- > Documentation/devicetree/bindings/power/opp.txt | 25 ++++++++++++ > drivers/base/power/opp.c | 47 +++++++++++++++++++++++ > include/linux/opp.h | 8 ++++ > 3 files changed, 80 insertions(+), 0 deletions(-) > create mode 100644 Documentation/devicetree/bindings/power/opp.txt > > diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/power/opp.txt > new file mode 100644 > index 0000000..74499e5 > --- /dev/null > +++ b/Documentation/devicetree/bindings/power/opp.txt > @@ -0,0 +1,25 @@ > +* Generic OPP Interface > + > +SoCs have a standard set of tuples consisting of frequency and > +voltage pairs that the device will support per voltage domain. These > +are called Operating Performance Points or OPPs. > + > +Properties: > +- operating-points: An array of 2-tuples items, and each item consists > + of frequency and voltage like <freq-kHz vol-uV>. > + freq: clock frequency in kHz > + vol: voltage in microvolt > + > +Examples: > + > +cpu@0 { > + compatible = "arm,cortex-a9"; > + reg = <0>; > + next-level-cache = <&L2>; > + operating-points = < > + /* kHz uV */ > + 792000 1100000 > + 396000 950000 > + 198000 850000 > + >; > +}; > diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c > index ac993ea..d946864 100644 > --- a/drivers/base/power/opp.c > +++ b/drivers/base/power/opp.c > @@ -22,6 +22,7 @@ > #include <linux/rculist.h> > #include <linux/rcupdate.h> > #include <linux/opp.h> > +#include <linux/of.h> > > /* > * Internal data structure organization with the OPP layer library is as > @@ -674,3 +675,49 @@ struct srcu_notifier_head *opp_get_notifier(struct device *dev) > > return &dev_opp->head; > } > + > +#ifdef CONFIG_OF > +/** > + * of_init_opp_table() - Initialize opp table from device tree > + * @dev: device pointer used to lookup device OPPs. > + * > + * Register the initial OPP table with the OPP library for given device. > + */ > +int of_init_opp_table(struct device *dev) > +{ > + const struct property *prop; > + const __be32 *val; > + int nr; > + > + prop = of_find_property(dev->of_node, "operating-points", NULL); > + if (!prop) > + return -ENODEV; > + if (!prop->value) > + return -ENODATA; > + > + /* > + * Each OPP is a set of tuples consisting of frequency and > + * voltage like <freq-kHz vol-uV>. > + */ > + nr = prop->length / sizeof(u32); > + if (nr % 2) { > + dev_err(dev, "%s: Invalid OPP list\n", __func__); > + return -EINVAL; > + } > + > + val = prop->value; > + while (nr) { > + unsigned long freq = be32_to_cpup(val++) * 1000; > + unsigned long volt = be32_to_cpup(val++); > + > + if (opp_add(dev, freq, volt)) { > + dev_warn(dev, "%s: Failed to add OPP %ld\n", > + __func__, freq); > + continue; > + } > + nr -= 2; > + } > + > + return 0; > +} > +#endif > diff --git a/include/linux/opp.h b/include/linux/opp.h > index 2a4e5fa..214e0eb 100644 > --- a/include/linux/opp.h > +++ b/include/linux/opp.h > @@ -48,6 +48,14 @@ int opp_disable(struct device *dev, unsigned long freq); > > struct srcu_notifier_head *opp_get_notifier(struct device *dev); > > +#ifdef CONFIG_OF > +int of_init_opp_table(struct device *dev); > +#else > +static inline int of_init_opp_table(struct device *dev) > +{ > + return -EINVAL; > +} > +#endif /* CONFIG_OF */ > #else > static inline unsigned long opp_get_voltage(struct opp *opp) > { > -- To unsubscribe from this list: send the line "unsubscribe cpufreq" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html