From 456ab9a912089f41aa8dd8490b944c74225df9ae Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Sun, 15 Dec 2019 02:26:23 +0100 Subject: [PATCH] ipq806x: opp/core: update patch allowing adjusting of OPP voltages at runtime Update 0049-PM-OPP-Support-adjusting-OPP-voltages-at-runtime with upstream version. Tested-by: Stefan Lippers-Hollmann [nbg6817/ipq8065] Signed-off-by: Ansuel Smith --- ...rt-adjusting-OPP-voltages-at-runtime.patch | 132 ++++++++++-------- 1 file changed, 71 insertions(+), 61 deletions(-) diff --git a/target/linux/ipq806x/patches-4.19/0049-PM-OPP-Support-adjusting-OPP-voltages-at-runtime.patch b/target/linux/ipq806x/patches-4.19/0049-PM-OPP-Support-adjusting-OPP-voltages-at-runtime.patch index 1a0e50d3d3..9181d94901 100644 --- a/target/linux/ipq806x/patches-4.19/0049-PM-OPP-Support-adjusting-OPP-voltages-at-runtime.patch +++ b/target/linux/ipq806x/patches-4.19/0049-PM-OPP-Support-adjusting-OPP-voltages-at-runtime.patch @@ -1,7 +1,17 @@ -From c949f08cf20fe82971fbdb4015daa38210da492e Mon Sep 17 00:00:00 2001 +From: Sylwester Nawrocki +To: krzk@kernel.org, vireshk@kernel.org, robh+dt@kernel.org +Cc: sboyd@kernel.org, roger.lu@mediatek.com, + linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, + linux-samsung-soc@vger.kernel.org, devicetree@vger.kernel.org, + b.zolnierkie@samsung.com, m.szyprowski@samsung.com, + Stephen Boyd , + Sylwester Nawrocki +Subject: [PATCH v5 1/4] PM / OPP: Support adjusting OPP voltages at runtime +Date: Wed, 16 Oct 2019 16:57:53 +0200 +Message-ID: <20191016145756.16004-2-s.nawrocki@samsung.com> (raw) +In-Reply-To: <20191016145756.16004-1-s.nawrocki@samsung.com> + From: Stephen Boyd -Date: Fri, 18 Sep 2015 17:52:06 -0700 -Subject: [PATCH 49/69] PM / OPP: Support adjusting OPP voltages at runtime On some SoCs the Adaptive Voltage Scaling (AVS) technique is employed to optimize the operating voltage of a device. At a @@ -15,61 +25,57 @@ change. The assumption is that drivers like CPUfreq or devfreq will register for the OPP notifiers and adjust the voltage according to suggestions that AVS makes. -Cc: Nishanth Menon -Acked-by: Viresh Kumar +This patch is derived from [1] submitted by Stephen. +[1] https://lore.kernel.org/patchwork/patch/599279/ + Signed-off-by: Stephen Boyd -Acked-by: Viresh Kumar -Signed-off-by: Georgi Djakov +Signed-off-by: Roger Lu +[s.nawrocki@samsung.com: added handling of OPP min/max voltage] +Signed-off-by: Sylwester Nawrocki --- - drivers/opp/core.c | 77 +++++++++++++++++++++++++++++++++++++++++++ - include/linux/pm_opp.h | 11 +++++++ - 2 files changed, 88 insertions(+) + drivers/opp/core.c | 69 ++++++++++++++++++++++++++++++++++++++++++ + include/linux/pm_opp.h | 13 ++++++++ + 2 files changed, 82 insertions(+) +diff --git a/drivers/opp/core.c b/drivers/opp/core.c +index 3b7ffd0234e9..f38b3be85072 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c -@@ -1625,6 +1625,83 @@ put_table: +@@ -2112,6 +2112,75 @@ static int _opp_set_availability(struct device *dev, unsigned long freq, + return r; } - - /** + ++/** + * dev_pm_opp_adjust_voltage() - helper to change the voltage of an OPP + * @dev: device for which we do this operation + * @freq: OPP frequency to adjust voltage of -+ * @u_volt: new OPP voltage -+ * -+ * Change the voltage of an OPP with an RCU operation. ++ * @u_volt: new OPP target voltage ++ * @u_volt_min: new OPP min voltage ++ * @u_volt_max: new OPP max voltage + * + * Return: -EINVAL for bad pointers, -ENOMEM if no memory available for the + * copy operation, returns 0 if no modifcation was done OR modification was + * successful. -+ * -+ * Locking: The internal device_opp and opp structures are RCU protected. -+ * Hence this function internally uses RCU updater strategy with mutex locks to -+ * keep the integrity of the internal data structures. Callers should ensure -+ * that this function is *NOT* called under RCU protection or in contexts where -+ * mutex locking or synchronize_rcu() blocking calls cannot be used. + */ +int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq, -+ unsigned long u_volt) ++ unsigned long u_volt, unsigned long u_volt_min, ++ unsigned long u_volt_max) ++ +{ + struct opp_table *opp_table; -+ struct dev_pm_opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV); ++ struct dev_pm_opp *tmp_opp, *opp = ERR_PTR(-ENODEV); + int r = 0; + -+ /* keep the node allocated */ -+ new_opp = kmalloc(sizeof(*new_opp), GFP_KERNEL); -+ if (!new_opp) -+ return -ENOMEM; -+ -+ mutex_lock(&opp_table_lock); -+ + /* Find the opp_table */ + opp_table = _find_opp_table(dev); + if (IS_ERR(opp_table)) { + r = PTR_ERR(opp_table); + dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r); -+ goto unlock; ++ return r; + } + ++ mutex_lock(&opp_table->lock); ++ + /* Do we have the frequency? */ + list_for_each_entry(tmp_opp, &opp_table->opp_list, node) { + if (tmp_opp->rate == freq) { @@ -77,67 +83,71 @@ Signed-off-by: Georgi Djakov + break; + } + } ++ + if (IS_ERR(opp)) { + r = PTR_ERR(opp); -+ goto unlock; ++ goto adjust_unlock; + } + + /* Is update really needed? */ -+ if (opp->supplies[0].u_volt == u_volt) -+ goto unlock; -+ /* copy the old data over */ -+ *new_opp = *opp; ++ if (opp->supplies->u_volt == u_volt) ++ goto adjust_unlock; + -+ /* plug in new node */ -+ new_opp->supplies[0].u_volt = u_volt; ++ opp->supplies->u_volt = u_volt; ++ opp->supplies->u_volt_min = u_volt_min; ++ opp->supplies->u_volt_max = u_volt_max; + -+ list_replace(&opp->node, &new_opp->node); -+ mutex_unlock(&opp_table_lock); -+ kfree(opp); ++ dev_pm_opp_get(opp); ++ mutex_unlock(&opp_table->lock); + -+ /* Notify the change of the OPP */ ++ /* Notify the voltage change of the OPP */ + blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_ADJUST_VOLTAGE, -+ new_opp); ++ opp); + -+ return 0; ++ dev_pm_opp_put(opp); ++ goto adjust_put_table; + -+unlock: -+ mutex_unlock(&opp_table_lock); -+ kfree(new_opp); ++adjust_unlock: ++ mutex_unlock(&opp_table->lock); ++adjust_put_table: ++ dev_pm_opp_put_opp_table(opp_table); + return r; +} + -+/** + /** * dev_pm_opp_enable() - Enable a specific OPP * @dev: device for which we do this operation - * @freq: OPP frequency to enable +diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h +index b8197ab014f2..747861816f4f 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h -@@ -25,6 +25,7 @@ struct opp_table; - +@@ -22,6 +22,7 @@ struct opp_table; + enum dev_pm_opp_event { OPP_EVENT_ADD, OPP_EVENT_REMOVE, OPP_EVENT_ENABLE, OPP_EVENT_DISABLE, + OPP_EVENT_ADJUST_VOLTAGE, }; - + /** -@@ -108,6 +109,9 @@ int dev_pm_opp_add(struct device *dev, u - unsigned long u_volt); +@@ -113,6 +114,10 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq, void dev_pm_opp_remove(struct device *dev, unsigned long freq); - + void dev_pm_opp_remove_all_dynamic(struct device *dev); + +int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq, -+ unsigned long u_volt); ++ unsigned long u_volt, unsigned long u_volt_min, ++ unsigned long u_volt_max); + int dev_pm_opp_enable(struct device *dev, unsigned long freq); - + int dev_pm_opp_disable(struct device *dev, unsigned long freq); -@@ -208,6 +212,13 @@ static inline void dev_pm_opp_remove(str +@@ -242,6 +247,14 @@ static inline void dev_pm_opp_remove_all_dynamic(struct device *dev) { } - + +static inline int +dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq, -+ unsigned long u_volt) ++ unsigned long u_volt, unsigned long u_volt_min, ++ unsigned long u_volt_max) +{ + return 0; +} -- 2.30.2