mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-30 10:39:04 +00:00
mediatek: backport cpufreq changes to support MT7988
Backport cpufreq changes from upstream so that the MediaTek MT7988 SoC
can be supported.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
(cherry picked from commit e4555d69a1
)
This commit is contained in:
parent
fd17917951
commit
670dedbbd7
@ -0,0 +1,166 @@
|
||||
From 7a768326fdba542144833b9198a6d0edab52fad2 Mon Sep 17 00:00:00 2001
|
||||
From: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Date: Fri, 8 Apr 2022 12:58:56 +0800
|
||||
Subject: [PATCH 01/21] cpufreq: mediatek: Cleanup variables and error handling
|
||||
in mtk_cpu_dvfs_info_init()
|
||||
|
||||
- Remove several unnecessary varaibles in mtk_cpu_dvfs_info_init().
|
||||
- Unify error message format and use dev_err_probe() if possible.
|
||||
|
||||
Signed-off-by: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Signed-off-by: Rex-BC Chen <rex-bc.chen@mediatek.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 89 ++++++++++++------------------
|
||||
1 file changed, 34 insertions(+), 55 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -302,96 +302,75 @@ static int mtk_cpufreq_set_target(struct
|
||||
static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
|
||||
{
|
||||
struct device *cpu_dev;
|
||||
- struct regulator *proc_reg = ERR_PTR(-ENODEV);
|
||||
- struct regulator *sram_reg = ERR_PTR(-ENODEV);
|
||||
- struct clk *cpu_clk = ERR_PTR(-ENODEV);
|
||||
- struct clk *inter_clk = ERR_PTR(-ENODEV);
|
||||
struct dev_pm_opp *opp;
|
||||
unsigned long rate;
|
||||
int ret;
|
||||
|
||||
cpu_dev = get_cpu_device(cpu);
|
||||
if (!cpu_dev) {
|
||||
- pr_err("failed to get cpu%d device\n", cpu);
|
||||
+ dev_err(cpu_dev, "failed to get cpu%d device\n", cpu);
|
||||
return -ENODEV;
|
||||
}
|
||||
+ info->cpu_dev = cpu_dev;
|
||||
|
||||
- cpu_clk = clk_get(cpu_dev, "cpu");
|
||||
- if (IS_ERR(cpu_clk)) {
|
||||
- if (PTR_ERR(cpu_clk) == -EPROBE_DEFER)
|
||||
- pr_warn("cpu clk for cpu%d not ready, retry.\n", cpu);
|
||||
- else
|
||||
- pr_err("failed to get cpu clk for cpu%d\n", cpu);
|
||||
-
|
||||
- ret = PTR_ERR(cpu_clk);
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- inter_clk = clk_get(cpu_dev, "intermediate");
|
||||
- if (IS_ERR(inter_clk)) {
|
||||
- if (PTR_ERR(inter_clk) == -EPROBE_DEFER)
|
||||
- pr_warn("intermediate clk for cpu%d not ready, retry.\n",
|
||||
- cpu);
|
||||
- else
|
||||
- pr_err("failed to get intermediate clk for cpu%d\n",
|
||||
- cpu);
|
||||
+ info->cpu_clk = clk_get(cpu_dev, "cpu");
|
||||
+ if (IS_ERR(info->cpu_clk)) {
|
||||
+ ret = PTR_ERR(info->cpu_clk);
|
||||
+ return dev_err_probe(cpu_dev, ret,
|
||||
+ "cpu%d: failed to get cpu clk\n", cpu);
|
||||
+ }
|
||||
|
||||
- ret = PTR_ERR(inter_clk);
|
||||
+ info->inter_clk = clk_get(cpu_dev, "intermediate");
|
||||
+ if (IS_ERR(info->inter_clk)) {
|
||||
+ ret = PTR_ERR(info->inter_clk);
|
||||
+ dev_err_probe(cpu_dev, ret,
|
||||
+ "cpu%d: failed to get intermediate clk\n", cpu);
|
||||
goto out_free_resources;
|
||||
}
|
||||
|
||||
- proc_reg = regulator_get_optional(cpu_dev, "proc");
|
||||
- if (IS_ERR(proc_reg)) {
|
||||
- if (PTR_ERR(proc_reg) == -EPROBE_DEFER)
|
||||
- pr_warn("proc regulator for cpu%d not ready, retry.\n",
|
||||
- cpu);
|
||||
- else
|
||||
- pr_err("failed to get proc regulator for cpu%d\n",
|
||||
- cpu);
|
||||
-
|
||||
- ret = PTR_ERR(proc_reg);
|
||||
+ info->proc_reg = regulator_get_optional(cpu_dev, "proc");
|
||||
+ if (IS_ERR(info->proc_reg)) {
|
||||
+ ret = PTR_ERR(info->proc_reg);
|
||||
+ dev_err_probe(cpu_dev, ret,
|
||||
+ "cpu%d: failed to get proc regulator\n", cpu);
|
||||
goto out_free_resources;
|
||||
}
|
||||
|
||||
/* Both presence and absence of sram regulator are valid cases. */
|
||||
- sram_reg = regulator_get_exclusive(cpu_dev, "sram");
|
||||
+ info->sram_reg = regulator_get_exclusive(cpu_dev, "sram");
|
||||
+ if (IS_ERR(info->sram_reg))
|
||||
+ info->sram_reg = NULL;
|
||||
|
||||
/* Get OPP-sharing information from "operating-points-v2" bindings */
|
||||
ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, &info->cpus);
|
||||
if (ret) {
|
||||
- pr_err("failed to get OPP-sharing information for cpu%d\n",
|
||||
- cpu);
|
||||
+ dev_err(cpu_dev,
|
||||
+ "cpu%d: failed to get OPP-sharing information\n", cpu);
|
||||
goto out_free_resources;
|
||||
}
|
||||
|
||||
ret = dev_pm_opp_of_cpumask_add_table(&info->cpus);
|
||||
if (ret) {
|
||||
- pr_warn("no OPP table for cpu%d\n", cpu);
|
||||
+ dev_warn(cpu_dev, "cpu%d: no OPP table\n", cpu);
|
||||
goto out_free_resources;
|
||||
}
|
||||
|
||||
/* Search a safe voltage for intermediate frequency. */
|
||||
- rate = clk_get_rate(inter_clk);
|
||||
+ rate = clk_get_rate(info->inter_clk);
|
||||
opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
|
||||
if (IS_ERR(opp)) {
|
||||
- pr_err("failed to get intermediate opp for cpu%d\n", cpu);
|
||||
+ dev_err(cpu_dev, "cpu%d: failed to get intermediate opp\n", cpu);
|
||||
ret = PTR_ERR(opp);
|
||||
goto out_free_opp_table;
|
||||
}
|
||||
info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
- info->cpu_dev = cpu_dev;
|
||||
- info->proc_reg = proc_reg;
|
||||
- info->sram_reg = IS_ERR(sram_reg) ? NULL : sram_reg;
|
||||
- info->cpu_clk = cpu_clk;
|
||||
- info->inter_clk = inter_clk;
|
||||
-
|
||||
/*
|
||||
* If SRAM regulator is present, software "voltage tracking" is needed
|
||||
* for this CPU power domain.
|
||||
*/
|
||||
- info->need_voltage_tracking = !IS_ERR(sram_reg);
|
||||
+ info->need_voltage_tracking = (info->sram_reg != NULL);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -399,14 +378,14 @@ out_free_opp_table:
|
||||
dev_pm_opp_of_cpumask_remove_table(&info->cpus);
|
||||
|
||||
out_free_resources:
|
||||
- if (!IS_ERR(proc_reg))
|
||||
- regulator_put(proc_reg);
|
||||
- if (!IS_ERR(sram_reg))
|
||||
- regulator_put(sram_reg);
|
||||
- if (!IS_ERR(cpu_clk))
|
||||
- clk_put(cpu_clk);
|
||||
- if (!IS_ERR(inter_clk))
|
||||
- clk_put(inter_clk);
|
||||
+ if (!IS_ERR(info->proc_reg))
|
||||
+ regulator_put(info->proc_reg);
|
||||
+ if (!IS_ERR(info->sram_reg))
|
||||
+ regulator_put(info->sram_reg);
|
||||
+ if (!IS_ERR(info->cpu_clk))
|
||||
+ clk_put(info->cpu_clk);
|
||||
+ if (!IS_ERR(info->inter_clk))
|
||||
+ clk_put(info->inter_clk);
|
||||
|
||||
return ret;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
From 756104b856d4bc3121420af3ced342f5fc2b2123 Mon Sep 17 00:00:00 2001
|
||||
From: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Date: Fri, 8 Apr 2022 12:58:57 +0800
|
||||
Subject: [PATCH 02/21] cpufreq: mediatek: Remove unused headers
|
||||
|
||||
Remove unused headers.
|
||||
|
||||
Signed-off-by: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -13,8 +13,6 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_opp.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
-#include <linux/slab.h>
|
||||
-#include <linux/thermal.h>
|
||||
|
||||
#define MIN_VOLT_SHIFT (100000)
|
||||
#define MAX_VOLT_SHIFT (200000)
|
@ -0,0 +1,117 @@
|
||||
From 342d5545e9f40496db9ae0d31c2427dd5f369a43 Mon Sep 17 00:00:00 2001
|
||||
From: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Date: Fri, 8 Apr 2022 12:58:58 +0800
|
||||
Subject: [PATCH 03/21] cpufreq: mediatek: Enable clocks and regulators
|
||||
|
||||
We need to enable regulators so that the max and min requested values will
|
||||
be recorded.
|
||||
The intermediate clock is not always enabled by CCF in different projects,
|
||||
so we should enable it in the cpufreq driver.
|
||||
|
||||
Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
|
||||
Signed-off-by: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Signed-off-by: Rex-BC Chen <rex-bc.chen@mediatek.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 50 +++++++++++++++++++++++++++---
|
||||
1 file changed, 45 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -334,10 +334,23 @@ static int mtk_cpu_dvfs_info_init(struct
|
||||
goto out_free_resources;
|
||||
}
|
||||
|
||||
+ ret = regulator_enable(info->proc_reg);
|
||||
+ if (ret) {
|
||||
+ dev_warn(cpu_dev, "cpu%d: failed to enable vproc\n", cpu);
|
||||
+ goto out_free_resources;
|
||||
+ }
|
||||
+
|
||||
/* Both presence and absence of sram regulator are valid cases. */
|
||||
info->sram_reg = regulator_get_exclusive(cpu_dev, "sram");
|
||||
if (IS_ERR(info->sram_reg))
|
||||
info->sram_reg = NULL;
|
||||
+ else {
|
||||
+ ret = regulator_enable(info->sram_reg);
|
||||
+ if (ret) {
|
||||
+ dev_warn(cpu_dev, "cpu%d: failed to enable vsram\n", cpu);
|
||||
+ goto out_free_resources;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
/* Get OPP-sharing information from "operating-points-v2" bindings */
|
||||
ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, &info->cpus);
|
||||
@@ -353,13 +366,21 @@ static int mtk_cpu_dvfs_info_init(struct
|
||||
goto out_free_resources;
|
||||
}
|
||||
|
||||
+ ret = clk_prepare_enable(info->cpu_clk);
|
||||
+ if (ret)
|
||||
+ goto out_free_opp_table;
|
||||
+
|
||||
+ ret = clk_prepare_enable(info->inter_clk);
|
||||
+ if (ret)
|
||||
+ goto out_disable_mux_clock;
|
||||
+
|
||||
/* Search a safe voltage for intermediate frequency. */
|
||||
rate = clk_get_rate(info->inter_clk);
|
||||
opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
|
||||
if (IS_ERR(opp)) {
|
||||
dev_err(cpu_dev, "cpu%d: failed to get intermediate opp\n", cpu);
|
||||
ret = PTR_ERR(opp);
|
||||
- goto out_free_opp_table;
|
||||
+ goto out_disable_inter_clock;
|
||||
}
|
||||
info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
|
||||
dev_pm_opp_put(opp);
|
||||
@@ -372,10 +393,21 @@ static int mtk_cpu_dvfs_info_init(struct
|
||||
|
||||
return 0;
|
||||
|
||||
+out_disable_inter_clock:
|
||||
+ clk_disable_unprepare(info->inter_clk);
|
||||
+
|
||||
+out_disable_mux_clock:
|
||||
+ clk_disable_unprepare(info->cpu_clk);
|
||||
+
|
||||
out_free_opp_table:
|
||||
dev_pm_opp_of_cpumask_remove_table(&info->cpus);
|
||||
|
||||
out_free_resources:
|
||||
+ if (regulator_is_enabled(info->proc_reg))
|
||||
+ regulator_disable(info->proc_reg);
|
||||
+ if (info->sram_reg && regulator_is_enabled(info->sram_reg))
|
||||
+ regulator_disable(info->sram_reg);
|
||||
+
|
||||
if (!IS_ERR(info->proc_reg))
|
||||
regulator_put(info->proc_reg);
|
||||
if (!IS_ERR(info->sram_reg))
|
||||
@@ -390,14 +422,22 @@ out_free_resources:
|
||||
|
||||
static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info)
|
||||
{
|
||||
- if (!IS_ERR(info->proc_reg))
|
||||
+ if (!IS_ERR(info->proc_reg)) {
|
||||
+ regulator_disable(info->proc_reg);
|
||||
regulator_put(info->proc_reg);
|
||||
- if (!IS_ERR(info->sram_reg))
|
||||
+ }
|
||||
+ if (!IS_ERR(info->sram_reg)) {
|
||||
+ regulator_disable(info->sram_reg);
|
||||
regulator_put(info->sram_reg);
|
||||
- if (!IS_ERR(info->cpu_clk))
|
||||
+ }
|
||||
+ if (!IS_ERR(info->cpu_clk)) {
|
||||
+ clk_disable_unprepare(info->cpu_clk);
|
||||
clk_put(info->cpu_clk);
|
||||
- if (!IS_ERR(info->inter_clk))
|
||||
+ }
|
||||
+ if (!IS_ERR(info->inter_clk)) {
|
||||
+ clk_disable_unprepare(info->inter_clk);
|
||||
clk_put(info->inter_clk);
|
||||
+ }
|
||||
|
||||
dev_pm_opp_of_cpumask_remove_table(&info->cpus);
|
||||
}
|
@ -0,0 +1,161 @@
|
||||
From a02e2b359141035d2d6999940bc1b9f83ec88587 Mon Sep 17 00:00:00 2001
|
||||
From: Rex-BC Chen <rex-bc.chen@mediatek.com>
|
||||
Date: Fri, 22 Apr 2022 15:52:27 +0800
|
||||
Subject: [PATCH 04/21] cpufreq: mediatek: Use device print to show logs
|
||||
|
||||
- Replace pr_* with dev_* to show logs.
|
||||
- Remove usage of __func__.
|
||||
|
||||
Signed-off-by: Rex-BC Chen <rex-bc.chen@mediatek.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 54 ++++++++++++++++--------------
|
||||
1 file changed, 28 insertions(+), 26 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -67,7 +67,8 @@ static int mtk_cpufreq_voltage_tracking(
|
||||
|
||||
old_vproc = regulator_get_voltage(proc_reg);
|
||||
if (old_vproc < 0) {
|
||||
- pr_err("%s: invalid Vproc value: %d\n", __func__, old_vproc);
|
||||
+ dev_err(info->cpu_dev,
|
||||
+ "invalid Vproc value: %d\n", old_vproc);
|
||||
return old_vproc;
|
||||
}
|
||||
/* Vsram should not exceed the maximum allowed voltage of SoC. */
|
||||
@@ -83,14 +84,14 @@ static int mtk_cpufreq_voltage_tracking(
|
||||
do {
|
||||
old_vsram = regulator_get_voltage(sram_reg);
|
||||
if (old_vsram < 0) {
|
||||
- pr_err("%s: invalid Vsram value: %d\n",
|
||||
- __func__, old_vsram);
|
||||
+ dev_err(info->cpu_dev,
|
||||
+ "invalid Vsram value: %d\n", old_vsram);
|
||||
return old_vsram;
|
||||
}
|
||||
old_vproc = regulator_get_voltage(proc_reg);
|
||||
if (old_vproc < 0) {
|
||||
- pr_err("%s: invalid Vproc value: %d\n",
|
||||
- __func__, old_vproc);
|
||||
+ dev_err(info->cpu_dev,
|
||||
+ "invalid Vproc value: %d\n", old_vproc);
|
||||
return old_vproc;
|
||||
}
|
||||
|
||||
@@ -138,14 +139,14 @@ static int mtk_cpufreq_voltage_tracking(
|
||||
do {
|
||||
old_vproc = regulator_get_voltage(proc_reg);
|
||||
if (old_vproc < 0) {
|
||||
- pr_err("%s: invalid Vproc value: %d\n",
|
||||
- __func__, old_vproc);
|
||||
+ dev_err(info->cpu_dev,
|
||||
+ "invalid Vproc value: %d\n", old_vproc);
|
||||
return old_vproc;
|
||||
}
|
||||
old_vsram = regulator_get_voltage(sram_reg);
|
||||
if (old_vsram < 0) {
|
||||
- pr_err("%s: invalid Vsram value: %d\n",
|
||||
- __func__, old_vsram);
|
||||
+ dev_err(info->cpu_dev,
|
||||
+ "invalid Vsram value: %d\n", old_vsram);
|
||||
return old_vsram;
|
||||
}
|
||||
|
||||
@@ -216,7 +217,7 @@ static int mtk_cpufreq_set_target(struct
|
||||
old_freq_hz = clk_get_rate(cpu_clk);
|
||||
old_vproc = regulator_get_voltage(info->proc_reg);
|
||||
if (old_vproc < 0) {
|
||||
- pr_err("%s: invalid Vproc value: %d\n", __func__, old_vproc);
|
||||
+ dev_err(cpu_dev, "invalid Vproc value: %d\n", old_vproc);
|
||||
return old_vproc;
|
||||
}
|
||||
|
||||
@@ -224,8 +225,8 @@ static int mtk_cpufreq_set_target(struct
|
||||
|
||||
opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
|
||||
if (IS_ERR(opp)) {
|
||||
- pr_err("cpu%d: failed to find OPP for %ld\n",
|
||||
- policy->cpu, freq_hz);
|
||||
+ dev_err(cpu_dev, "cpu%d: failed to find OPP for %ld\n",
|
||||
+ policy->cpu, freq_hz);
|
||||
return PTR_ERR(opp);
|
||||
}
|
||||
vproc = dev_pm_opp_get_voltage(opp);
|
||||
@@ -239,8 +240,8 @@ static int mtk_cpufreq_set_target(struct
|
||||
if (old_vproc < target_vproc) {
|
||||
ret = mtk_cpufreq_set_voltage(info, target_vproc);
|
||||
if (ret) {
|
||||
- pr_err("cpu%d: failed to scale up voltage!\n",
|
||||
- policy->cpu);
|
||||
+ dev_err(cpu_dev,
|
||||
+ "cpu%d: failed to scale up voltage!\n", policy->cpu);
|
||||
mtk_cpufreq_set_voltage(info, old_vproc);
|
||||
return ret;
|
||||
}
|
||||
@@ -249,8 +250,8 @@ static int mtk_cpufreq_set_target(struct
|
||||
/* Reparent the CPU clock to intermediate clock. */
|
||||
ret = clk_set_parent(cpu_clk, info->inter_clk);
|
||||
if (ret) {
|
||||
- pr_err("cpu%d: failed to re-parent cpu clock!\n",
|
||||
- policy->cpu);
|
||||
+ dev_err(cpu_dev,
|
||||
+ "cpu%d: failed to re-parent cpu clock!\n", policy->cpu);
|
||||
mtk_cpufreq_set_voltage(info, old_vproc);
|
||||
WARN_ON(1);
|
||||
return ret;
|
||||
@@ -259,8 +260,8 @@ static int mtk_cpufreq_set_target(struct
|
||||
/* Set the original PLL to target rate. */
|
||||
ret = clk_set_rate(armpll, freq_hz);
|
||||
if (ret) {
|
||||
- pr_err("cpu%d: failed to scale cpu clock rate!\n",
|
||||
- policy->cpu);
|
||||
+ dev_err(cpu_dev,
|
||||
+ "cpu%d: failed to scale cpu clock rate!\n", policy->cpu);
|
||||
clk_set_parent(cpu_clk, armpll);
|
||||
mtk_cpufreq_set_voltage(info, old_vproc);
|
||||
return ret;
|
||||
@@ -269,8 +270,8 @@ static int mtk_cpufreq_set_target(struct
|
||||
/* Set parent of CPU clock back to the original PLL. */
|
||||
ret = clk_set_parent(cpu_clk, armpll);
|
||||
if (ret) {
|
||||
- pr_err("cpu%d: failed to re-parent cpu clock!\n",
|
||||
- policy->cpu);
|
||||
+ dev_err(cpu_dev,
|
||||
+ "cpu%d: failed to re-parent cpu clock!\n", policy->cpu);
|
||||
mtk_cpufreq_set_voltage(info, inter_vproc);
|
||||
WARN_ON(1);
|
||||
return ret;
|
||||
@@ -283,8 +284,8 @@ static int mtk_cpufreq_set_target(struct
|
||||
if (vproc < inter_vproc || vproc < old_vproc) {
|
||||
ret = mtk_cpufreq_set_voltage(info, vproc);
|
||||
if (ret) {
|
||||
- pr_err("cpu%d: failed to scale down voltage!\n",
|
||||
- policy->cpu);
|
||||
+ dev_err(cpu_dev,
|
||||
+ "cpu%d: failed to scale down voltage!\n", policy->cpu);
|
||||
clk_set_parent(cpu_clk, info->inter_clk);
|
||||
clk_set_rate(armpll, old_freq_hz);
|
||||
clk_set_parent(cpu_clk, armpll);
|
||||
@@ -450,15 +451,16 @@ static int mtk_cpufreq_init(struct cpufr
|
||||
|
||||
info = mtk_cpu_dvfs_info_lookup(policy->cpu);
|
||||
if (!info) {
|
||||
- pr_err("dvfs info for cpu%d is not initialized.\n",
|
||||
- policy->cpu);
|
||||
+ dev_err(info->cpu_dev,
|
||||
+ "dvfs info for cpu%d is not initialized.\n", policy->cpu);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = dev_pm_opp_init_cpufreq_table(info->cpu_dev, &freq_table);
|
||||
if (ret) {
|
||||
- pr_err("failed to init cpufreq table for cpu%d: %d\n",
|
||||
- policy->cpu, ret);
|
||||
+ dev_err(info->cpu_dev,
|
||||
+ "failed to init cpufreq table for cpu%d: %d\n",
|
||||
+ policy->cpu, ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -0,0 +1,201 @@
|
||||
From 35832d9f9c5c1da01420d962dc56e7e61d104829 Mon Sep 17 00:00:00 2001
|
||||
From: Rex-BC Chen <rex-bc.chen@mediatek.com>
|
||||
Date: Fri, 22 Apr 2022 15:52:28 +0800
|
||||
Subject: [PATCH 05/21] cpufreq: mediatek: Replace old_* with pre_*
|
||||
|
||||
To make driver more readable, replace old_* with pre_*.
|
||||
|
||||
Signed-off-by: Rex-BC Chen <rex-bc.chen@mediatek.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 84 +++++++++++++++---------------
|
||||
1 file changed, 42 insertions(+), 42 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -63,18 +63,18 @@ static int mtk_cpufreq_voltage_tracking(
|
||||
{
|
||||
struct regulator *proc_reg = info->proc_reg;
|
||||
struct regulator *sram_reg = info->sram_reg;
|
||||
- int old_vproc, old_vsram, new_vsram, vsram, vproc, ret;
|
||||
+ int pre_vproc, pre_vsram, new_vsram, vsram, vproc, ret;
|
||||
|
||||
- old_vproc = regulator_get_voltage(proc_reg);
|
||||
- if (old_vproc < 0) {
|
||||
+ pre_vproc = regulator_get_voltage(proc_reg);
|
||||
+ if (pre_vproc < 0) {
|
||||
dev_err(info->cpu_dev,
|
||||
- "invalid Vproc value: %d\n", old_vproc);
|
||||
- return old_vproc;
|
||||
+ "invalid Vproc value: %d\n", pre_vproc);
|
||||
+ return pre_vproc;
|
||||
}
|
||||
/* Vsram should not exceed the maximum allowed voltage of SoC. */
|
||||
new_vsram = min(new_vproc + MIN_VOLT_SHIFT, MAX_VOLT_LIMIT);
|
||||
|
||||
- if (old_vproc < new_vproc) {
|
||||
+ if (pre_vproc < new_vproc) {
|
||||
/*
|
||||
* When scaling up voltages, Vsram and Vproc scale up step
|
||||
* by step. At each step, set Vsram to (Vproc + 200mV) first,
|
||||
@@ -82,20 +82,20 @@ static int mtk_cpufreq_voltage_tracking(
|
||||
* Keep doing it until Vsram and Vproc hit target voltages.
|
||||
*/
|
||||
do {
|
||||
- old_vsram = regulator_get_voltage(sram_reg);
|
||||
- if (old_vsram < 0) {
|
||||
+ pre_vsram = regulator_get_voltage(sram_reg);
|
||||
+ if (pre_vsram < 0) {
|
||||
dev_err(info->cpu_dev,
|
||||
- "invalid Vsram value: %d\n", old_vsram);
|
||||
- return old_vsram;
|
||||
+ "invalid Vsram value: %d\n", pre_vsram);
|
||||
+ return pre_vsram;
|
||||
}
|
||||
- old_vproc = regulator_get_voltage(proc_reg);
|
||||
- if (old_vproc < 0) {
|
||||
+ pre_vproc = regulator_get_voltage(proc_reg);
|
||||
+ if (pre_vproc < 0) {
|
||||
dev_err(info->cpu_dev,
|
||||
- "invalid Vproc value: %d\n", old_vproc);
|
||||
- return old_vproc;
|
||||
+ "invalid Vproc value: %d\n", pre_vproc);
|
||||
+ return pre_vproc;
|
||||
}
|
||||
|
||||
- vsram = min(new_vsram, old_vproc + MAX_VOLT_SHIFT);
|
||||
+ vsram = min(new_vsram, pre_vproc + MAX_VOLT_SHIFT);
|
||||
|
||||
if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) {
|
||||
vsram = MAX_VOLT_LIMIT;
|
||||
@@ -124,12 +124,12 @@ static int mtk_cpufreq_voltage_tracking(
|
||||
ret = regulator_set_voltage(proc_reg, vproc,
|
||||
vproc + VOLT_TOL);
|
||||
if (ret) {
|
||||
- regulator_set_voltage(sram_reg, old_vsram,
|
||||
- old_vsram);
|
||||
+ regulator_set_voltage(sram_reg, pre_vsram,
|
||||
+ pre_vsram);
|
||||
return ret;
|
||||
}
|
||||
} while (vproc < new_vproc || vsram < new_vsram);
|
||||
- } else if (old_vproc > new_vproc) {
|
||||
+ } else if (pre_vproc > new_vproc) {
|
||||
/*
|
||||
* When scaling down voltages, Vsram and Vproc scale down step
|
||||
* by step. At each step, set Vproc to (Vsram - 200mV) first,
|
||||
@@ -137,20 +137,20 @@ static int mtk_cpufreq_voltage_tracking(
|
||||
* Keep doing it until Vsram and Vproc hit target voltages.
|
||||
*/
|
||||
do {
|
||||
- old_vproc = regulator_get_voltage(proc_reg);
|
||||
- if (old_vproc < 0) {
|
||||
+ pre_vproc = regulator_get_voltage(proc_reg);
|
||||
+ if (pre_vproc < 0) {
|
||||
dev_err(info->cpu_dev,
|
||||
- "invalid Vproc value: %d\n", old_vproc);
|
||||
- return old_vproc;
|
||||
+ "invalid Vproc value: %d\n", pre_vproc);
|
||||
+ return pre_vproc;
|
||||
}
|
||||
- old_vsram = regulator_get_voltage(sram_reg);
|
||||
- if (old_vsram < 0) {
|
||||
+ pre_vsram = regulator_get_voltage(sram_reg);
|
||||
+ if (pre_vsram < 0) {
|
||||
dev_err(info->cpu_dev,
|
||||
- "invalid Vsram value: %d\n", old_vsram);
|
||||
- return old_vsram;
|
||||
+ "invalid Vsram value: %d\n", pre_vsram);
|
||||
+ return pre_vsram;
|
||||
}
|
||||
|
||||
- vproc = max(new_vproc, old_vsram - MAX_VOLT_SHIFT);
|
||||
+ vproc = max(new_vproc, pre_vsram - MAX_VOLT_SHIFT);
|
||||
ret = regulator_set_voltage(proc_reg, vproc,
|
||||
vproc + VOLT_TOL);
|
||||
if (ret)
|
||||
@@ -180,8 +180,8 @@ static int mtk_cpufreq_voltage_tracking(
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
- regulator_set_voltage(proc_reg, old_vproc,
|
||||
- old_vproc);
|
||||
+ regulator_set_voltage(proc_reg, pre_vproc,
|
||||
+ pre_vproc);
|
||||
return ret;
|
||||
}
|
||||
} while (vproc > new_vproc + VOLT_TOL ||
|
||||
@@ -209,16 +209,16 @@ static int mtk_cpufreq_set_target(struct
|
||||
struct mtk_cpu_dvfs_info *info = policy->driver_data;
|
||||
struct device *cpu_dev = info->cpu_dev;
|
||||
struct dev_pm_opp *opp;
|
||||
- long freq_hz, old_freq_hz;
|
||||
- int vproc, old_vproc, inter_vproc, target_vproc, ret;
|
||||
+ long freq_hz, pre_freq_hz;
|
||||
+ int vproc, pre_vproc, inter_vproc, target_vproc, ret;
|
||||
|
||||
inter_vproc = info->intermediate_voltage;
|
||||
|
||||
- old_freq_hz = clk_get_rate(cpu_clk);
|
||||
- old_vproc = regulator_get_voltage(info->proc_reg);
|
||||
- if (old_vproc < 0) {
|
||||
- dev_err(cpu_dev, "invalid Vproc value: %d\n", old_vproc);
|
||||
- return old_vproc;
|
||||
+ pre_freq_hz = clk_get_rate(cpu_clk);
|
||||
+ pre_vproc = regulator_get_voltage(info->proc_reg);
|
||||
+ if (pre_vproc < 0) {
|
||||
+ dev_err(cpu_dev, "invalid Vproc value: %d\n", pre_vproc);
|
||||
+ return pre_vproc;
|
||||
}
|
||||
|
||||
freq_hz = freq_table[index].frequency * 1000;
|
||||
@@ -237,12 +237,12 @@ static int mtk_cpufreq_set_target(struct
|
||||
* current voltage, scale up voltage first.
|
||||
*/
|
||||
target_vproc = (inter_vproc > vproc) ? inter_vproc : vproc;
|
||||
- if (old_vproc < target_vproc) {
|
||||
+ if (pre_vproc < target_vproc) {
|
||||
ret = mtk_cpufreq_set_voltage(info, target_vproc);
|
||||
if (ret) {
|
||||
dev_err(cpu_dev,
|
||||
"cpu%d: failed to scale up voltage!\n", policy->cpu);
|
||||
- mtk_cpufreq_set_voltage(info, old_vproc);
|
||||
+ mtk_cpufreq_set_voltage(info, pre_vproc);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -252,7 +252,7 @@ static int mtk_cpufreq_set_target(struct
|
||||
if (ret) {
|
||||
dev_err(cpu_dev,
|
||||
"cpu%d: failed to re-parent cpu clock!\n", policy->cpu);
|
||||
- mtk_cpufreq_set_voltage(info, old_vproc);
|
||||
+ mtk_cpufreq_set_voltage(info, pre_vproc);
|
||||
WARN_ON(1);
|
||||
return ret;
|
||||
}
|
||||
@@ -263,7 +263,7 @@ static int mtk_cpufreq_set_target(struct
|
||||
dev_err(cpu_dev,
|
||||
"cpu%d: failed to scale cpu clock rate!\n", policy->cpu);
|
||||
clk_set_parent(cpu_clk, armpll);
|
||||
- mtk_cpufreq_set_voltage(info, old_vproc);
|
||||
+ mtk_cpufreq_set_voltage(info, pre_vproc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -281,13 +281,13 @@ static int mtk_cpufreq_set_target(struct
|
||||
* If the new voltage is lower than the intermediate voltage or the
|
||||
* original voltage, scale down to the new voltage.
|
||||
*/
|
||||
- if (vproc < inter_vproc || vproc < old_vproc) {
|
||||
+ if (vproc < inter_vproc || vproc < pre_vproc) {
|
||||
ret = mtk_cpufreq_set_voltage(info, vproc);
|
||||
if (ret) {
|
||||
dev_err(cpu_dev,
|
||||
"cpu%d: failed to scale down voltage!\n", policy->cpu);
|
||||
clk_set_parent(cpu_clk, info->inter_clk);
|
||||
- clk_set_rate(armpll, old_freq_hz);
|
||||
+ clk_set_rate(armpll, pre_freq_hz);
|
||||
clk_set_parent(cpu_clk, armpll);
|
||||
return ret;
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
From 34737eb8d0daa0d4183f10286a2f55d8788066bc Mon Sep 17 00:00:00 2001
|
||||
From: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Date: Fri, 22 Apr 2022 15:52:29 +0800
|
||||
Subject: [PATCH 06/21] cpufreq: mediatek: Record previous target vproc value
|
||||
|
||||
We found the buck voltage may not be exactly the same with what we set
|
||||
because CPU may share the same buck with other module.
|
||||
Therefore, we need to record the previous desired value instead of reading
|
||||
it from regulators.
|
||||
|
||||
Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
|
||||
Signed-off-by: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Signed-off-by: Rex-BC Chen <rex-bc.chen@mediatek.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 20 ++++++++++++++++----
|
||||
1 file changed, 16 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -40,6 +40,7 @@ struct mtk_cpu_dvfs_info {
|
||||
struct list_head list_head;
|
||||
int intermediate_voltage;
|
||||
bool need_voltage_tracking;
|
||||
+ int pre_vproc;
|
||||
};
|
||||
|
||||
static struct platform_device *cpufreq_pdev;
|
||||
@@ -193,11 +194,17 @@ static int mtk_cpufreq_voltage_tracking(
|
||||
|
||||
static int mtk_cpufreq_set_voltage(struct mtk_cpu_dvfs_info *info, int vproc)
|
||||
{
|
||||
+ int ret;
|
||||
+
|
||||
if (info->need_voltage_tracking)
|
||||
- return mtk_cpufreq_voltage_tracking(info, vproc);
|
||||
+ ret = mtk_cpufreq_voltage_tracking(info, vproc);
|
||||
else
|
||||
- return regulator_set_voltage(info->proc_reg, vproc,
|
||||
- vproc + VOLT_TOL);
|
||||
+ ret = regulator_set_voltage(info->proc_reg, vproc,
|
||||
+ MAX_VOLT_LIMIT);
|
||||
+ if (!ret)
|
||||
+ info->pre_vproc = vproc;
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
|
||||
@@ -215,7 +222,12 @@ static int mtk_cpufreq_set_target(struct
|
||||
inter_vproc = info->intermediate_voltage;
|
||||
|
||||
pre_freq_hz = clk_get_rate(cpu_clk);
|
||||
- pre_vproc = regulator_get_voltage(info->proc_reg);
|
||||
+
|
||||
+ if (unlikely(info->pre_vproc <= 0))
|
||||
+ pre_vproc = regulator_get_voltage(info->proc_reg);
|
||||
+ else
|
||||
+ pre_vproc = info->pre_vproc;
|
||||
+
|
||||
if (pre_vproc < 0) {
|
||||
dev_err(cpu_dev, "invalid Vproc value: %d\n", pre_vproc);
|
||||
return pre_vproc;
|
@ -0,0 +1,30 @@
|
||||
From f6114c2bc563a8050e9dc874ad87e1448865f031 Mon Sep 17 00:00:00 2001
|
||||
From: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Date: Fri, 22 Apr 2022 15:52:33 +0800
|
||||
Subject: [PATCH 07/21] cpufreq: mediatek: Make sram regulator optional
|
||||
|
||||
For some MediaTek SoCs, like MT8186, it's possible that the sram regulator
|
||||
is shared between CPU and CCI.
|
||||
We hope regulator framework can return error for error handling rather
|
||||
than a dummy handler from regulator_get api.
|
||||
Therefore, we choose to use regulator_get_optional.
|
||||
|
||||
Signed-off-by: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Signed-off-by: Rex-BC Chen <rex-bc.chen@mediatek.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -354,7 +354,7 @@ static int mtk_cpu_dvfs_info_init(struct
|
||||
}
|
||||
|
||||
/* Both presence and absence of sram regulator are valid cases. */
|
||||
- info->sram_reg = regulator_get_exclusive(cpu_dev, "sram");
|
||||
+ info->sram_reg = regulator_get_optional(cpu_dev, "sram");
|
||||
if (IS_ERR(info->sram_reg))
|
||||
info->sram_reg = NULL;
|
||||
else {
|
@ -0,0 +1,32 @@
|
||||
From fa7030d8ad4638acfd9e0fac84a20716d031dc95 Mon Sep 17 00:00:00 2001
|
||||
From: Wan Jiabing <wanjiabing@vivo.com>
|
||||
Date: Tue, 26 Apr 2022 19:17:14 +0800
|
||||
Subject: [PATCH 08/21] cpufreq: mediatek: Fix NULL pointer dereference in
|
||||
mediatek-cpufreq
|
||||
|
||||
Fix following coccicheck error:
|
||||
drivers/cpufreq/mediatek-cpufreq.c:464:16-23: ERROR: info is NULL but dereferenced.
|
||||
|
||||
Use pr_err instead of dev_err to avoid dereferring a NULL pointer.
|
||||
|
||||
Fixes: f52b16ba9fe4 ("cpufreq: mediatek: Use device print to show logs")
|
||||
Signed-off-by: Wan Jiabing <wanjiabing@vivo.com>
|
||||
Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -463,8 +463,8 @@ static int mtk_cpufreq_init(struct cpufr
|
||||
|
||||
info = mtk_cpu_dvfs_info_lookup(policy->cpu);
|
||||
if (!info) {
|
||||
- dev_err(info->cpu_dev,
|
||||
- "dvfs info for cpu%d is not initialized.\n", policy->cpu);
|
||||
+ pr_err("dvfs info for cpu%d is not initialized.\n",
|
||||
+ policy->cpu);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -0,0 +1,227 @@
|
||||
From be2354b064e6bafbbad599ae2e10569ba4f7d5a6 Mon Sep 17 00:00:00 2001
|
||||
From: Rex-BC Chen <rex-bc.chen@mediatek.com>
|
||||
Date: Thu, 5 May 2022 19:52:19 +0800
|
||||
Subject: [PATCH 09/21] cpufreq: mediatek: Move voltage limits to platform data
|
||||
|
||||
Voltages and shifts are defined as macros originally.
|
||||
There are different requirements of these values for each MediaTek SoCs.
|
||||
Therefore, we add the platform data and move these values into it.
|
||||
|
||||
Signed-off-by: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Signed-off-by: Rex-BC Chen <rex-bc.chen@mediatek.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 84 +++++++++++++++++++++---------
|
||||
1 file changed, 58 insertions(+), 26 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -10,15 +10,21 @@
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
+#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_opp.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
-#define MIN_VOLT_SHIFT (100000)
|
||||
-#define MAX_VOLT_SHIFT (200000)
|
||||
-#define MAX_VOLT_LIMIT (1150000)
|
||||
#define VOLT_TOL (10000)
|
||||
|
||||
+struct mtk_cpufreq_platform_data {
|
||||
+ int min_volt_shift;
|
||||
+ int max_volt_shift;
|
||||
+ int proc_max_volt;
|
||||
+ int sram_min_volt;
|
||||
+ int sram_max_volt;
|
||||
+};
|
||||
+
|
||||
/*
|
||||
* The struct mtk_cpu_dvfs_info holds necessary information for doing CPU DVFS
|
||||
* on each CPU power/clock domain of Mediatek SoCs. Each CPU cluster in
|
||||
@@ -41,6 +47,7 @@ struct mtk_cpu_dvfs_info {
|
||||
int intermediate_voltage;
|
||||
bool need_voltage_tracking;
|
||||
int pre_vproc;
|
||||
+ const struct mtk_cpufreq_platform_data *soc_data;
|
||||
};
|
||||
|
||||
static struct platform_device *cpufreq_pdev;
|
||||
@@ -62,6 +69,7 @@ static struct mtk_cpu_dvfs_info *mtk_cpu
|
||||
static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info,
|
||||
int new_vproc)
|
||||
{
|
||||
+ const struct mtk_cpufreq_platform_data *soc_data = info->soc_data;
|
||||
struct regulator *proc_reg = info->proc_reg;
|
||||
struct regulator *sram_reg = info->sram_reg;
|
||||
int pre_vproc, pre_vsram, new_vsram, vsram, vproc, ret;
|
||||
@@ -73,7 +81,8 @@ static int mtk_cpufreq_voltage_tracking(
|
||||
return pre_vproc;
|
||||
}
|
||||
/* Vsram should not exceed the maximum allowed voltage of SoC. */
|
||||
- new_vsram = min(new_vproc + MIN_VOLT_SHIFT, MAX_VOLT_LIMIT);
|
||||
+ new_vsram = min(new_vproc + soc_data->min_volt_shift,
|
||||
+ soc_data->sram_max_volt);
|
||||
|
||||
if (pre_vproc < new_vproc) {
|
||||
/*
|
||||
@@ -96,10 +105,11 @@ static int mtk_cpufreq_voltage_tracking(
|
||||
return pre_vproc;
|
||||
}
|
||||
|
||||
- vsram = min(new_vsram, pre_vproc + MAX_VOLT_SHIFT);
|
||||
+ vsram = min(new_vsram,
|
||||
+ pre_vproc + soc_data->min_volt_shift);
|
||||
|
||||
- if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) {
|
||||
- vsram = MAX_VOLT_LIMIT;
|
||||
+ if (vsram + VOLT_TOL >= soc_data->sram_max_volt) {
|
||||
+ vsram = soc_data->sram_max_volt;
|
||||
|
||||
/*
|
||||
* If the target Vsram hits the maximum voltage,
|
||||
@@ -117,7 +127,7 @@ static int mtk_cpufreq_voltage_tracking(
|
||||
ret = regulator_set_voltage(sram_reg, vsram,
|
||||
vsram + VOLT_TOL);
|
||||
|
||||
- vproc = vsram - MIN_VOLT_SHIFT;
|
||||
+ vproc = vsram - soc_data->min_volt_shift;
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -151,7 +161,8 @@ static int mtk_cpufreq_voltage_tracking(
|
||||
return pre_vsram;
|
||||
}
|
||||
|
||||
- vproc = max(new_vproc, pre_vsram - MAX_VOLT_SHIFT);
|
||||
+ vproc = max(new_vproc,
|
||||
+ pre_vsram - soc_data->max_volt_shift);
|
||||
ret = regulator_set_voltage(proc_reg, vproc,
|
||||
vproc + VOLT_TOL);
|
||||
if (ret)
|
||||
@@ -160,10 +171,11 @@ static int mtk_cpufreq_voltage_tracking(
|
||||
if (vproc == new_vproc)
|
||||
vsram = new_vsram;
|
||||
else
|
||||
- vsram = max(new_vsram, vproc + MIN_VOLT_SHIFT);
|
||||
+ vsram = max(new_vsram,
|
||||
+ vproc + soc_data->min_volt_shift);
|
||||
|
||||
- if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) {
|
||||
- vsram = MAX_VOLT_LIMIT;
|
||||
+ if (vsram + VOLT_TOL >= soc_data->sram_max_volt) {
|
||||
+ vsram = soc_data->sram_max_volt;
|
||||
|
||||
/*
|
||||
* If the target Vsram hits the maximum voltage,
|
||||
@@ -194,13 +206,14 @@ static int mtk_cpufreq_voltage_tracking(
|
||||
|
||||
static int mtk_cpufreq_set_voltage(struct mtk_cpu_dvfs_info *info, int vproc)
|
||||
{
|
||||
+ const struct mtk_cpufreq_platform_data *soc_data = info->soc_data;
|
||||
int ret;
|
||||
|
||||
if (info->need_voltage_tracking)
|
||||
ret = mtk_cpufreq_voltage_tracking(info, vproc);
|
||||
else
|
||||
ret = regulator_set_voltage(info->proc_reg, vproc,
|
||||
- MAX_VOLT_LIMIT);
|
||||
+ soc_data->proc_max_volt);
|
||||
if (!ret)
|
||||
info->pre_vproc = vproc;
|
||||
|
||||
@@ -509,9 +522,17 @@ static struct cpufreq_driver mtk_cpufreq
|
||||
|
||||
static int mtk_cpufreq_probe(struct platform_device *pdev)
|
||||
{
|
||||
+ const struct mtk_cpufreq_platform_data *data;
|
||||
struct mtk_cpu_dvfs_info *info, *tmp;
|
||||
int cpu, ret;
|
||||
|
||||
+ data = dev_get_platdata(&pdev->dev);
|
||||
+ if (!data) {
|
||||
+ dev_err(&pdev->dev,
|
||||
+ "failed to get mtk cpufreq platform data\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
for_each_possible_cpu(cpu) {
|
||||
info = mtk_cpu_dvfs_info_lookup(cpu);
|
||||
if (info)
|
||||
@@ -523,6 +544,7 @@ static int mtk_cpufreq_probe(struct plat
|
||||
goto release_dvfs_info_list;
|
||||
}
|
||||
|
||||
+ info->soc_data = data;
|
||||
ret = mtk_cpu_dvfs_info_init(info, cpu);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
@@ -558,20 +580,27 @@ static struct platform_driver mtk_cpufre
|
||||
.probe = mtk_cpufreq_probe,
|
||||
};
|
||||
|
||||
+static const struct mtk_cpufreq_platform_data mt2701_platform_data = {
|
||||
+ .min_volt_shift = 100000,
|
||||
+ .max_volt_shift = 200000,
|
||||
+ .proc_max_volt = 1150000,
|
||||
+ .sram_min_volt = 0,
|
||||
+ .sram_max_volt = 1150000,
|
||||
+};
|
||||
+
|
||||
/* List of machines supported by this driver */
|
||||
static const struct of_device_id mtk_cpufreq_machines[] __initconst = {
|
||||
- { .compatible = "mediatek,mt2701", },
|
||||
- { .compatible = "mediatek,mt2712", },
|
||||
- { .compatible = "mediatek,mt7622", },
|
||||
- { .compatible = "mediatek,mt7623", },
|
||||
- { .compatible = "mediatek,mt8167", },
|
||||
- { .compatible = "mediatek,mt817x", },
|
||||
- { .compatible = "mediatek,mt8173", },
|
||||
- { .compatible = "mediatek,mt8176", },
|
||||
- { .compatible = "mediatek,mt8183", },
|
||||
- { .compatible = "mediatek,mt8365", },
|
||||
- { .compatible = "mediatek,mt8516", },
|
||||
-
|
||||
+ { .compatible = "mediatek,mt2701", .data = &mt2701_platform_data },
|
||||
+ { .compatible = "mediatek,mt2712", .data = &mt2701_platform_data },
|
||||
+ { .compatible = "mediatek,mt7622", .data = &mt2701_platform_data },
|
||||
+ { .compatible = "mediatek,mt7623", .data = &mt2701_platform_data },
|
||||
+ { .compatible = "mediatek,mt8167", .data = &mt2701_platform_data },
|
||||
+ { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data },
|
||||
+ { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data },
|
||||
+ { .compatible = "mediatek,mt8176", .data = &mt2701_platform_data },
|
||||
+ { .compatible = "mediatek,mt8183", .data = &mt2701_platform_data },
|
||||
+ { .compatible = "mediatek,mt8365", .data = &mt2701_platform_data },
|
||||
+ { .compatible = "mediatek,mt8516", .data = &mt2701_platform_data },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mtk_cpufreq_machines);
|
||||
@@ -580,6 +609,7 @@ static int __init mtk_cpufreq_driver_ini
|
||||
{
|
||||
struct device_node *np;
|
||||
const struct of_device_id *match;
|
||||
+ const struct mtk_cpufreq_platform_data *data;
|
||||
int err;
|
||||
|
||||
np = of_find_node_by_path("/");
|
||||
@@ -592,6 +622,7 @@ static int __init mtk_cpufreq_driver_ini
|
||||
pr_debug("Machine is not compatible with mtk-cpufreq\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
+ data = match->data;
|
||||
|
||||
err = platform_driver_register(&mtk_cpufreq_platdrv);
|
||||
if (err)
|
||||
@@ -603,7 +634,8 @@ static int __init mtk_cpufreq_driver_ini
|
||||
* and the device registration codes are put here to handle defer
|
||||
* probing.
|
||||
*/
|
||||
- cpufreq_pdev = platform_device_register_simple("mtk-cpufreq", -1, NULL, 0);
|
||||
+ cpufreq_pdev = platform_device_register_data(NULL, "mtk-cpufreq", -1,
|
||||
+ data, sizeof(*data));
|
||||
if (IS_ERR(cpufreq_pdev)) {
|
||||
pr_err("failed to register mtk-cpufreq platform device\n");
|
||||
platform_driver_unregister(&mtk_cpufreq_platdrv);
|
@ -0,0 +1,255 @@
|
||||
From 944b041c91f1e1cd762c39c1222f078550149486 Mon Sep 17 00:00:00 2001
|
||||
From: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Date: Thu, 5 May 2022 19:52:20 +0800
|
||||
Subject: [PATCH 10/21] cpufreq: mediatek: Refine
|
||||
mtk_cpufreq_voltage_tracking()
|
||||
|
||||
Because the difference of sram and proc should in a range of min_volt_shift
|
||||
and max_volt_shift. We need to adjust the sram and proc step by step.
|
||||
|
||||
We replace VOLT_TOL (voltage tolerance) with the platform data and update the
|
||||
logic to determine the voltage boundary and invoking regulator_set_voltage.
|
||||
|
||||
- Use 'sram_min_volt' and 'sram_max_volt' to determine the voltage boundary
|
||||
of sram regulator.
|
||||
- Use (sram_min_volt - min_volt_shift) and 'proc_max_volt' to determine the
|
||||
voltage boundary of vproc regulator.
|
||||
|
||||
Moreover, to prevent infinite loop when tracking voltage, we calculate the
|
||||
maximum value for each platform data.
|
||||
We assume min voltage is 0 and tracking target voltage using
|
||||
min_volt_shift for each iteration.
|
||||
The retry_max is 3 times of expeted iteration count.
|
||||
|
||||
Signed-off-by: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Signed-off-by: Rex-BC Chen <rex-bc.chen@mediatek.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 147 ++++++++++-------------------
|
||||
1 file changed, 51 insertions(+), 96 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/cpumask.h>
|
||||
+#include <linux/minmax.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
@@ -15,8 +16,6 @@
|
||||
#include <linux/pm_opp.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
-#define VOLT_TOL (10000)
|
||||
-
|
||||
struct mtk_cpufreq_platform_data {
|
||||
int min_volt_shift;
|
||||
int max_volt_shift;
|
||||
@@ -48,6 +47,7 @@ struct mtk_cpu_dvfs_info {
|
||||
bool need_voltage_tracking;
|
||||
int pre_vproc;
|
||||
const struct mtk_cpufreq_platform_data *soc_data;
|
||||
+ int vtrack_max;
|
||||
};
|
||||
|
||||
static struct platform_device *cpufreq_pdev;
|
||||
@@ -73,6 +73,7 @@ static int mtk_cpufreq_voltage_tracking(
|
||||
struct regulator *proc_reg = info->proc_reg;
|
||||
struct regulator *sram_reg = info->sram_reg;
|
||||
int pre_vproc, pre_vsram, new_vsram, vsram, vproc, ret;
|
||||
+ int retry = info->vtrack_max;
|
||||
|
||||
pre_vproc = regulator_get_voltage(proc_reg);
|
||||
if (pre_vproc < 0) {
|
||||
@@ -80,91 +81,44 @@ static int mtk_cpufreq_voltage_tracking(
|
||||
"invalid Vproc value: %d\n", pre_vproc);
|
||||
return pre_vproc;
|
||||
}
|
||||
- /* Vsram should not exceed the maximum allowed voltage of SoC. */
|
||||
- new_vsram = min(new_vproc + soc_data->min_volt_shift,
|
||||
- soc_data->sram_max_volt);
|
||||
-
|
||||
- if (pre_vproc < new_vproc) {
|
||||
- /*
|
||||
- * When scaling up voltages, Vsram and Vproc scale up step
|
||||
- * by step. At each step, set Vsram to (Vproc + 200mV) first,
|
||||
- * then set Vproc to (Vsram - 100mV).
|
||||
- * Keep doing it until Vsram and Vproc hit target voltages.
|
||||
- */
|
||||
- do {
|
||||
- pre_vsram = regulator_get_voltage(sram_reg);
|
||||
- if (pre_vsram < 0) {
|
||||
- dev_err(info->cpu_dev,
|
||||
- "invalid Vsram value: %d\n", pre_vsram);
|
||||
- return pre_vsram;
|
||||
- }
|
||||
- pre_vproc = regulator_get_voltage(proc_reg);
|
||||
- if (pre_vproc < 0) {
|
||||
- dev_err(info->cpu_dev,
|
||||
- "invalid Vproc value: %d\n", pre_vproc);
|
||||
- return pre_vproc;
|
||||
- }
|
||||
|
||||
- vsram = min(new_vsram,
|
||||
- pre_vproc + soc_data->min_volt_shift);
|
||||
+ pre_vsram = regulator_get_voltage(sram_reg);
|
||||
+ if (pre_vsram < 0) {
|
||||
+ dev_err(info->cpu_dev, "invalid Vsram value: %d\n", pre_vsram);
|
||||
+ return pre_vsram;
|
||||
+ }
|
||||
|
||||
- if (vsram + VOLT_TOL >= soc_data->sram_max_volt) {
|
||||
- vsram = soc_data->sram_max_volt;
|
||||
+ new_vsram = clamp(new_vproc + soc_data->min_volt_shift,
|
||||
+ soc_data->sram_min_volt, soc_data->sram_max_volt);
|
||||
+
|
||||
+ do {
|
||||
+ if (pre_vproc <= new_vproc) {
|
||||
+ vsram = clamp(pre_vproc + soc_data->max_volt_shift,
|
||||
+ soc_data->sram_min_volt, new_vsram);
|
||||
+ ret = regulator_set_voltage(sram_reg, vsram,
|
||||
+ soc_data->sram_max_volt);
|
||||
|
||||
- /*
|
||||
- * If the target Vsram hits the maximum voltage,
|
||||
- * try to set the exact voltage value first.
|
||||
- */
|
||||
- ret = regulator_set_voltage(sram_reg, vsram,
|
||||
- vsram);
|
||||
- if (ret)
|
||||
- ret = regulator_set_voltage(sram_reg,
|
||||
- vsram - VOLT_TOL,
|
||||
- vsram);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
+ if (vsram == soc_data->sram_max_volt ||
|
||||
+ new_vsram == soc_data->sram_min_volt)
|
||||
vproc = new_vproc;
|
||||
- } else {
|
||||
- ret = regulator_set_voltage(sram_reg, vsram,
|
||||
- vsram + VOLT_TOL);
|
||||
-
|
||||
+ else
|
||||
vproc = vsram - soc_data->min_volt_shift;
|
||||
- }
|
||||
- if (ret)
|
||||
- return ret;
|
||||
|
||||
ret = regulator_set_voltage(proc_reg, vproc,
|
||||
- vproc + VOLT_TOL);
|
||||
+ soc_data->proc_max_volt);
|
||||
if (ret) {
|
||||
regulator_set_voltage(sram_reg, pre_vsram,
|
||||
- pre_vsram);
|
||||
+ soc_data->sram_max_volt);
|
||||
return ret;
|
||||
}
|
||||
- } while (vproc < new_vproc || vsram < new_vsram);
|
||||
- } else if (pre_vproc > new_vproc) {
|
||||
- /*
|
||||
- * When scaling down voltages, Vsram and Vproc scale down step
|
||||
- * by step. At each step, set Vproc to (Vsram - 200mV) first,
|
||||
- * then set Vproc to (Vproc + 100mV).
|
||||
- * Keep doing it until Vsram and Vproc hit target voltages.
|
||||
- */
|
||||
- do {
|
||||
- pre_vproc = regulator_get_voltage(proc_reg);
|
||||
- if (pre_vproc < 0) {
|
||||
- dev_err(info->cpu_dev,
|
||||
- "invalid Vproc value: %d\n", pre_vproc);
|
||||
- return pre_vproc;
|
||||
- }
|
||||
- pre_vsram = regulator_get_voltage(sram_reg);
|
||||
- if (pre_vsram < 0) {
|
||||
- dev_err(info->cpu_dev,
|
||||
- "invalid Vsram value: %d\n", pre_vsram);
|
||||
- return pre_vsram;
|
||||
- }
|
||||
-
|
||||
+ } else if (pre_vproc > new_vproc) {
|
||||
vproc = max(new_vproc,
|
||||
pre_vsram - soc_data->max_volt_shift);
|
||||
ret = regulator_set_voltage(proc_reg, vproc,
|
||||
- vproc + VOLT_TOL);
|
||||
+ soc_data->proc_max_volt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -174,32 +128,24 @@ static int mtk_cpufreq_voltage_tracking(
|
||||
vsram = max(new_vsram,
|
||||
vproc + soc_data->min_volt_shift);
|
||||
|
||||
- if (vsram + VOLT_TOL >= soc_data->sram_max_volt) {
|
||||
- vsram = soc_data->sram_max_volt;
|
||||
-
|
||||
- /*
|
||||
- * If the target Vsram hits the maximum voltage,
|
||||
- * try to set the exact voltage value first.
|
||||
- */
|
||||
- ret = regulator_set_voltage(sram_reg, vsram,
|
||||
- vsram);
|
||||
- if (ret)
|
||||
- ret = regulator_set_voltage(sram_reg,
|
||||
- vsram - VOLT_TOL,
|
||||
- vsram);
|
||||
- } else {
|
||||
- ret = regulator_set_voltage(sram_reg, vsram,
|
||||
- vsram + VOLT_TOL);
|
||||
- }
|
||||
-
|
||||
+ ret = regulator_set_voltage(sram_reg, vsram,
|
||||
+ soc_data->sram_max_volt);
|
||||
if (ret) {
|
||||
regulator_set_voltage(proc_reg, pre_vproc,
|
||||
- pre_vproc);
|
||||
+ soc_data->proc_max_volt);
|
||||
return ret;
|
||||
}
|
||||
- } while (vproc > new_vproc + VOLT_TOL ||
|
||||
- vsram > new_vsram + VOLT_TOL);
|
||||
- }
|
||||
+ }
|
||||
+
|
||||
+ pre_vproc = vproc;
|
||||
+ pre_vsram = vsram;
|
||||
+
|
||||
+ if (--retry < 0) {
|
||||
+ dev_err(info->cpu_dev,
|
||||
+ "over loop count, failed to set voltage\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ } while (vproc != new_vproc || vsram != new_vsram);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -261,8 +207,8 @@ static int mtk_cpufreq_set_target(struct
|
||||
* If the new voltage or the intermediate voltage is higher than the
|
||||
* current voltage, scale up voltage first.
|
||||
*/
|
||||
- target_vproc = (inter_vproc > vproc) ? inter_vproc : vproc;
|
||||
- if (pre_vproc < target_vproc) {
|
||||
+ target_vproc = max(inter_vproc, vproc);
|
||||
+ if (pre_vproc <= target_vproc) {
|
||||
ret = mtk_cpufreq_set_voltage(info, target_vproc);
|
||||
if (ret) {
|
||||
dev_err(cpu_dev,
|
||||
@@ -417,6 +363,15 @@ static int mtk_cpu_dvfs_info_init(struct
|
||||
*/
|
||||
info->need_voltage_tracking = (info->sram_reg != NULL);
|
||||
|
||||
+ /*
|
||||
+ * We assume min voltage is 0 and tracking target voltage using
|
||||
+ * min_volt_shift for each iteration.
|
||||
+ * The vtrack_max is 3 times of expeted iteration count.
|
||||
+ */
|
||||
+ info->vtrack_max = 3 * DIV_ROUND_UP(max(info->soc_data->sram_max_volt,
|
||||
+ info->soc_data->proc_max_volt),
|
||||
+ info->soc_data->min_volt_shift);
|
||||
+
|
||||
return 0;
|
||||
|
||||
out_disable_inter_clock:
|
@ -0,0 +1,184 @@
|
||||
From 01be227eff7e5fc01f7c8de8f6daddd5fb17ddd1 Mon Sep 17 00:00:00 2001
|
||||
From: Rex-BC Chen <rex-bc.chen@mediatek.com>
|
||||
Date: Thu, 5 May 2022 19:52:21 +0800
|
||||
Subject: [PATCH 11/21] cpufreq: mediatek: Add opp notification support
|
||||
|
||||
From this opp notifier, cpufreq should listen to opp notification and do
|
||||
proper actions when receiving events of disable and voltage adjustment.
|
||||
|
||||
One of the user for this opp notifier is MediaTek SVS.
|
||||
The MediaTek Smart Voltage Scaling (SVS) is a hardware which calculates
|
||||
suitable SVS bank voltages to OPP voltage table.
|
||||
|
||||
Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
|
||||
Signed-off-by: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Signed-off-by: Rex-BC Chen <rex-bc.chen@mediatek.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
[ Viresh: Renamed opp_freq as current_freq and moved its initialization ]
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 90 +++++++++++++++++++++++++++---
|
||||
1 file changed, 82 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -46,6 +46,11 @@ struct mtk_cpu_dvfs_info {
|
||||
int intermediate_voltage;
|
||||
bool need_voltage_tracking;
|
||||
int pre_vproc;
|
||||
+ /* Avoid race condition for regulators between notify and policy */
|
||||
+ struct mutex reg_lock;
|
||||
+ struct notifier_block opp_nb;
|
||||
+ unsigned int opp_cpu;
|
||||
+ unsigned long current_freq;
|
||||
const struct mtk_cpufreq_platform_data *soc_data;
|
||||
int vtrack_max;
|
||||
};
|
||||
@@ -182,6 +187,8 @@ static int mtk_cpufreq_set_target(struct
|
||||
|
||||
pre_freq_hz = clk_get_rate(cpu_clk);
|
||||
|
||||
+ mutex_lock(&info->reg_lock);
|
||||
+
|
||||
if (unlikely(info->pre_vproc <= 0))
|
||||
pre_vproc = regulator_get_voltage(info->proc_reg);
|
||||
else
|
||||
@@ -214,7 +221,7 @@ static int mtk_cpufreq_set_target(struct
|
||||
dev_err(cpu_dev,
|
||||
"cpu%d: failed to scale up voltage!\n", policy->cpu);
|
||||
mtk_cpufreq_set_voltage(info, pre_vproc);
|
||||
- return ret;
|
||||
+ goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,8 +231,7 @@ static int mtk_cpufreq_set_target(struct
|
||||
dev_err(cpu_dev,
|
||||
"cpu%d: failed to re-parent cpu clock!\n", policy->cpu);
|
||||
mtk_cpufreq_set_voltage(info, pre_vproc);
|
||||
- WARN_ON(1);
|
||||
- return ret;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
/* Set the original PLL to target rate. */
|
||||
@@ -235,7 +241,7 @@ static int mtk_cpufreq_set_target(struct
|
||||
"cpu%d: failed to scale cpu clock rate!\n", policy->cpu);
|
||||
clk_set_parent(cpu_clk, armpll);
|
||||
mtk_cpufreq_set_voltage(info, pre_vproc);
|
||||
- return ret;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
/* Set parent of CPU clock back to the original PLL. */
|
||||
@@ -244,8 +250,7 @@ static int mtk_cpufreq_set_target(struct
|
||||
dev_err(cpu_dev,
|
||||
"cpu%d: failed to re-parent cpu clock!\n", policy->cpu);
|
||||
mtk_cpufreq_set_voltage(info, inter_vproc);
|
||||
- WARN_ON(1);
|
||||
- return ret;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -260,15 +265,72 @@ static int mtk_cpufreq_set_target(struct
|
||||
clk_set_parent(cpu_clk, info->inter_clk);
|
||||
clk_set_rate(armpll, pre_freq_hz);
|
||||
clk_set_parent(cpu_clk, armpll);
|
||||
- return ret;
|
||||
+ goto out;
|
||||
}
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ info->current_freq = freq_hz;
|
||||
+
|
||||
+out:
|
||||
+ mutex_unlock(&info->reg_lock);
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
#define DYNAMIC_POWER "dynamic-power-coefficient"
|
||||
|
||||
+static int mtk_cpufreq_opp_notifier(struct notifier_block *nb,
|
||||
+ unsigned long event, void *data)
|
||||
+{
|
||||
+ struct dev_pm_opp *opp = data;
|
||||
+ struct dev_pm_opp *new_opp;
|
||||
+ struct mtk_cpu_dvfs_info *info;
|
||||
+ unsigned long freq, volt;
|
||||
+ struct cpufreq_policy *policy;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ info = container_of(nb, struct mtk_cpu_dvfs_info, opp_nb);
|
||||
+
|
||||
+ if (event == OPP_EVENT_ADJUST_VOLTAGE) {
|
||||
+ freq = dev_pm_opp_get_freq(opp);
|
||||
+
|
||||
+ mutex_lock(&info->reg_lock);
|
||||
+ if (info->current_freq == freq) {
|
||||
+ volt = dev_pm_opp_get_voltage(opp);
|
||||
+ ret = mtk_cpufreq_set_voltage(info, volt);
|
||||
+ if (ret)
|
||||
+ dev_err(info->cpu_dev,
|
||||
+ "failed to scale voltage: %d\n", ret);
|
||||
+ }
|
||||
+ mutex_unlock(&info->reg_lock);
|
||||
+ } else if (event == OPP_EVENT_DISABLE) {
|
||||
+ freq = dev_pm_opp_get_freq(opp);
|
||||
+
|
||||
+ /* case of current opp item is disabled */
|
||||
+ if (info->current_freq == freq) {
|
||||
+ freq = 1;
|
||||
+ new_opp = dev_pm_opp_find_freq_ceil(info->cpu_dev,
|
||||
+ &freq);
|
||||
+ if (IS_ERR(new_opp)) {
|
||||
+ dev_err(info->cpu_dev,
|
||||
+ "all opp items are disabled\n");
|
||||
+ ret = PTR_ERR(new_opp);
|
||||
+ return notifier_from_errno(ret);
|
||||
+ }
|
||||
+
|
||||
+ dev_pm_opp_put(new_opp);
|
||||
+ policy = cpufreq_cpu_get(info->opp_cpu);
|
||||
+ if (policy) {
|
||||
+ cpufreq_driver_target(policy, freq / 1000,
|
||||
+ CPUFREQ_RELATION_L);
|
||||
+ cpufreq_cpu_put(policy);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return notifier_from_errno(ret);
|
||||
+}
|
||||
+
|
||||
static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
|
||||
{
|
||||
struct device *cpu_dev;
|
||||
@@ -357,6 +419,17 @@ static int mtk_cpu_dvfs_info_init(struct
|
||||
info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
+ mutex_init(&info->reg_lock);
|
||||
+ info->current_freq = clk_get_rate(info->cpu_clk);
|
||||
+
|
||||
+ info->opp_cpu = cpu;
|
||||
+ info->opp_nb.notifier_call = mtk_cpufreq_opp_notifier;
|
||||
+ ret = dev_pm_opp_register_notifier(cpu_dev, &info->opp_nb);
|
||||
+ if (ret) {
|
||||
+ dev_err(cpu_dev, "cpu%d: failed to register opp notifier\n", cpu);
|
||||
+ goto out_disable_inter_clock;
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* If SRAM regulator is present, software "voltage tracking" is needed
|
||||
* for this CPU power domain.
|
||||
@@ -421,6 +494,7 @@ static void mtk_cpu_dvfs_info_release(st
|
||||
}
|
||||
|
||||
dev_pm_opp_of_cpumask_remove_table(&info->cpus);
|
||||
+ dev_pm_opp_unregister_notifier(info->cpu_dev, &info->opp_nb);
|
||||
}
|
||||
|
||||
static int mtk_cpufreq_init(struct cpufreq_policy *policy)
|
@ -0,0 +1,43 @@
|
||||
From 6a1bd7cf4ed7a1948f564aaf16d34b7352c0029b Mon Sep 17 00:00:00 2001
|
||||
From: Wan Jiabing <wanjiabing@vivo.com>
|
||||
Date: Tue, 10 May 2022 17:05:31 +0800
|
||||
Subject: [PATCH 12/21] cpufreq: mediatek: Fix potential deadlock problem in
|
||||
mtk_cpufreq_set_target
|
||||
|
||||
Fix following coccichek error:
|
||||
./drivers/cpufreq/mediatek-cpufreq.c:199:2-8: preceding lock on line
|
||||
./drivers/cpufreq/mediatek-cpufreq.c:208:2-8: preceding lock on line
|
||||
|
||||
mutex_lock is acquired but not released before return.
|
||||
Use 'goto out' to help releasing the mutex_lock.
|
||||
|
||||
Fixes: c210063b40ac ("cpufreq: mediatek: Add opp notification support")
|
||||
Signed-off-by: Wan Jiabing <wanjiabing@vivo.com>
|
||||
Reviewed-by: Rex-BC Chen <rex-bc.chen@mediatek.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -196,7 +196,8 @@ static int mtk_cpufreq_set_target(struct
|
||||
|
||||
if (pre_vproc < 0) {
|
||||
dev_err(cpu_dev, "invalid Vproc value: %d\n", pre_vproc);
|
||||
- return pre_vproc;
|
||||
+ ret = pre_vproc;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
freq_hz = freq_table[index].frequency * 1000;
|
||||
@@ -205,7 +206,8 @@ static int mtk_cpufreq_set_target(struct
|
||||
if (IS_ERR(opp)) {
|
||||
dev_err(cpu_dev, "cpu%d: failed to find OPP for %ld\n",
|
||||
policy->cpu, freq_hz);
|
||||
- return PTR_ERR(opp);
|
||||
+ ret = PTR_ERR(opp);
|
||||
+ goto out;
|
||||
}
|
||||
vproc = dev_pm_opp_get_voltage(opp);
|
||||
dev_pm_opp_put(opp);
|
@ -0,0 +1,188 @@
|
||||
From 15aaf74fb734a3e69b10d00b97b322711b81e222 Mon Sep 17 00:00:00 2001
|
||||
From: Rex-BC Chen <rex-bc.chen@mediatek.com>
|
||||
Date: Thu, 5 May 2022 19:52:22 +0800
|
||||
Subject: [PATCH 13/21] cpufreq: mediatek: Link CCI device to CPU
|
||||
|
||||
In some MediaTek SoCs, like MT8183, CPU and CCI share the same power
|
||||
supplies. Cpufreq needs to check if CCI devfreq exists and wait until
|
||||
CCI devfreq ready before scaling frequency.
|
||||
|
||||
Before CCI devfreq is ready, we record the voltage when booting to
|
||||
kernel and use the max(cpu target voltage, booting voltage) to
|
||||
prevent cpufreq adjust to the lower voltage which will cause the CCI
|
||||
crash because of high frequency and low voltage.
|
||||
|
||||
- Add is_ccifreq_ready() to link CCI device to CPI, and CPU will start
|
||||
DVFS when CCI is ready.
|
||||
- Add platform data for MT8183.
|
||||
|
||||
Signed-off-by: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Signed-off-by: Rex-BC Chen <rex-bc.chen@mediatek.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Reviewed-by: Kevin Hilman <khilman@baylibre.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 82 +++++++++++++++++++++++++++++-
|
||||
1 file changed, 81 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -22,6 +22,7 @@ struct mtk_cpufreq_platform_data {
|
||||
int proc_max_volt;
|
||||
int sram_min_volt;
|
||||
int sram_max_volt;
|
||||
+ bool ccifreq_supported;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -38,6 +39,7 @@ struct mtk_cpufreq_platform_data {
|
||||
struct mtk_cpu_dvfs_info {
|
||||
struct cpumask cpus;
|
||||
struct device *cpu_dev;
|
||||
+ struct device *cci_dev;
|
||||
struct regulator *proc_reg;
|
||||
struct regulator *sram_reg;
|
||||
struct clk *cpu_clk;
|
||||
@@ -45,6 +47,7 @@ struct mtk_cpu_dvfs_info {
|
||||
struct list_head list_head;
|
||||
int intermediate_voltage;
|
||||
bool need_voltage_tracking;
|
||||
+ int vproc_on_boot;
|
||||
int pre_vproc;
|
||||
/* Avoid race condition for regulators between notify and policy */
|
||||
struct mutex reg_lock;
|
||||
@@ -53,6 +56,7 @@ struct mtk_cpu_dvfs_info {
|
||||
unsigned long current_freq;
|
||||
const struct mtk_cpufreq_platform_data *soc_data;
|
||||
int vtrack_max;
|
||||
+ bool ccifreq_bound;
|
||||
};
|
||||
|
||||
static struct platform_device *cpufreq_pdev;
|
||||
@@ -171,6 +175,28 @@ static int mtk_cpufreq_set_voltage(struc
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static bool is_ccifreq_ready(struct mtk_cpu_dvfs_info *info)
|
||||
+{
|
||||
+ struct device_link *sup_link;
|
||||
+
|
||||
+ if (info->ccifreq_bound)
|
||||
+ return true;
|
||||
+
|
||||
+ sup_link = device_link_add(info->cpu_dev, info->cci_dev,
|
||||
+ DL_FLAG_AUTOREMOVE_CONSUMER);
|
||||
+ if (!sup_link) {
|
||||
+ dev_err(info->cpu_dev, "cpu%d: sup_link is NULL\n", info->opp_cpu);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (sup_link->supplier->links.status != DL_DEV_DRIVER_BOUND)
|
||||
+ return false;
|
||||
+
|
||||
+ info->ccifreq_bound = true;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
|
||||
unsigned int index)
|
||||
{
|
||||
@@ -213,6 +239,14 @@ static int mtk_cpufreq_set_target(struct
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
/*
|
||||
+ * If MediaTek cci is supported but is not ready, we will use the value
|
||||
+ * of max(target cpu voltage, booting voltage) to prevent high freqeuncy
|
||||
+ * low voltage crash.
|
||||
+ */
|
||||
+ if (info->soc_data->ccifreq_supported && !is_ccifreq_ready(info))
|
||||
+ vproc = max(vproc, info->vproc_on_boot);
|
||||
+
|
||||
+ /*
|
||||
* If the new voltage or the intermediate voltage is higher than the
|
||||
* current voltage, scale up voltage first.
|
||||
*/
|
||||
@@ -333,6 +367,23 @@ static int mtk_cpufreq_opp_notifier(stru
|
||||
return notifier_from_errno(ret);
|
||||
}
|
||||
|
||||
+static struct device *of_get_cci(struct device *cpu_dev)
|
||||
+{
|
||||
+ struct device_node *np;
|
||||
+ struct platform_device *pdev;
|
||||
+
|
||||
+ np = of_parse_phandle(cpu_dev->of_node, "mediatek,cci", 0);
|
||||
+ if (IS_ERR_OR_NULL(np))
|
||||
+ return NULL;
|
||||
+
|
||||
+ pdev = of_find_device_by_node(np);
|
||||
+ of_node_put(np);
|
||||
+ if (IS_ERR_OR_NULL(pdev))
|
||||
+ return NULL;
|
||||
+
|
||||
+ return &pdev->dev;
|
||||
+}
|
||||
+
|
||||
static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
|
||||
{
|
||||
struct device *cpu_dev;
|
||||
@@ -347,6 +398,16 @@ static int mtk_cpu_dvfs_info_init(struct
|
||||
}
|
||||
info->cpu_dev = cpu_dev;
|
||||
|
||||
+ info->ccifreq_bound = false;
|
||||
+ if (info->soc_data->ccifreq_supported) {
|
||||
+ info->cci_dev = of_get_cci(info->cpu_dev);
|
||||
+ if (IS_ERR_OR_NULL(info->cci_dev)) {
|
||||
+ ret = PTR_ERR(info->cci_dev);
|
||||
+ dev_err(cpu_dev, "cpu%d: failed to get cci device\n", cpu);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
info->cpu_clk = clk_get(cpu_dev, "cpu");
|
||||
if (IS_ERR(info->cpu_clk)) {
|
||||
ret = PTR_ERR(info->cpu_clk);
|
||||
@@ -410,6 +471,15 @@ static int mtk_cpu_dvfs_info_init(struct
|
||||
if (ret)
|
||||
goto out_disable_mux_clock;
|
||||
|
||||
+ if (info->soc_data->ccifreq_supported) {
|
||||
+ info->vproc_on_boot = regulator_get_voltage(info->proc_reg);
|
||||
+ if (info->vproc_on_boot < 0) {
|
||||
+ dev_err(info->cpu_dev,
|
||||
+ "invalid Vproc value: %d\n", info->vproc_on_boot);
|
||||
+ goto out_disable_inter_clock;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* Search a safe voltage for intermediate frequency. */
|
||||
rate = clk_get_rate(info->inter_clk);
|
||||
opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
|
||||
@@ -617,6 +687,16 @@ static const struct mtk_cpufreq_platform
|
||||
.proc_max_volt = 1150000,
|
||||
.sram_min_volt = 0,
|
||||
.sram_max_volt = 1150000,
|
||||
+ .ccifreq_supported = false,
|
||||
+};
|
||||
+
|
||||
+static const struct mtk_cpufreq_platform_data mt8183_platform_data = {
|
||||
+ .min_volt_shift = 100000,
|
||||
+ .max_volt_shift = 200000,
|
||||
+ .proc_max_volt = 1150000,
|
||||
+ .sram_min_volt = 0,
|
||||
+ .sram_max_volt = 1150000,
|
||||
+ .ccifreq_supported = true,
|
||||
};
|
||||
|
||||
/* List of machines supported by this driver */
|
||||
@@ -629,7 +709,7 @@ static const struct of_device_id mtk_cpu
|
||||
{ .compatible = "mediatek,mt817x", .data = &mt2701_platform_data },
|
||||
{ .compatible = "mediatek,mt8173", .data = &mt2701_platform_data },
|
||||
{ .compatible = "mediatek,mt8176", .data = &mt2701_platform_data },
|
||||
- { .compatible = "mediatek,mt8183", .data = &mt2701_platform_data },
|
||||
+ { .compatible = "mediatek,mt8183", .data = &mt8183_platform_data },
|
||||
{ .compatible = "mediatek,mt8365", .data = &mt2701_platform_data },
|
||||
{ .compatible = "mediatek,mt8516", .data = &mt2701_platform_data },
|
||||
{ }
|
@ -0,0 +1,42 @@
|
||||
From b6be0baa6615afc65c3963adab674e36af1d4d5f Mon Sep 17 00:00:00 2001
|
||||
From: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Date: Thu, 5 May 2022 19:52:23 +0800
|
||||
Subject: [PATCH 14/21] cpufreq: mediatek: Add support for MT8186
|
||||
|
||||
The platform data of MT8186 is different from previous MediaTek SoCs,
|
||||
so we add a new compatible and platform data for it.
|
||||
|
||||
Signed-off-by: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Signed-off-by: Rex-BC Chen <rex-bc.chen@mediatek.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -699,6 +699,15 @@ static const struct mtk_cpufreq_platform
|
||||
.ccifreq_supported = true,
|
||||
};
|
||||
|
||||
+static const struct mtk_cpufreq_platform_data mt8186_platform_data = {
|
||||
+ .min_volt_shift = 100000,
|
||||
+ .max_volt_shift = 250000,
|
||||
+ .proc_max_volt = 1118750,
|
||||
+ .sram_min_volt = 850000,
|
||||
+ .sram_max_volt = 1118750,
|
||||
+ .ccifreq_supported = true,
|
||||
+};
|
||||
+
|
||||
/* List of machines supported by this driver */
|
||||
static const struct of_device_id mtk_cpufreq_machines[] __initconst = {
|
||||
{ .compatible = "mediatek,mt2701", .data = &mt2701_platform_data },
|
||||
@@ -710,6 +719,7 @@ static const struct of_device_id mtk_cpu
|
||||
{ .compatible = "mediatek,mt8173", .data = &mt2701_platform_data },
|
||||
{ .compatible = "mediatek,mt8176", .data = &mt2701_platform_data },
|
||||
{ .compatible = "mediatek,mt8183", .data = &mt8183_platform_data },
|
||||
+ { .compatible = "mediatek,mt8186", .data = &mt8186_platform_data },
|
||||
{ .compatible = "mediatek,mt8365", .data = &mt2701_platform_data },
|
||||
{ .compatible = "mediatek,mt8516", .data = &mt2701_platform_data },
|
||||
{ }
|
@ -0,0 +1,35 @@
|
||||
From 75d19b24aa3203d6c78e4c431c2cc07157ce12fe Mon Sep 17 00:00:00 2001
|
||||
From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Date: Wed, 13 Jul 2022 13:15:36 +0200
|
||||
Subject: [PATCH 15/21] cpufreq: mediatek: Handle sram regulator probe deferral
|
||||
|
||||
If the regulator_get_optional() call for the SRAM regulator returns
|
||||
a probe deferral, we must bail out and retry probing later: failing
|
||||
to do this will produce unstabilities on platforms requiring the
|
||||
handling for this regulator.
|
||||
|
||||
Fixes: ffa7bdf7f344 ("cpufreq: mediatek: Make sram regulator optional")
|
||||
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 8 ++++++--
|
||||
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -439,9 +439,13 @@ static int mtk_cpu_dvfs_info_init(struct
|
||||
|
||||
/* Both presence and absence of sram regulator are valid cases. */
|
||||
info->sram_reg = regulator_get_optional(cpu_dev, "sram");
|
||||
- if (IS_ERR(info->sram_reg))
|
||||
+ if (IS_ERR(info->sram_reg)) {
|
||||
+ ret = PTR_ERR(info->sram_reg);
|
||||
+ if (ret == -EPROBE_DEFER)
|
||||
+ goto out_free_resources;
|
||||
+
|
||||
info->sram_reg = NULL;
|
||||
- else {
|
||||
+ } else {
|
||||
ret = regulator_enable(info->sram_reg);
|
||||
if (ret) {
|
||||
dev_warn(cpu_dev, "cpu%d: failed to enable vsram\n", cpu);
|
@ -0,0 +1,29 @@
|
||||
From dd1174c21dacacd6c0129c1dabc5decad35c02c2 Mon Sep 17 00:00:00 2001
|
||||
From: Yang Yingliang <yangyingliang@huawei.com>
|
||||
Date: Tue, 17 May 2022 21:34:50 +0800
|
||||
Subject: [PATCH 16/21] cpufreq: mediatek: fix error return code in
|
||||
mtk_cpu_dvfs_info_init()
|
||||
|
||||
If regulator_get_voltage() fails, it should return the error code in
|
||||
mtk_cpu_dvfs_info_init().
|
||||
|
||||
Fixes: 0daa47325bae ("cpufreq: mediatek: Link CCI device to CPU")
|
||||
Reported-by: Hulk Robot <hulkci@huawei.com>
|
||||
Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Reviewed-by: Rex-BC Chen <rex-bc.chen@mediatek.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -478,6 +478,7 @@ static int mtk_cpu_dvfs_info_init(struct
|
||||
if (info->soc_data->ccifreq_supported) {
|
||||
info->vproc_on_boot = regulator_get_voltage(info->proc_reg);
|
||||
if (info->vproc_on_boot < 0) {
|
||||
+ ret = info->vproc_on_boot;
|
||||
dev_err(info->cpu_dev,
|
||||
"invalid Vproc value: %d\n", info->vproc_on_boot);
|
||||
goto out_disable_inter_clock;
|
@ -0,0 +1,47 @@
|
||||
From 230a74d459244411db91bfd678f17fcf7aedfcd0 Mon Sep 17 00:00:00 2001
|
||||
From: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Date: Fri, 24 Mar 2023 18:11:27 +0800
|
||||
Subject: [PATCH 17/21] cpufreq: mediatek: fix passing zero to 'PTR_ERR'
|
||||
|
||||
In order to prevent passing zero to 'PTR_ERR' in
|
||||
mtk_cpu_dvfs_info_init(), we fix the return value of of_get_cci() using
|
||||
error pointer by explicitly casting error number.
|
||||
|
||||
Signed-off-by: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Fixes: 0daa47325bae ("cpufreq: mediatek: Link CCI device to CPU")
|
||||
Reported-by: Dan Carpenter <error27@gmail.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -373,13 +373,13 @@ static struct device *of_get_cci(struct
|
||||
struct platform_device *pdev;
|
||||
|
||||
np = of_parse_phandle(cpu_dev->of_node, "mediatek,cci", 0);
|
||||
- if (IS_ERR_OR_NULL(np))
|
||||
- return NULL;
|
||||
+ if (!np)
|
||||
+ return ERR_PTR(-ENODEV);
|
||||
|
||||
pdev = of_find_device_by_node(np);
|
||||
of_node_put(np);
|
||||
- if (IS_ERR_OR_NULL(pdev))
|
||||
- return NULL;
|
||||
+ if (!pdev)
|
||||
+ return ERR_PTR(-ENODEV);
|
||||
|
||||
return &pdev->dev;
|
||||
}
|
||||
@@ -401,7 +401,7 @@ static int mtk_cpu_dvfs_info_init(struct
|
||||
info->ccifreq_bound = false;
|
||||
if (info->soc_data->ccifreq_supported) {
|
||||
info->cci_dev = of_get_cci(info->cpu_dev);
|
||||
- if (IS_ERR_OR_NULL(info->cci_dev)) {
|
||||
+ if (IS_ERR(info->cci_dev)) {
|
||||
ret = PTR_ERR(info->cci_dev);
|
||||
dev_err(cpu_dev, "cpu%d: failed to get cci device\n", cpu);
|
||||
return -ENODEV;
|
@ -0,0 +1,149 @@
|
||||
From fced531b7c7e18192e7982637c8e8f20c29aad64 Mon Sep 17 00:00:00 2001
|
||||
From: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Date: Fri, 24 Mar 2023 18:11:28 +0800
|
||||
Subject: [PATCH 18/21] cpufreq: mediatek: fix KP caused by handler usage after
|
||||
regulator_put/clk_put
|
||||
|
||||
Any kind of failure in mtk_cpu_dvfs_info_init() will lead to calling
|
||||
regulator_put() or clk_put() and the KP will occur since the regulator/clk
|
||||
handlers are used after released in mtk_cpu_dvfs_info_release().
|
||||
|
||||
To prevent the usage after regulator_put()/clk_put(), the regulator/clk
|
||||
handlers are addressed in a way of "Free the Last Thing Style".
|
||||
|
||||
Signed-off-by: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Fixes: 4b9ceb757bbb ("cpufreq: mediatek: Enable clocks and regulators")
|
||||
Suggested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Suggested-by: Dan Carpenter <error27@gmail.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 62 +++++++++++++++---------------
|
||||
1 file changed, 30 insertions(+), 32 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -420,7 +420,7 @@ static int mtk_cpu_dvfs_info_init(struct
|
||||
ret = PTR_ERR(info->inter_clk);
|
||||
dev_err_probe(cpu_dev, ret,
|
||||
"cpu%d: failed to get intermediate clk\n", cpu);
|
||||
- goto out_free_resources;
|
||||
+ goto out_free_mux_clock;
|
||||
}
|
||||
|
||||
info->proc_reg = regulator_get_optional(cpu_dev, "proc");
|
||||
@@ -428,13 +428,13 @@ static int mtk_cpu_dvfs_info_init(struct
|
||||
ret = PTR_ERR(info->proc_reg);
|
||||
dev_err_probe(cpu_dev, ret,
|
||||
"cpu%d: failed to get proc regulator\n", cpu);
|
||||
- goto out_free_resources;
|
||||
+ goto out_free_inter_clock;
|
||||
}
|
||||
|
||||
ret = regulator_enable(info->proc_reg);
|
||||
if (ret) {
|
||||
dev_warn(cpu_dev, "cpu%d: failed to enable vproc\n", cpu);
|
||||
- goto out_free_resources;
|
||||
+ goto out_free_proc_reg;
|
||||
}
|
||||
|
||||
/* Both presence and absence of sram regulator are valid cases. */
|
||||
@@ -442,14 +442,14 @@ static int mtk_cpu_dvfs_info_init(struct
|
||||
if (IS_ERR(info->sram_reg)) {
|
||||
ret = PTR_ERR(info->sram_reg);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
- goto out_free_resources;
|
||||
+ goto out_disable_proc_reg;
|
||||
|
||||
info->sram_reg = NULL;
|
||||
} else {
|
||||
ret = regulator_enable(info->sram_reg);
|
||||
if (ret) {
|
||||
dev_warn(cpu_dev, "cpu%d: failed to enable vsram\n", cpu);
|
||||
- goto out_free_resources;
|
||||
+ goto out_free_sram_reg;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,13 +458,13 @@ static int mtk_cpu_dvfs_info_init(struct
|
||||
if (ret) {
|
||||
dev_err(cpu_dev,
|
||||
"cpu%d: failed to get OPP-sharing information\n", cpu);
|
||||
- goto out_free_resources;
|
||||
+ goto out_disable_sram_reg;
|
||||
}
|
||||
|
||||
ret = dev_pm_opp_of_cpumask_add_table(&info->cpus);
|
||||
if (ret) {
|
||||
dev_warn(cpu_dev, "cpu%d: no OPP table\n", cpu);
|
||||
- goto out_free_resources;
|
||||
+ goto out_disable_sram_reg;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(info->cpu_clk);
|
||||
@@ -533,43 +533,41 @@ out_disable_mux_clock:
|
||||
out_free_opp_table:
|
||||
dev_pm_opp_of_cpumask_remove_table(&info->cpus);
|
||||
|
||||
-out_free_resources:
|
||||
- if (regulator_is_enabled(info->proc_reg))
|
||||
- regulator_disable(info->proc_reg);
|
||||
- if (info->sram_reg && regulator_is_enabled(info->sram_reg))
|
||||
+out_disable_sram_reg:
|
||||
+ if (info->sram_reg)
|
||||
regulator_disable(info->sram_reg);
|
||||
|
||||
- if (!IS_ERR(info->proc_reg))
|
||||
- regulator_put(info->proc_reg);
|
||||
- if (!IS_ERR(info->sram_reg))
|
||||
+out_free_sram_reg:
|
||||
+ if (info->sram_reg)
|
||||
regulator_put(info->sram_reg);
|
||||
- if (!IS_ERR(info->cpu_clk))
|
||||
- clk_put(info->cpu_clk);
|
||||
- if (!IS_ERR(info->inter_clk))
|
||||
- clk_put(info->inter_clk);
|
||||
+
|
||||
+out_disable_proc_reg:
|
||||
+ regulator_disable(info->proc_reg);
|
||||
+
|
||||
+out_free_proc_reg:
|
||||
+ regulator_put(info->proc_reg);
|
||||
+
|
||||
+out_free_inter_clock:
|
||||
+ clk_put(info->inter_clk);
|
||||
+
|
||||
+out_free_mux_clock:
|
||||
+ clk_put(info->cpu_clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info)
|
||||
{
|
||||
- if (!IS_ERR(info->proc_reg)) {
|
||||
- regulator_disable(info->proc_reg);
|
||||
- regulator_put(info->proc_reg);
|
||||
- }
|
||||
- if (!IS_ERR(info->sram_reg)) {
|
||||
+ regulator_disable(info->proc_reg);
|
||||
+ regulator_put(info->proc_reg);
|
||||
+ if (info->sram_reg) {
|
||||
regulator_disable(info->sram_reg);
|
||||
regulator_put(info->sram_reg);
|
||||
}
|
||||
- if (!IS_ERR(info->cpu_clk)) {
|
||||
- clk_disable_unprepare(info->cpu_clk);
|
||||
- clk_put(info->cpu_clk);
|
||||
- }
|
||||
- if (!IS_ERR(info->inter_clk)) {
|
||||
- clk_disable_unprepare(info->inter_clk);
|
||||
- clk_put(info->inter_clk);
|
||||
- }
|
||||
-
|
||||
+ clk_disable_unprepare(info->cpu_clk);
|
||||
+ clk_put(info->cpu_clk);
|
||||
+ clk_disable_unprepare(info->inter_clk);
|
||||
+ clk_put(info->inter_clk);
|
||||
dev_pm_opp_of_cpumask_remove_table(&info->cpus);
|
||||
dev_pm_opp_unregister_notifier(info->cpu_dev, &info->opp_nb);
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
From 24bc42a2d44cb821818717a5c607270921ec5d20 Mon Sep 17 00:00:00 2001
|
||||
From: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Date: Fri, 24 Mar 2023 18:11:29 +0800
|
||||
Subject: [PATCH 19/21] cpufreq: mediatek: raise proc/sram max voltage for
|
||||
MT8516
|
||||
|
||||
Since the upper boundary of proc/sram voltage of MT8516 is 1300 mV,
|
||||
which is greater than the value of MT2701 1150 mV, we fix it by adding
|
||||
the corresponding platform data and specify proc/sram_max_volt to
|
||||
support MT8516.
|
||||
|
||||
Signed-off-by: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Fixes: ead858bd128d ("cpufreq: mediatek: Move voltage limits to platform data")
|
||||
Fixes: 6a17b3876bc8 ("cpufreq: mediatek: Refine mtk_cpufreq_voltage_tracking()")
|
||||
Reported-by: Nick Hainke <vincent@systemli.org>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 13 +++++++++++--
|
||||
1 file changed, 11 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -711,20 +711,29 @@ static const struct mtk_cpufreq_platform
|
||||
.ccifreq_supported = true,
|
||||
};
|
||||
|
||||
+static const struct mtk_cpufreq_platform_data mt8516_platform_data = {
|
||||
+ .min_volt_shift = 100000,
|
||||
+ .max_volt_shift = 200000,
|
||||
+ .proc_max_volt = 1310000,
|
||||
+ .sram_min_volt = 0,
|
||||
+ .sram_max_volt = 1310000,
|
||||
+ .ccifreq_supported = false,
|
||||
+};
|
||||
+
|
||||
/* List of machines supported by this driver */
|
||||
static const struct of_device_id mtk_cpufreq_machines[] __initconst = {
|
||||
{ .compatible = "mediatek,mt2701", .data = &mt2701_platform_data },
|
||||
{ .compatible = "mediatek,mt2712", .data = &mt2701_platform_data },
|
||||
{ .compatible = "mediatek,mt7622", .data = &mt2701_platform_data },
|
||||
{ .compatible = "mediatek,mt7623", .data = &mt2701_platform_data },
|
||||
- { .compatible = "mediatek,mt8167", .data = &mt2701_platform_data },
|
||||
+ { .compatible = "mediatek,mt8167", .data = &mt8516_platform_data },
|
||||
{ .compatible = "mediatek,mt817x", .data = &mt2701_platform_data },
|
||||
{ .compatible = "mediatek,mt8173", .data = &mt2701_platform_data },
|
||||
{ .compatible = "mediatek,mt8176", .data = &mt2701_platform_data },
|
||||
{ .compatible = "mediatek,mt8183", .data = &mt8183_platform_data },
|
||||
{ .compatible = "mediatek,mt8186", .data = &mt8186_platform_data },
|
||||
{ .compatible = "mediatek,mt8365", .data = &mt2701_platform_data },
|
||||
- { .compatible = "mediatek,mt8516", .data = &mt2701_platform_data },
|
||||
+ { .compatible = "mediatek,mt8516", .data = &mt8516_platform_data },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mtk_cpufreq_machines);
|
@ -0,0 +1,58 @@
|
||||
From fe6ef09358dc0cfead9d383a8676fbe7a40fcef7 Mon Sep 17 00:00:00 2001
|
||||
From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Date: Fri, 24 Mar 2023 18:11:30 +0800
|
||||
Subject: [PATCH 20/21] cpufreq: mediatek: Raise proc and sram max voltage for
|
||||
MT7622/7623
|
||||
|
||||
During the addition of SRAM voltage tracking for CCI scaling, this
|
||||
driver got some voltage limits set for the vtrack algorithm: these
|
||||
were moved to platform data first, then enforced in a later commit
|
||||
6a17b3876bc8 ("cpufreq: mediatek: Refine mtk_cpufreq_voltage_tracking()")
|
||||
using these as max values for the regulator_set_voltage() calls.
|
||||
|
||||
In this case, the vsram/vproc constraints for MT7622 and MT7623
|
||||
were supposed to be the same as MT2701 (and a number of other SoCs),
|
||||
but that turned out to be a mistake because the aforementioned two
|
||||
SoCs' maximum voltage for both VPROC and VPROC_SRAM is 1.36V.
|
||||
|
||||
Fix that by adding new platform data for MT7622/7623 declaring the
|
||||
right {proc,sram}_max_volt parameter.
|
||||
|
||||
Fixes: ead858bd128d ("cpufreq: mediatek: Move voltage limits to platform data")
|
||||
Fixes: 6a17b3876bc8 ("cpufreq: mediatek: Refine mtk_cpufreq_voltage_tracking()")
|
||||
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Jia-Wei Chang <jia-wei.chang@mediatek.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 13 +++++++++++--
|
||||
1 file changed, 11 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -693,6 +693,15 @@ static const struct mtk_cpufreq_platform
|
||||
.ccifreq_supported = false,
|
||||
};
|
||||
|
||||
+static const struct mtk_cpufreq_platform_data mt7622_platform_data = {
|
||||
+ .min_volt_shift = 100000,
|
||||
+ .max_volt_shift = 200000,
|
||||
+ .proc_max_volt = 1360000,
|
||||
+ .sram_min_volt = 0,
|
||||
+ .sram_max_volt = 1360000,
|
||||
+ .ccifreq_supported = false,
|
||||
+};
|
||||
+
|
||||
static const struct mtk_cpufreq_platform_data mt8183_platform_data = {
|
||||
.min_volt_shift = 100000,
|
||||
.max_volt_shift = 200000,
|
||||
@@ -724,8 +733,8 @@ static const struct mtk_cpufreq_platform
|
||||
static const struct of_device_id mtk_cpufreq_machines[] __initconst = {
|
||||
{ .compatible = "mediatek,mt2701", .data = &mt2701_platform_data },
|
||||
{ .compatible = "mediatek,mt2712", .data = &mt2701_platform_data },
|
||||
- { .compatible = "mediatek,mt7622", .data = &mt2701_platform_data },
|
||||
- { .compatible = "mediatek,mt7623", .data = &mt2701_platform_data },
|
||||
+ { .compatible = "mediatek,mt7622", .data = &mt7622_platform_data },
|
||||
+ { .compatible = "mediatek,mt7623", .data = &mt7622_platform_data },
|
||||
{ .compatible = "mediatek,mt8167", .data = &mt8516_platform_data },
|
||||
{ .compatible = "mediatek,mt817x", .data = &mt2701_platform_data },
|
||||
{ .compatible = "mediatek,mt8173", .data = &mt2701_platform_data },
|
@ -0,0 +1,41 @@
|
||||
From 4983a1517e7ddbc6f53fc07607e4ebeb51412843 Mon Sep 17 00:00:00 2001
|
||||
From: Sam Shih <sam.shih@mediatek.com>
|
||||
Date: Tue, 28 Feb 2023 19:59:22 +0800
|
||||
Subject: [PATCH 21/21] cpufreq: mediatek: Add support for MT7988
|
||||
|
||||
This add cpufreq support for mediatek MT7988 SoC.
|
||||
|
||||
The platform data of MT7988 is different from previous MediaTek SoCs,
|
||||
so we add a new compatible and platform data for it.
|
||||
|
||||
Signed-off-by: Sam Shih <sam.shih@mediatek.com>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -702,6 +702,15 @@ static const struct mtk_cpufreq_platform
|
||||
.ccifreq_supported = false,
|
||||
};
|
||||
|
||||
+static const struct mtk_cpufreq_platform_data mt7988_platform_data = {
|
||||
+ .min_volt_shift = 100000,
|
||||
+ .max_volt_shift = 200000,
|
||||
+ .proc_max_volt = 900000,
|
||||
+ .sram_min_volt = 0,
|
||||
+ .sram_max_volt = 1150000,
|
||||
+ .ccifreq_supported = true,
|
||||
+};
|
||||
+
|
||||
static const struct mtk_cpufreq_platform_data mt8183_platform_data = {
|
||||
.min_volt_shift = 100000,
|
||||
.max_volt_shift = 200000,
|
||||
@@ -735,6 +744,7 @@ static const struct of_device_id mtk_cpu
|
||||
{ .compatible = "mediatek,mt2712", .data = &mt2701_platform_data },
|
||||
{ .compatible = "mediatek,mt7622", .data = &mt7622_platform_data },
|
||||
{ .compatible = "mediatek,mt7623", .data = &mt7622_platform_data },
|
||||
+ { .compatible = "mediatek,mt7988", .data = &mt7988_platform_data },
|
||||
{ .compatible = "mediatek,mt8167", .data = &mt8516_platform_data },
|
||||
{ .compatible = "mediatek,mt817x", .data = &mt2701_platform_data },
|
||||
{ .compatible = "mediatek,mt8173", .data = &mt2701_platform_data },
|
@ -0,0 +1,29 @@
|
||||
From 20aad28ba5d62f1618408c264384d0b2ad7417db Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Mon, 22 May 2023 23:25:48 +0100
|
||||
Subject: [PATCH] cpufreq: mediatek: don't request unsupported voltage
|
||||
|
||||
PMICs on MT7622 and MT7623 boards only support up to 1350000uV despite
|
||||
the SoC's processor and SRAM voltage can be up to 1360000uV. As a
|
||||
work-around specify max. processor and SRAM voltage as 1350000uV to
|
||||
avoid requesting an unsupported voltage from the regulator.
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
drivers/cpufreq/mediatek-cpufreq.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/mediatek-cpufreq.c
|
||||
+++ b/drivers/cpufreq/mediatek-cpufreq.c
|
||||
@@ -696,9 +696,9 @@ static const struct mtk_cpufreq_platform
|
||||
static const struct mtk_cpufreq_platform_data mt7622_platform_data = {
|
||||
.min_volt_shift = 100000,
|
||||
.max_volt_shift = 200000,
|
||||
- .proc_max_volt = 1360000,
|
||||
+ .proc_max_volt = 1350000,
|
||||
.sram_min_volt = 0,
|
||||
- .sram_max_volt = 1360000,
|
||||
+ .sram_max_volt = 1350000,
|
||||
.ccifreq_supported = false,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user