mediatek: backport cpufreq changes to support MT7988
authorDaniel Golle <daniel@makrotopia.org>
Sun, 30 Apr 2023 17:03:00 +0000 (18:03 +0100)
committerDaniel Golle <daniel@makrotopia.org>
Wed, 24 May 2023 18:26:52 +0000 (19:26 +0100)
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)

22 files changed:
target/linux/mediatek/patches-5.15/350-01-cpufreq-mediatek-Cleanup-variables-and-error-handlin.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-02-cpufreq-mediatek-Remove-unused-headers.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-03-cpufreq-mediatek-Enable-clocks-and-regulators.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-04-cpufreq-mediatek-Use-device-print-to-show-logs.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-05-cpufreq-mediatek-Replace-old_-with-pre_.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-06-cpufreq-mediatek-Record-previous-target-vproc-value.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-07-cpufreq-mediatek-Make-sram-regulator-optional.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-08-cpufreq-mediatek-Fix-NULL-pointer-dereference-in-med.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-09-cpufreq-mediatek-Move-voltage-limits-to-platform-dat.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-10-cpufreq-mediatek-Refine-mtk_cpufreq_voltage_tracking.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-11-cpufreq-mediatek-Add-opp-notification-support.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-12-cpufreq-mediatek-Fix-potential-deadlock-problem-in-m.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-13-cpufreq-mediatek-Link-CCI-device-to-CPU.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-14-cpufreq-mediatek-Add-support-for-MT8186.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-15-cpufreq-mediatek-Handle-sram-regulator-probe-deferra.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-16-cpufreq-mediatek-fix-error-return-code-in-mtk_cpu_dv.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-17-cpufreq-mediatek-fix-passing-zero-to-PTR_ERR.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-18-cpufreq-mediatek-fix-KP-caused-by-handler-usage-afte.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-19-cpufreq-mediatek-raise-proc-sram-max-voltage-for-MT8.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-20-cpufreq-mediatek-Raise-proc-and-sram-max-voltage-for.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch [new file with mode: 0644]
target/linux/mediatek/patches-5.15/351-cpufreq-mediatek-don-t-request-unsupported-voltage.patch [new file with mode: 0644]

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 (file)
index 0000000..8fad64a
--- /dev/null
@@ -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 (file)
index 0000000..eebeeb0
--- /dev/null
@@ -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 (file)
index 0000000..c97d5fc
--- /dev/null
@@ -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 (file)
index 0000000..18e1da7
--- /dev/null
@@ -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 (file)
index 0000000..8506f4e
--- /dev/null
@@ -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 (file)
index 0000000..94e6617
--- /dev/null
@@ -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 (file)
index 0000000..4b74873
--- /dev/null
@@ -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 (file)
index 0000000..f2f572a
--- /dev/null
@@ -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 (file)
index 0000000..23b3196
--- /dev/null
@@ -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 (file)
index 0000000..0ba9471
--- /dev/null
@@ -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 (file)
index 0000000..2cb99b9
--- /dev/null
@@ -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 (file)
index 0000000..76bd795
--- /dev/null
@@ -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 (file)
index 0000000..eeaa466
--- /dev/null
@@ -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 (file)
index 0000000..31000cf
--- /dev/null
@@ -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 (file)
index 0000000..c013789
--- /dev/null
@@ -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 (file)
index 0000000..45c4477
--- /dev/null
@@ -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 (file)
index 0000000..557d02b
--- /dev/null
@@ -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 (file)
index 0000000..61531d3
--- /dev/null
@@ -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 (file)
index 0000000..2b7d229
--- /dev/null
@@ -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 (file)
index 0000000..2de8eb6
--- /dev/null
@@ -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 (file)
index 0000000..6acd3d6
--- /dev/null
@@ -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 (file)
index 0000000..a7a4bd8
--- /dev/null
@@ -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,
+ };