From: Sylwester Nawrocki <s.nawrocki@samsung.com> 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 <sboyd@codeaurora.org>, Sylwester Nawrocki <s.nawrocki@samsung.com> Subject: [PATCH v5 1/4] PM / OPP: Support adjusting OPP voltages at runtime Date: Wed, 16 Oct 2019 16:57:53 +0200 [thread overview] Message-ID: <20191016145756.16004-2-s.nawrocki@samsung.com> (raw) In-Reply-To: <20191016145756.16004-1-s.nawrocki@samsung.com> From: Stephen Boyd <sboyd@codeaurora.org> On some SoCs the Adaptive Voltage Scaling (AVS) technique is employed to optimize the operating voltage of a device. At a given frequency, the hardware monitors dynamic factors and either makes a suggestion for how much to adjust a voltage for the current frequency, or it automatically adjusts the voltage without software intervention. Add an API to the OPP library for the former case, so that AVS type devices can update the voltages for an OPP when the hardware determines the voltage should 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. This patch is derived from [1] submitted by Stephen. [1] https://lore.kernel.org/patchwork/patch/599279/ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> Signed-off-by: Roger Lu <roger.lu@mediatek.com> [s.nawrocki@samsung.com: added handling of OPP min/max voltage] Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> --- 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 @@ -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 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. + */ +int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq, + unsigned long u_volt, unsigned long u_volt_min, + unsigned long u_volt_max) + +{ + struct opp_table *opp_table; + struct dev_pm_opp *tmp_opp, *opp = ERR_PTR(-ENODEV); + int r = 0; + + /* 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); + 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) { + opp = tmp_opp; + break; + } + } + + if (IS_ERR(opp)) { + r = PTR_ERR(opp); + goto adjust_unlock; + } + + /* Is update really needed? */ + if (opp->supplies->u_volt == u_volt) + goto adjust_unlock; + + opp->supplies->u_volt = u_volt; + opp->supplies->u_volt_min = u_volt_min; + opp->supplies->u_volt_max = u_volt_max; + + dev_pm_opp_get(opp); + mutex_unlock(&opp_table->lock); + + /* Notify the voltage change of the OPP */ + blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_ADJUST_VOLTAGE, + opp); + + dev_pm_opp_put(opp); + goto adjust_put_table; + +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 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 @@ -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, }; /** @@ -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_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); @@ -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_min, + unsigned long u_volt_max) +{ + return 0; +} + static inline int dev_pm_opp_enable(struct device *dev, unsigned long freq) { return 0; -- 2.17.1
WARNING: multiple messages have this Message-ID (diff)
From: Sylwester Nawrocki <s.nawrocki@samsung.com> To: krzk@kernel.org, vireshk@kernel.org, robh+dt@kernel.org Cc: devicetree@vger.kernel.org, linux-samsung-soc@vger.kernel.org, linux-pm@vger.kernel.org, sboyd@kernel.org, Stephen Boyd <sboyd@codeaurora.org>, b.zolnierkie@samsung.com, roger.lu@mediatek.com, Sylwester Nawrocki <s.nawrocki@samsung.com>, linux-arm-kernel@lists.infradead.org, m.szyprowski@samsung.com Subject: [PATCH v5 1/4] PM / OPP: Support adjusting OPP voltages at runtime Date: Wed, 16 Oct 2019 16:57:53 +0200 [thread overview] Message-ID: <20191016145756.16004-2-s.nawrocki@samsung.com> (raw) In-Reply-To: <20191016145756.16004-1-s.nawrocki@samsung.com> From: Stephen Boyd <sboyd@codeaurora.org> On some SoCs the Adaptive Voltage Scaling (AVS) technique is employed to optimize the operating voltage of a device. At a given frequency, the hardware monitors dynamic factors and either makes a suggestion for how much to adjust a voltage for the current frequency, or it automatically adjusts the voltage without software intervention. Add an API to the OPP library for the former case, so that AVS type devices can update the voltages for an OPP when the hardware determines the voltage should 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. This patch is derived from [1] submitted by Stephen. [1] https://lore.kernel.org/patchwork/patch/599279/ Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> Signed-off-by: Roger Lu <roger.lu@mediatek.com> [s.nawrocki@samsung.com: added handling of OPP min/max voltage] Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> --- 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 @@ -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 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. + */ +int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq, + unsigned long u_volt, unsigned long u_volt_min, + unsigned long u_volt_max) + +{ + struct opp_table *opp_table; + struct dev_pm_opp *tmp_opp, *opp = ERR_PTR(-ENODEV); + int r = 0; + + /* 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); + 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) { + opp = tmp_opp; + break; + } + } + + if (IS_ERR(opp)) { + r = PTR_ERR(opp); + goto adjust_unlock; + } + + /* Is update really needed? */ + if (opp->supplies->u_volt == u_volt) + goto adjust_unlock; + + opp->supplies->u_volt = u_volt; + opp->supplies->u_volt_min = u_volt_min; + opp->supplies->u_volt_max = u_volt_max; + + dev_pm_opp_get(opp); + mutex_unlock(&opp_table->lock); + + /* Notify the voltage change of the OPP */ + blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_ADJUST_VOLTAGE, + opp); + + dev_pm_opp_put(opp); + goto adjust_put_table; + +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 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 @@ -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, }; /** @@ -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_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); @@ -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_min, + unsigned long u_volt_max) +{ + return 0; +} + static inline int dev_pm_opp_enable(struct device *dev, unsigned long freq) { return 0; -- 2.17.1 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2019-10-16 14:58 UTC|newest] Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top [not found] <CGME20191016145806eucas1p2d522901fc79e1ca6e03f1bb516a81370@eucas1p2.samsung.com> 2019-10-16 14:57 ` [PATCH v5 0/4] Exynos Adaptive Supply Voltage support Sylwester Nawrocki 2019-10-16 14:57 ` Sylwester Nawrocki [not found] ` <CGME20191016145810eucas1p1b31400c9b2e7f30cdf6deeb4ccee2788@eucas1p1.samsung.com> 2019-10-16 14:57 ` Sylwester Nawrocki [this message] 2019-10-16 14:57 ` [PATCH v5 1/4] PM / OPP: Support adjusting OPP voltages at runtime Sylwester Nawrocki 2019-10-17 6:42 ` Viresh Kumar 2019-10-17 6:42 ` Viresh Kumar 2019-10-21 11:23 ` Krzysztof Kozlowski 2019-10-21 11:23 ` Krzysztof Kozlowski 2019-10-22 2:23 ` Viresh Kumar 2019-10-22 2:23 ` Viresh Kumar 2019-10-22 18:43 ` Krzysztof Kozlowski 2019-10-22 18:43 ` Krzysztof Kozlowski [not found] ` <CGME20191016145812eucas1p1a3cf3f44a2cff4c32a2270334630c4a2@eucas1p1.samsung.com> 2019-10-16 14:57 ` [PATCH v5 2/4] dt-bindings: arm: samsung: Update the CHIPID binding for ASV Sylwester Nawrocki 2019-10-16 14:57 ` Sylwester Nawrocki 2019-10-16 16:16 ` Krzysztof Kozlowski 2019-10-16 16:16 ` Krzysztof Kozlowski 2019-10-17 9:03 ` Sylwester Nawrocki 2019-10-17 9:03 ` Sylwester Nawrocki [not found] ` <CGME20191016145813eucas1p1623db169f1ee93f88cb2c75090804747@eucas1p1.samsung.com> 2019-10-16 14:57 ` [PATCH v5 3/4] soc: samsung: Add Exynos Adaptive Supply Voltage driver Sylwester Nawrocki 2019-10-16 14:57 ` Sylwester Nawrocki 2019-10-22 19:04 ` Krzysztof Kozlowski 2019-10-22 19:04 ` Krzysztof Kozlowski 2019-10-23 10:48 ` Sylwester Nawrocki 2019-10-23 10:48 ` Sylwester Nawrocki 2019-10-23 11:20 ` Krzysztof Kozlowski 2019-10-23 11:20 ` Krzysztof Kozlowski [not found] ` <CGME20191016145814eucas1p10d50d438abb850fd82f622122b223196@eucas1p1.samsung.com> 2019-10-16 14:57 ` [PATCH v5 4/4] ARM: EXYNOS: Enable exynos-asv driver for ARCH_EXYNOS Sylwester Nawrocki 2019-10-16 14:57 ` Sylwester Nawrocki
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20191016145756.16004-2-s.nawrocki@samsung.com \ --to=s.nawrocki@samsung.com \ --cc=b.zolnierkie@samsung.com \ --cc=devicetree@vger.kernel.org \ --cc=krzk@kernel.org \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-pm@vger.kernel.org \ --cc=linux-samsung-soc@vger.kernel.org \ --cc=m.szyprowski@samsung.com \ --cc=robh+dt@kernel.org \ --cc=roger.lu@mediatek.com \ --cc=sboyd@codeaurora.org \ --cc=sboyd@kernel.org \ --cc=vireshk@kernel.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.