diff options
author | Daniel Golle <daniel@makrotopia.org> | 2023-04-30 18:03:00 +0100 |
---|---|---|
committer | Daniel Golle <daniel@makrotopia.org> | 2023-05-24 19:26:52 +0100 |
commit | 670dedbbd71056fa60666a6c5f7bd84ebcf6a2a1 (patch) | |
tree | 42527bc0b5f167424f084c34422f207c960deaca /target/linux | |
parent | fd1791795195cec46b86900ff3e228c080c8bf20 (diff) | |
download | upstream-670dedbbd71056fa60666a6c5f7bd84ebcf6a2a1.tar.gz upstream-670dedbbd71056fa60666a6c5f7bd84ebcf6a2a1.tar.bz2 upstream-670dedbbd71056fa60666a6c5f7bd84ebcf6a2a1.zip |
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 e4555d69a1c7c811188d8e257e77ac917d15f492)
Diffstat (limited to 'target/linux')
22 files changed, 2178 insertions, 0 deletions
diff --git a/target/linux/mediatek/patches-5.15/350-01-cpufreq-mediatek-Cleanup-variables-and-error-handlin.patch b/target/linux/mediatek/patches-5.15/350-01-cpufreq-mediatek-Cleanup-variables-and-error-handlin.patch new file mode 100644 index 0000000000..8fad64a570 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-01-cpufreq-mediatek-Cleanup-variables-and-error-handlin.patch @@ -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; + } diff --git a/target/linux/mediatek/patches-5.15/350-02-cpufreq-mediatek-Remove-unused-headers.patch b/target/linux/mediatek/patches-5.15/350-02-cpufreq-mediatek-Remove-unused-headers.patch new file mode 100644 index 0000000000..eebeeb0902 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-02-cpufreq-mediatek-Remove-unused-headers.patch @@ -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) diff --git a/target/linux/mediatek/patches-5.15/350-03-cpufreq-mediatek-Enable-clocks-and-regulators.patch b/target/linux/mediatek/patches-5.15/350-03-cpufreq-mediatek-Enable-clocks-and-regulators.patch new file mode 100644 index 0000000000..c97d5fc3d9 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-03-cpufreq-mediatek-Enable-clocks-and-regulators.patch @@ -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); + } diff --git a/target/linux/mediatek/patches-5.15/350-04-cpufreq-mediatek-Use-device-print-to-show-logs.patch b/target/linux/mediatek/patches-5.15/350-04-cpufreq-mediatek-Use-device-print-to-show-logs.patch new file mode 100644 index 0000000000..18e1da728a --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-04-cpufreq-mediatek-Use-device-print-to-show-logs.patch @@ -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; + } + diff --git a/target/linux/mediatek/patches-5.15/350-05-cpufreq-mediatek-Replace-old_-with-pre_.patch b/target/linux/mediatek/patches-5.15/350-05-cpufreq-mediatek-Replace-old_-with-pre_.patch new file mode 100644 index 0000000000..8506f4e477 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-05-cpufreq-mediatek-Replace-old_-with-pre_.patch @@ -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; + } diff --git a/target/linux/mediatek/patches-5.15/350-06-cpufreq-mediatek-Record-previous-target-vproc-value.patch b/target/linux/mediatek/patches-5.15/350-06-cpufreq-mediatek-Record-previous-target-vproc-value.patch new file mode 100644 index 0000000000..94e6617d26 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-06-cpufreq-mediatek-Record-previous-target-vproc-value.patch @@ -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; diff --git a/target/linux/mediatek/patches-5.15/350-07-cpufreq-mediatek-Make-sram-regulator-optional.patch b/target/linux/mediatek/patches-5.15/350-07-cpufreq-mediatek-Make-sram-regulator-optional.patch new file mode 100644 index 0000000000..4b74873b15 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-07-cpufreq-mediatek-Make-sram-regulator-optional.patch @@ -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 { diff --git a/target/linux/mediatek/patches-5.15/350-08-cpufreq-mediatek-Fix-NULL-pointer-dereference-in-med.patch b/target/linux/mediatek/patches-5.15/350-08-cpufreq-mediatek-Fix-NULL-pointer-dereference-in-med.patch new file mode 100644 index 0000000000..f2f572a753 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-08-cpufreq-mediatek-Fix-NULL-pointer-dereference-in-med.patch @@ -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; + } + diff --git a/target/linux/mediatek/patches-5.15/350-09-cpufreq-mediatek-Move-voltage-limits-to-platform-dat.patch b/target/linux/mediatek/patches-5.15/350-09-cpufreq-mediatek-Move-voltage-limits-to-platform-dat.patch new file mode 100644 index 0000000000..23b319648d --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-09-cpufreq-mediatek-Move-voltage-limits-to-platform-dat.patch @@ -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); diff --git a/target/linux/mediatek/patches-5.15/350-10-cpufreq-mediatek-Refine-mtk_cpufreq_voltage_tracking.patch b/target/linux/mediatek/patches-5.15/350-10-cpufreq-mediatek-Refine-mtk_cpufreq_voltage_tracking.patch new file mode 100644 index 0000000000..0ba9471ffa --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-10-cpufreq-mediatek-Refine-mtk_cpufreq_voltage_tracking.patch @@ -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: diff --git a/target/linux/mediatek/patches-5.15/350-11-cpufreq-mediatek-Add-opp-notification-support.patch b/target/linux/mediatek/patches-5.15/350-11-cpufreq-mediatek-Add-opp-notification-support.patch new file mode 100644 index 0000000000..2cb99b907a --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-11-cpufreq-mediatek-Add-opp-notification-support.patch @@ -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) diff --git a/target/linux/mediatek/patches-5.15/350-12-cpufreq-mediatek-Fix-potential-deadlock-problem-in-m.patch b/target/linux/mediatek/patches-5.15/350-12-cpufreq-mediatek-Fix-potential-deadlock-problem-in-m.patch new file mode 100644 index 0000000000..76bd795c00 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-12-cpufreq-mediatek-Fix-potential-deadlock-problem-in-m.patch @@ -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); diff --git a/target/linux/mediatek/patches-5.15/350-13-cpufreq-mediatek-Link-CCI-device-to-CPU.patch b/target/linux/mediatek/patches-5.15/350-13-cpufreq-mediatek-Link-CCI-device-to-CPU.patch new file mode 100644 index 0000000000..eeaa466c32 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-13-cpufreq-mediatek-Link-CCI-device-to-CPU.patch @@ -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 }, + { } diff --git a/target/linux/mediatek/patches-5.15/350-14-cpufreq-mediatek-Add-support-for-MT8186.patch b/target/linux/mediatek/patches-5.15/350-14-cpufreq-mediatek-Add-support-for-MT8186.patch new file mode 100644 index 0000000000..31000cfbe0 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-14-cpufreq-mediatek-Add-support-for-MT8186.patch @@ -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 }, + { } diff --git a/target/linux/mediatek/patches-5.15/350-15-cpufreq-mediatek-Handle-sram-regulator-probe-deferra.patch b/target/linux/mediatek/patches-5.15/350-15-cpufreq-mediatek-Handle-sram-regulator-probe-deferra.patch new file mode 100644 index 0000000000..c0137894c9 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-15-cpufreq-mediatek-Handle-sram-regulator-probe-deferra.patch @@ -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); diff --git a/target/linux/mediatek/patches-5.15/350-16-cpufreq-mediatek-fix-error-return-code-in-mtk_cpu_dv.patch b/target/linux/mediatek/patches-5.15/350-16-cpufreq-mediatek-fix-error-return-code-in-mtk_cpu_dv.patch new file mode 100644 index 0000000000..45c4477ff1 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-16-cpufreq-mediatek-fix-error-return-code-in-mtk_cpu_dv.patch @@ -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; diff --git a/target/linux/mediatek/patches-5.15/350-17-cpufreq-mediatek-fix-passing-zero-to-PTR_ERR.patch b/target/linux/mediatek/patches-5.15/350-17-cpufreq-mediatek-fix-passing-zero-to-PTR_ERR.patch new file mode 100644 index 0000000000..557d02b822 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-17-cpufreq-mediatek-fix-passing-zero-to-PTR_ERR.patch @@ -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; diff --git a/target/linux/mediatek/patches-5.15/350-18-cpufreq-mediatek-fix-KP-caused-by-handler-usage-afte.patch b/target/linux/mediatek/patches-5.15/350-18-cpufreq-mediatek-fix-KP-caused-by-handler-usage-afte.patch new file mode 100644 index 0000000000..61531d38ad --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-18-cpufreq-mediatek-fix-KP-caused-by-handler-usage-afte.patch @@ -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); + } diff --git a/target/linux/mediatek/patches-5.15/350-19-cpufreq-mediatek-raise-proc-sram-max-voltage-for-MT8.patch b/target/linux/mediatek/patches-5.15/350-19-cpufreq-mediatek-raise-proc-sram-max-voltage-for-MT8.patch new file mode 100644 index 0000000000..2b7d229f1c --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-19-cpufreq-mediatek-raise-proc-sram-max-voltage-for-MT8.patch @@ -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); diff --git a/target/linux/mediatek/patches-5.15/350-20-cpufreq-mediatek-Raise-proc-and-sram-max-voltage-for.patch b/target/linux/mediatek/patches-5.15/350-20-cpufreq-mediatek-Raise-proc-and-sram-max-voltage-for.patch new file mode 100644 index 0000000000..2de8eb6394 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-20-cpufreq-mediatek-Raise-proc-and-sram-max-voltage-for.patch @@ -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 }, diff --git a/target/linux/mediatek/patches-5.15/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch b/target/linux/mediatek/patches-5.15/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch new file mode 100644 index 0000000000..6acd3d607f --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch @@ -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 }, diff --git a/target/linux/mediatek/patches-5.15/351-cpufreq-mediatek-don-t-request-unsupported-voltage.patch b/target/linux/mediatek/patches-5.15/351-cpufreq-mediatek-don-t-request-unsupported-voltage.patch new file mode 100644 index 0000000000..a7a4bd8ea2 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/351-cpufreq-mediatek-don-t-request-unsupported-voltage.patch @@ -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, + }; + |