diff options
author | Viresh Kumar <viresh.kumar@linaro.org> | 2017-11-29 04:48:36 -0500 |
---|---|---|
committer | Viresh Kumar <viresh.kumar@linaro.org> | 2018-05-09 00:45:19 -0400 |
commit | a88bd2a51e901ed8081841d647157de8153df813 (patch) | |
tree | d5d01ef8c2d292f64c1cd234c72ff54da8600d74 /drivers/opp | |
parent | fa9b274f8aeffb97787b055b8cfbf9062e158551 (diff) |
PM / OPP: Implement of_dev_pm_opp_find_required_opp()
A device's DT node or its OPP nodes can contain a phandle to other
device's OPP node, in the "required-opps" property.
This patch implements a routine to find that required OPP from the node
that contains the "required-opps" property.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/opp')
-rw-r--r-- | drivers/opp/core.c | 4 | ||||
-rw-r--r-- | drivers/opp/of.c | 54 | ||||
-rw-r--r-- | drivers/opp/opp.h | 1 |
3 files changed, 56 insertions, 3 deletions
diff --git a/drivers/opp/core.c b/drivers/opp/core.c index a0f72c732718..416f54ba7a26 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c | |||
@@ -33,8 +33,6 @@ LIST_HEAD(opp_tables); | |||
33 | /* Lock to allow exclusive modification to the device and opp lists */ | 33 | /* Lock to allow exclusive modification to the device and opp lists */ |
34 | DEFINE_MUTEX(opp_table_lock); | 34 | DEFINE_MUTEX(opp_table_lock); |
35 | 35 | ||
36 | static void dev_pm_opp_get(struct dev_pm_opp *opp); | ||
37 | |||
38 | static struct opp_device *_find_opp_dev(const struct device *dev, | 36 | static struct opp_device *_find_opp_dev(const struct device *dev, |
39 | struct opp_table *opp_table) | 37 | struct opp_table *opp_table) |
40 | { | 38 | { |
@@ -901,7 +899,7 @@ static void _opp_kref_release(struct kref *kref) | |||
901 | dev_pm_opp_put_opp_table(opp_table); | 899 | dev_pm_opp_put_opp_table(opp_table); |
902 | } | 900 | } |
903 | 901 | ||
904 | static void dev_pm_opp_get(struct dev_pm_opp *opp) | 902 | void dev_pm_opp_get(struct dev_pm_opp *opp) |
905 | { | 903 | { |
906 | kref_get(&opp->kref); | 904 | kref_get(&opp->kref); |
907 | } | 905 | } |
diff --git a/drivers/opp/of.c b/drivers/opp/of.c index cba669cd00c5..6380ec3d695b 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c | |||
@@ -673,3 +673,57 @@ put_cpu_node: | |||
673 | return ret; | 673 | return ret; |
674 | } | 674 | } |
675 | EXPORT_SYMBOL_GPL(dev_pm_opp_of_get_sharing_cpus); | 675 | EXPORT_SYMBOL_GPL(dev_pm_opp_of_get_sharing_cpus); |
676 | |||
677 | /** | ||
678 | * of_dev_pm_opp_find_required_opp() - Search for required OPP. | ||
679 | * @dev: The device whose OPP node is referenced by the 'np' DT node. | ||
680 | * @np: Node that contains the "required-opps" property. | ||
681 | * | ||
682 | * Returns the OPP of the device 'dev', whose phandle is present in the "np" | ||
683 | * node. Although the "required-opps" property supports having multiple | ||
684 | * phandles, this helper routine only parses the very first phandle in the list. | ||
685 | * | ||
686 | * Return: Matching opp, else returns ERR_PTR in case of error and should be | ||
687 | * handled using IS_ERR. | ||
688 | * | ||
689 | * The callers are required to call dev_pm_opp_put() for the returned OPP after | ||
690 | * use. | ||
691 | */ | ||
692 | struct dev_pm_opp *of_dev_pm_opp_find_required_opp(struct device *dev, | ||
693 | struct device_node *np) | ||
694 | { | ||
695 | struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ENODEV); | ||
696 | struct device_node *required_np; | ||
697 | struct opp_table *opp_table; | ||
698 | |||
699 | opp_table = _find_opp_table(dev); | ||
700 | if (IS_ERR(opp_table)) | ||
701 | return ERR_CAST(opp_table); | ||
702 | |||
703 | required_np = of_parse_phandle(np, "required-opps", 0); | ||
704 | if (unlikely(!required_np)) { | ||
705 | dev_err(dev, "Unable to parse required-opps\n"); | ||
706 | goto put_opp_table; | ||
707 | } | ||
708 | |||
709 | mutex_lock(&opp_table->lock); | ||
710 | |||
711 | list_for_each_entry(temp_opp, &opp_table->opp_list, node) { | ||
712 | if (temp_opp->available && temp_opp->np == required_np) { | ||
713 | opp = temp_opp; | ||
714 | |||
715 | /* Increment the reference count of OPP */ | ||
716 | dev_pm_opp_get(opp); | ||
717 | break; | ||
718 | } | ||
719 | } | ||
720 | |||
721 | mutex_unlock(&opp_table->lock); | ||
722 | |||
723 | of_node_put(required_np); | ||
724 | put_opp_table: | ||
725 | dev_pm_opp_put_opp_table(opp_table); | ||
726 | |||
727 | return opp; | ||
728 | } | ||
729 | EXPORT_SYMBOL_GPL(of_dev_pm_opp_find_required_opp); | ||
diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h index 381a4fb15d5c..f9eccf9811ae 100644 --- a/drivers/opp/opp.h +++ b/drivers/opp/opp.h | |||
@@ -187,6 +187,7 @@ struct opp_table { | |||
187 | }; | 187 | }; |
188 | 188 | ||
189 | /* Routines internal to opp core */ | 189 | /* Routines internal to opp core */ |
190 | void dev_pm_opp_get(struct dev_pm_opp *opp); | ||
190 | void _get_opp_table_kref(struct opp_table *opp_table); | 191 | void _get_opp_table_kref(struct opp_table *opp_table); |
191 | int _get_opp_count(struct opp_table *opp_table); | 192 | int _get_opp_count(struct opp_table *opp_table); |
192 | struct opp_table *_find_opp_table(struct device *dev); | 193 | struct opp_table *_find_opp_table(struct device *dev); |