From 18b380ed61f892ed06838d1f1a5124d966292ed3 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 14 May 2021 14:48:43 +0800 Subject: [PATCH 01/12] PM / devfreq: Add missing error code in devfreq_add_device() Set err code in the error path before jumping to the end of the function. Fixes: 4dc3bab8687f ("PM / devfreq: Add support delayed timer for polling mode") Signed-off-by: YueHaibing Signed-off-by: Chanwoo Choi --- drivers/devfreq/devfreq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index fe08c46642f7..28f3e0ba6cdd 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -823,6 +823,7 @@ struct devfreq *devfreq_add_device(struct device *dev, if (devfreq->profile->timer < 0 || devfreq->profile->timer >= DEVFREQ_TIMER_NUM) { mutex_unlock(&devfreq->lock); + err = -EINVAL; goto err_dev; } From 7dbc0d246891acbb8ae5840b3237881b7a0787df Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Wed, 19 May 2021 15:05:44 +0800 Subject: [PATCH 02/12] PM / devfreq: imx-bus: Remove imx_bus_get_dev_status Current driver actually does not support simple ondemand governor as it's unable to provide device load information. So removing the unnecessary callback to avoid confusing. Right now the driver is using userspace governor by default. polling_ms was also dropped as it's not needed for non-ondemand governor. Signed-off-by: Dong Aisheng Signed-off-by: Chanwoo Choi --- drivers/devfreq/imx-bus.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/devfreq/imx-bus.c b/drivers/devfreq/imx-bus.c index 3fc3fd77492d..f3f6e25053ed 100644 --- a/drivers/devfreq/imx-bus.c +++ b/drivers/devfreq/imx-bus.c @@ -45,18 +45,6 @@ static int imx_bus_get_cur_freq(struct device *dev, unsigned long *freq) return 0; } -static int imx_bus_get_dev_status(struct device *dev, - struct devfreq_dev_status *stat) -{ - struct imx_bus *priv = dev_get_drvdata(dev); - - stat->busy_time = 0; - stat->total_time = 0; - stat->current_frequency = clk_get_rate(priv->clk); - - return 0; -} - static void imx_bus_exit(struct device *dev) { struct imx_bus *priv = dev_get_drvdata(dev); @@ -129,9 +117,7 @@ static int imx_bus_probe(struct platform_device *pdev) return ret; } - priv->profile.polling_ms = 1000; priv->profile.target = imx_bus_target; - priv->profile.get_dev_status = imx_bus_get_dev_status; priv->profile.exit = imx_bus_exit; priv->profile.get_cur_freq = imx_bus_get_cur_freq; priv->profile.initial_freq = clk_get_rate(priv->clk); From 5e480ab94db8102baa73da33534e708a8636c2f9 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Tue, 11 May 2021 00:10:02 +0300 Subject: [PATCH 03/12] PM / devfreq: tegra30: Support thermal cooling Expose ACTMON devfreq device as a cooling device in order to throttle memory freq on overheat. Throttling of memory freq has a significant cooling effect on NVIDIA Tegra SoCs since higher memory freqs require higher SoC core voltage which is one of the main causes of the heating. Signed-off-by: Dmitry Osipenko Signed-off-by: Chanwoo Choi --- drivers/devfreq/tegra30-devfreq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/devfreq/tegra30-devfreq.c b/drivers/devfreq/tegra30-devfreq.c index ce83f883ca65..10661eb2aed8 100644 --- a/drivers/devfreq/tegra30-devfreq.c +++ b/drivers/devfreq/tegra30-devfreq.c @@ -688,6 +688,7 @@ static struct devfreq_dev_profile tegra_devfreq_profile = { .polling_ms = ACTMON_SAMPLING_PERIOD, .target = tegra_devfreq_target, .get_dev_status = tegra_devfreq_get_dev_status, + .is_cooling_device = true, }; static int tegra_governor_get_target(struct devfreq *devfreq, From a15fc9aa5b384e305ea25f42f744bb301fe39da0 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 21 May 2021 11:16:39 +0800 Subject: [PATCH 04/12] PM / devfreq: imx8m-ddrc: Remove DEVFREQ_GOV_SIMPLE_ONDEMAND dependency The driver can't support simple ondemand governor due to missing .get_dev_status() capability. Signed-off-by: Dong Aisheng Signed-off-by: Chanwoo Choi --- drivers/devfreq/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig index 20373a893b44..e87d01c0b76a 100644 --- a/drivers/devfreq/Kconfig +++ b/drivers/devfreq/Kconfig @@ -103,7 +103,6 @@ config ARM_IMX8M_DDRC_DEVFREQ tristate "i.MX8M DDRC DEVFREQ Driver" depends on (ARCH_MXC && HAVE_ARM_SMCCC) || \ (COMPILE_TEST && HAVE_ARM_SMCCC) - select DEVFREQ_GOV_SIMPLE_ONDEMAND select DEVFREQ_GOV_USERSPACE help This adds the DEVFREQ driver for the i.MX8M DDR Controller. It allows From 763663c9715f5f1cc0d065d2b020f12cd37417d2 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Wed, 12 May 2021 15:25:15 +0800 Subject: [PATCH 05/12] PM: domains: fix some kernel-doc issues Fix the following make W=1 kernel build warnings: drivers/base/power/domain_governor.c:259: warning: Function parameter or member 'now' not described in '_default_power_down_ok' drivers/base/power/domain.c:581: warning: Function parameter or member 'depth' not described in 'genpd_power_off' drivers/base/power/domain.c:2520: warning: Function parameter or member 'np' not described in 'of_genpd_remove_last' drivers/base/power/domain.c:2520: warning: Excess function parameter 'provider' description in 'of_genpd_remove_last' Signed-off-by: Yang Yingliang Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 3 ++- drivers/base/power/domain_governor.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index b6a782c31613..5695a641efd3 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -572,6 +572,7 @@ static void genpd_queue_power_off_work(struct generic_pm_domain *genpd) * RPM status of the releated device is in an intermediate state, not yet turned * into RPM_SUSPENDED. This means genpd_power_off() must allow one device to not * be RPM_SUSPENDED, while it tries to power off the PM domain. + * @depth: nesting count for lockdep. * * If all of the @genpd's devices have been suspended and all of its subdomains * have been powered down, remove power from @genpd. @@ -2505,7 +2506,7 @@ EXPORT_SYMBOL_GPL(of_genpd_remove_subdomain); /** * of_genpd_remove_last - Remove the last PM domain registered for a provider - * @provider: Pointer to device structure associated with provider + * @np: Pointer to device node associated with provider * * Find the last PM domain that was added by a particular provider and * remove this PM domain from the list of PM domains. The provider is diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c index c6c218758f0b..cd08c5885190 100644 --- a/drivers/base/power/domain_governor.c +++ b/drivers/base/power/domain_governor.c @@ -252,6 +252,7 @@ static bool __default_power_down_ok(struct dev_pm_domain *pd, /** * _default_power_down_ok - Default generic PM domain power off governor routine. * @pd: PM domain to check. + * @now: current ktime. * * This routine must be executed under the PM domain's lock. */ From 0eef091d2dc447e10607f6dafa173c311ada972b Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 3 Jun 2021 11:34:35 +0200 Subject: [PATCH 06/12] PM: domains: Split code in dev_pm_genpd_set_performance_state() To prepare some of the code in dev_pm_genpd_set_performance_state() to be re-used from subsequent changes, let's split it up into two functions. Reviewed-by: Viresh Kumar Signed-off-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 5695a641efd3..ede0f576efe6 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -379,6 +379,24 @@ static int _genpd_set_performance_state(struct generic_pm_domain *genpd, return ret; } +static int genpd_set_performance_state(struct device *dev, unsigned int state) +{ + struct generic_pm_domain *genpd = dev_to_genpd(dev); + struct generic_pm_domain_data *gpd_data = dev_gpd_data(dev); + unsigned int prev_state; + int ret; + + prev_state = gpd_data->performance_state; + gpd_data->performance_state = state; + state = _genpd_reeval_performance_state(genpd, state); + + ret = _genpd_set_performance_state(genpd, state, 0); + if (ret) + gpd_data->performance_state = prev_state; + + return ret; +} + /** * dev_pm_genpd_set_performance_state- Set performance state of device's power * domain. @@ -397,8 +415,6 @@ static int _genpd_set_performance_state(struct generic_pm_domain *genpd, int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state) { struct generic_pm_domain *genpd; - struct generic_pm_domain_data *gpd_data; - unsigned int prev; int ret; genpd = dev_to_genpd_safe(dev); @@ -410,16 +426,7 @@ int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state) return -EINVAL; genpd_lock(genpd); - - gpd_data = to_gpd_data(dev->power.subsys_data->domain_data); - prev = gpd_data->performance_state; - gpd_data->performance_state = state; - - state = _genpd_reeval_performance_state(genpd, state); - ret = _genpd_set_performance_state(genpd, state, 0); - if (ret) - gpd_data->performance_state = prev; - + ret = genpd_set_performance_state(dev, state); genpd_unlock(genpd); return ret; From d97fe100ee0b36c5dd8013ffd70fe8fcdcabff2b Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 3 Jun 2021 11:34:36 +0200 Subject: [PATCH 07/12] PM: domains: Return early if perf state is already set for the device When dev_pm_genpd_set_performance_state() gets called to set a new performance state for the device, let's take a quicker path by doing an early return, if it turns out that the new state is already set for the device. Suggested-by: Viresh Kumar Signed-off-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index ede0f576efe6..90a9828fcb2f 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -387,6 +387,9 @@ static int genpd_set_performance_state(struct device *dev, unsigned int state) int ret; prev_state = gpd_data->performance_state; + if (prev_state == state) + return 0; + gpd_data->performance_state = state; state = _genpd_reeval_performance_state(genpd, state); From 5937c3ce21228d33d2eb3287baa7e4cf6978dba9 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 3 Jun 2021 11:34:37 +0200 Subject: [PATCH 08/12] PM: domains: Drop/restore performance state votes for devices at runtime PM A subsystem/driver that need to manage OPPs for its device, should typically drop its vote for the OPP when the device becomes runtime suspended. In this way, the corresponding aggregation of the performance state votes that is managed in genpd for the attached PM domain, may find that the aggregated vote can be decreased. Hence, it may allow genpd to set the lower performance state for the PM domain, thus avoiding to waste energy. To accomplish this, typically a subsystem/driver would need to call dev_pm_opp_set_rate|opp() for its device from its ->runtime_suspend() callback, to drop the vote for the OPP. Accordingly, it needs another call to dev_pm_opp_set_rate|opp() to restore the vote for the OPP from its ->runtime_resume() callback. To avoid boilerplate code in subsystems/driver to deal with these things, let's instead manage this internally in genpd. Signed-off-by: Ulf Hansson Tested-by: Dmitry Osipenko Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 27 +++++++++++++++++++++++++-- include/linux/pm_domain.h | 1 + 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 90a9828fcb2f..ab0b740cc0f1 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -400,6 +400,23 @@ static int genpd_set_performance_state(struct device *dev, unsigned int state) return ret; } +static int genpd_drop_performance_state(struct device *dev) +{ + unsigned int prev_state = dev_gpd_data(dev)->performance_state; + + if (!genpd_set_performance_state(dev, 0)) + return prev_state; + + return 0; +} + +static void genpd_restore_performance_state(struct device *dev, + unsigned int state) +{ + if (state) + genpd_set_performance_state(dev, state); +} + /** * dev_pm_genpd_set_performance_state- Set performance state of device's power * domain. @@ -843,7 +860,8 @@ static int genpd_runtime_suspend(struct device *dev) { struct generic_pm_domain *genpd; bool (*suspend_ok)(struct device *__dev); - struct gpd_timing_data *td = &dev_gpd_data(dev)->td; + struct generic_pm_domain_data *gpd_data = dev_gpd_data(dev); + struct gpd_timing_data *td = &gpd_data->td; bool runtime_pm = pm_runtime_enabled(dev); ktime_t time_start; s64 elapsed_ns; @@ -900,6 +918,7 @@ static int genpd_runtime_suspend(struct device *dev) return 0; genpd_lock(genpd); + gpd_data->rpm_pstate = genpd_drop_performance_state(dev); genpd_power_off(genpd, true, 0); genpd_unlock(genpd); @@ -917,7 +936,8 @@ static int genpd_runtime_suspend(struct device *dev) static int genpd_runtime_resume(struct device *dev) { struct generic_pm_domain *genpd; - struct gpd_timing_data *td = &dev_gpd_data(dev)->td; + struct generic_pm_domain_data *gpd_data = dev_gpd_data(dev); + struct gpd_timing_data *td = &gpd_data->td; bool runtime_pm = pm_runtime_enabled(dev); ktime_t time_start; s64 elapsed_ns; @@ -941,6 +961,8 @@ static int genpd_runtime_resume(struct device *dev) genpd_lock(genpd); ret = genpd_power_on(genpd, 0); + if (!ret) + genpd_restore_performance_state(dev, gpd_data->rpm_pstate); genpd_unlock(genpd); if (ret) @@ -979,6 +1001,7 @@ static int genpd_runtime_resume(struct device *dev) err_poweroff: if (!pm_runtime_is_irq_safe(dev) || genpd_is_irq_safe(genpd)) { genpd_lock(genpd); + gpd_data->rpm_pstate = genpd_drop_performance_state(dev); genpd_power_off(genpd, true, 0); genpd_unlock(genpd); } diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index dfcfbcecc34b..21a0577305ef 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -198,6 +198,7 @@ struct generic_pm_domain_data { struct notifier_block *power_nb; int cpu; unsigned int performance_state; + unsigned int rpm_pstate; ktime_t next_wakeup; void *data; }; From 1ad4f329fccb5d9eb7b0a38d7fdf0f4688c6b341 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Mon, 24 May 2021 10:11:58 +0800 Subject: [PATCH 09/12] PM / devfreq: userspace: Use DEVICE_ATTR_RW macro Use DEVICE_ATTR_RW helper instead of plain DEVICE_ATTR, which makes the code a bit shorter and easier to read. Signed-off-by: YueHaibing Signed-off-by: Chanwoo Choi --- drivers/devfreq/governor_userspace.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/devfreq/governor_userspace.c b/drivers/devfreq/governor_userspace.c index 0fd6c4851071..ab9db7adb3ad 100644 --- a/drivers/devfreq/governor_userspace.c +++ b/drivers/devfreq/governor_userspace.c @@ -31,8 +31,8 @@ static int devfreq_userspace_func(struct devfreq *df, unsigned long *freq) return 0; } -static ssize_t store_freq(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t set_freq_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct devfreq *devfreq = to_devfreq(dev); struct userspace_data *data; @@ -52,8 +52,8 @@ static ssize_t store_freq(struct device *dev, struct device_attribute *attr, return err; } -static ssize_t show_freq(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t set_freq_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct devfreq *devfreq = to_devfreq(dev); struct userspace_data *data; @@ -70,7 +70,7 @@ static ssize_t show_freq(struct device *dev, struct device_attribute *attr, return err; } -static DEVICE_ATTR(set_freq, 0644, show_freq, store_freq); +static DEVICE_ATTR_RW(set_freq); static struct attribute *dev_entries[] = { &dev_attr_set_freq.attr, NULL, From 271ca53cb0c8b3a45c73e1140fc3336c2da42315 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Tue, 1 Jun 2021 05:23:18 +0300 Subject: [PATCH 10/12] dt-bindings: devfreq: tegra30-actmon: Convert to schema Convert NVIDIA Tegra ACTMON binding to schema. Reviewed-by: Rob Herring Acked-by: Chanwoo Choi Acked-by: Thierry Reding Signed-off-by: Dmitry Osipenko Signed-off-by: Chanwoo Choi --- .../arm/tegra/nvidia,tegra30-actmon.txt | 57 --------- .../devfreq/nvidia,tegra30-actmon.yaml | 121 ++++++++++++++++++ 2 files changed, 121 insertions(+), 57 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-actmon.txt create mode 100644 Documentation/devicetree/bindings/devfreq/nvidia,tegra30-actmon.yaml diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-actmon.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-actmon.txt deleted file mode 100644 index 897eedfa2bc8..000000000000 --- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-actmon.txt +++ /dev/null @@ -1,57 +0,0 @@ -NVIDIA Tegra Activity Monitor - -The activity monitor block collects statistics about the behaviour of other -components in the system. This information can be used to derive the rate at -which the external memory needs to be clocked in order to serve all requests -from the monitored clients. - -Required properties: -- compatible: should be "nvidia,tegra-actmon" -- reg: offset and length of the register set for the device -- interrupts: standard interrupt property -- clocks: Must contain a phandle and clock specifier pair for each entry in -clock-names. See ../../clock/clock-bindings.txt for details. -- clock-names: Must include the following entries: - - actmon - - emc -- resets: Must contain an entry for each entry in reset-names. See -../../reset/reset.txt for details. -- reset-names: Must include the following entries: - - actmon -- operating-points-v2: See ../bindings/opp/opp.txt for details. -- interconnects: Should contain entries for memory clients sitting on - MC->EMC memory interconnect path. -- interconnect-names: Should include name of the interconnect path for each - interconnect entry. Consult TRM documentation for - information about available memory clients, see MEMORY - CONTROLLER section. - -For each opp entry in 'operating-points-v2' table: -- opp-supported-hw: bitfield indicating SoC speedo ID mask -- opp-peak-kBps: peak bandwidth of the memory channel - -Example: - dfs_opp_table: opp-table { - compatible = "operating-points-v2"; - - opp@12750000 { - opp-hz = /bits/ 64 <12750000>; - opp-supported-hw = <0x000F>; - opp-peak-kBps = <51000>; - }; - ... - }; - - actmon@6000c800 { - compatible = "nvidia,tegra124-actmon"; - reg = <0x0 0x6000c800 0x0 0x400>; - interrupts = ; - clocks = <&tegra_car TEGRA124_CLK_ACTMON>, - <&tegra_car TEGRA124_CLK_EMC>; - clock-names = "actmon", "emc"; - resets = <&tegra_car 119>; - reset-names = "actmon"; - operating-points-v2 = <&dfs_opp_table>; - interconnects = <&mc TEGRA124_MC_MPCORER &emc>; - interconnect-names = "cpu"; - }; diff --git a/Documentation/devicetree/bindings/devfreq/nvidia,tegra30-actmon.yaml b/Documentation/devicetree/bindings/devfreq/nvidia,tegra30-actmon.yaml new file mode 100644 index 000000000000..ba938eed28ee --- /dev/null +++ b/Documentation/devicetree/bindings/devfreq/nvidia,tegra30-actmon.yaml @@ -0,0 +1,121 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/devfreq/nvidia,tegra30-actmon.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NVIDIA Tegra30 Activity Monitor + +maintainers: + - Dmitry Osipenko + - Jon Hunter + - Thierry Reding + +description: | + The activity monitor block collects statistics about the behaviour of other + components in the system. This information can be used to derive the rate at + which the external memory needs to be clocked in order to serve all requests + from the monitored clients. + +properties: + compatible: + enum: + - nvidia,tegra30-actmon + - nvidia,tegra114-actmon + - nvidia,tegra124-actmon + - nvidia,tegra210-actmon + + reg: + maxItems: 1 + + clocks: + maxItems: 2 + + clock-names: + items: + - const: actmon + - const: emc + + resets: + maxItems: 1 + + reset-names: + items: + - const: actmon + + interrupts: + maxItems: 1 + + interconnects: + minItems: 1 + maxItems: 12 + + interconnect-names: + minItems: 1 + maxItems: 12 + description: + Should include name of the interconnect path for each interconnect + entry. Consult TRM documentation for information about available + memory clients, see MEMORY CONTROLLER and ACTIVITY MONITOR sections. + + operating-points-v2: + description: + Should contain freqs and voltages and opp-supported-hw property, which + is a bitfield indicating SoC speedo ID mask. + +required: + - compatible + - reg + - clocks + - clock-names + - resets + - reset-names + - interrupts + - interconnects + - interconnect-names + - operating-points-v2 + +additionalProperties: false + +examples: + - | + #include + + mc: memory-controller@7000f000 { + compatible = "nvidia,tegra30-mc"; + reg = <0x7000f000 0x400>; + clocks = <&clk 32>; + clock-names = "mc"; + + interrupts = <0 77 4>; + + #iommu-cells = <1>; + #reset-cells = <1>; + #interconnect-cells = <1>; + }; + + emc: external-memory-controller@7000f400 { + compatible = "nvidia,tegra30-emc"; + reg = <0x7000f400 0x400>; + interrupts = <0 78 4>; + clocks = <&clk 57>; + + nvidia,memory-controller = <&mc>; + operating-points-v2 = <&dvfs_opp_table>; + power-domains = <&domain>; + + #interconnect-cells = <0>; + }; + + actmon@6000c800 { + compatible = "nvidia,tegra30-actmon"; + reg = <0x6000c800 0x400>; + interrupts = <0 45 4>; + clocks = <&clk 119>, <&clk 57>; + clock-names = "actmon", "emc"; + resets = <&rst 119>; + reset-names = "actmon"; + operating-points-v2 = <&dvfs_opp_table>; + interconnects = <&mc TEGRA30_MC_MPCORER &emc>; + interconnect-names = "cpu-read"; + }; From 6b61f55ecbe693d9d0d7ae14ebce01dabe10ecf1 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Tue, 1 Jun 2021 05:23:19 +0300 Subject: [PATCH 11/12] dt-bindings: devfreq: tegra30-actmon: Add cooling-cells The ACTMON watches activity of memory clients. Decisions about a minimum required frequency are made based on the info from ACTMON. We can use ACTMON as a thermal cooling device by limiting the required frequency. Document new cooling-cells property of NVIDIA Tegra ACTMON hardware unit. Reviewed-by: Rob Herring Acked-by: Chanwoo Choi Acked-by: Thierry Reding Signed-off-by: Dmitry Osipenko Signed-off-by: Chanwoo Choi --- .../devicetree/bindings/devfreq/nvidia,tegra30-actmon.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/devfreq/nvidia,tegra30-actmon.yaml b/Documentation/devicetree/bindings/devfreq/nvidia,tegra30-actmon.yaml index ba938eed28ee..e3379d106728 100644 --- a/Documentation/devicetree/bindings/devfreq/nvidia,tegra30-actmon.yaml +++ b/Documentation/devicetree/bindings/devfreq/nvidia,tegra30-actmon.yaml @@ -63,6 +63,9 @@ properties: Should contain freqs and voltages and opp-supported-hw property, which is a bitfield indicating SoC speedo ID mask. + "#cooling-cells": + const: 2 + required: - compatible - reg @@ -74,6 +77,7 @@ required: - interconnects - interconnect-names - operating-points-v2 + - "#cooling-cells" additionalProperties: false @@ -118,4 +122,5 @@ examples: operating-points-v2 = <&dvfs_opp_table>; interconnects = <&mc TEGRA30_MC_MPCORER &emc>; interconnect-names = "cpu-read"; + #cooling-cells = <2>; }; From 8c37d01e1a86073d15ea7084390fba58d9a1665f Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 17 Jun 2021 15:05:43 +0900 Subject: [PATCH 12/12] PM / devfreq: passive: Fix get_target_freq when not using required-opp The 86ad9a24f21e ("PM / devfreq: Add required OPPs support to passive governor") supported the required-opp property for using devfreq passive governor. But, 86ad9a24f21e has caused the problem on use-case when required-opp is not used such as exynos-bus.c devfreq driver. So that fix the get_target_freq of passive governor for supporting the case of when required-opp is not used. Fixes: 86ad9a24f21e ("PM / devfreq: Add required OPPs support to passive governor") Signed-off-by: Chanwoo Choi --- drivers/devfreq/governor_passive.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/devfreq/governor_passive.c b/drivers/devfreq/governor_passive.c index b094132bd20b..fc09324a03e0 100644 --- a/drivers/devfreq/governor_passive.c +++ b/drivers/devfreq/governor_passive.c @@ -65,7 +65,7 @@ static int devfreq_passive_get_target_freq(struct devfreq *devfreq, dev_pm_opp_put(p_opp); if (IS_ERR(opp)) - return PTR_ERR(opp); + goto no_required_opp; *freq = dev_pm_opp_get_freq(opp); dev_pm_opp_put(opp); @@ -73,6 +73,7 @@ static int devfreq_passive_get_target_freq(struct devfreq *devfreq, return 0; } +no_required_opp: /* * Get the OPP table's index of decided frequency by governor * of parent device.