mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-22 15:02:32 +00:00
670dedbbd7
Backport cpufreq changes from upstream so that the MediaTek MT7988 SoC
can be supported.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
(cherry picked from commit e4555d69a1
)
189 lines
5.8 KiB
Diff
189 lines
5.8 KiB
Diff
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 },
|
|
{ }
|