Skip to content

Commit 0daa473

Browse files
mtk-rex-bc-chenvireshk
authored andcommitted
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>
1 parent 818c832 commit 0daa473

1 file changed

Lines changed: 81 additions & 1 deletion

File tree

drivers/cpufreq/mediatek-cpufreq.c

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ struct mtk_cpufreq_platform_data {
2222
int proc_max_volt;
2323
int sram_min_volt;
2424
int sram_max_volt;
25+
bool ccifreq_supported;
2526
};
2627

2728
/*
@@ -38,13 +39,15 @@ struct mtk_cpufreq_platform_data {
3839
struct mtk_cpu_dvfs_info {
3940
struct cpumask cpus;
4041
struct device *cpu_dev;
42+
struct device *cci_dev;
4143
struct regulator *proc_reg;
4244
struct regulator *sram_reg;
4345
struct clk *cpu_clk;
4446
struct clk *inter_clk;
4547
struct list_head list_head;
4648
int intermediate_voltage;
4749
bool need_voltage_tracking;
50+
int vproc_on_boot;
4851
int pre_vproc;
4952
/* Avoid race condition for regulators between notify and policy */
5053
struct mutex reg_lock;
@@ -53,6 +56,7 @@ struct mtk_cpu_dvfs_info {
5356
unsigned long current_freq;
5457
const struct mtk_cpufreq_platform_data *soc_data;
5558
int vtrack_max;
59+
bool ccifreq_bound;
5660
};
5761

5862
static struct platform_device *cpufreq_pdev;
@@ -171,6 +175,28 @@ static int mtk_cpufreq_set_voltage(struct mtk_cpu_dvfs_info *info, int vproc)
171175
return ret;
172176
}
173177

178+
static bool is_ccifreq_ready(struct mtk_cpu_dvfs_info *info)
179+
{
180+
struct device_link *sup_link;
181+
182+
if (info->ccifreq_bound)
183+
return true;
184+
185+
sup_link = device_link_add(info->cpu_dev, info->cci_dev,
186+
DL_FLAG_AUTOREMOVE_CONSUMER);
187+
if (!sup_link) {
188+
dev_err(info->cpu_dev, "cpu%d: sup_link is NULL\n", info->opp_cpu);
189+
return false;
190+
}
191+
192+
if (sup_link->supplier->links.status != DL_DEV_DRIVER_BOUND)
193+
return false;
194+
195+
info->ccifreq_bound = true;
196+
197+
return true;
198+
}
199+
174200
static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
175201
unsigned int index)
176202
{
@@ -212,6 +238,14 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
212238
vproc = dev_pm_opp_get_voltage(opp);
213239
dev_pm_opp_put(opp);
214240

241+
/*
242+
* If MediaTek cci is supported but is not ready, we will use the value
243+
* of max(target cpu voltage, booting voltage) to prevent high freqeuncy
244+
* low voltage crash.
245+
*/
246+
if (info->soc_data->ccifreq_supported && !is_ccifreq_ready(info))
247+
vproc = max(vproc, info->vproc_on_boot);
248+
215249
/*
216250
* If the new voltage or the intermediate voltage is higher than the
217251
* current voltage, scale up voltage first.
@@ -333,6 +367,23 @@ static int mtk_cpufreq_opp_notifier(struct notifier_block *nb,
333367
return notifier_from_errno(ret);
334368
}
335369

370+
static struct device *of_get_cci(struct device *cpu_dev)
371+
{
372+
struct device_node *np;
373+
struct platform_device *pdev;
374+
375+
np = of_parse_phandle(cpu_dev->of_node, "mediatek,cci", 0);
376+
if (IS_ERR_OR_NULL(np))
377+
return NULL;
378+
379+
pdev = of_find_device_by_node(np);
380+
of_node_put(np);
381+
if (IS_ERR_OR_NULL(pdev))
382+
return NULL;
383+
384+
return &pdev->dev;
385+
}
386+
336387
static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
337388
{
338389
struct device *cpu_dev;
@@ -347,6 +398,16 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
347398
}
348399
info->cpu_dev = cpu_dev;
349400

401+
info->ccifreq_bound = false;
402+
if (info->soc_data->ccifreq_supported) {
403+
info->cci_dev = of_get_cci(info->cpu_dev);
404+
if (IS_ERR_OR_NULL(info->cci_dev)) {
405+
ret = PTR_ERR(info->cci_dev);
406+
dev_err(cpu_dev, "cpu%d: failed to get cci device\n", cpu);
407+
return -ENODEV;
408+
}
409+
}
410+
350411
info->cpu_clk = clk_get(cpu_dev, "cpu");
351412
if (IS_ERR(info->cpu_clk)) {
352413
ret = PTR_ERR(info->cpu_clk);
@@ -410,6 +471,15 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
410471
if (ret)
411472
goto out_disable_mux_clock;
412473

474+
if (info->soc_data->ccifreq_supported) {
475+
info->vproc_on_boot = regulator_get_voltage(info->proc_reg);
476+
if (info->vproc_on_boot < 0) {
477+
dev_err(info->cpu_dev,
478+
"invalid Vproc value: %d\n", info->vproc_on_boot);
479+
goto out_disable_inter_clock;
480+
}
481+
}
482+
413483
/* Search a safe voltage for intermediate frequency. */
414484
rate = clk_get_rate(info->inter_clk);
415485
opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
@@ -617,6 +687,16 @@ static const struct mtk_cpufreq_platform_data mt2701_platform_data = {
617687
.proc_max_volt = 1150000,
618688
.sram_min_volt = 0,
619689
.sram_max_volt = 1150000,
690+
.ccifreq_supported = false,
691+
};
692+
693+
static const struct mtk_cpufreq_platform_data mt8183_platform_data = {
694+
.min_volt_shift = 100000,
695+
.max_volt_shift = 200000,
696+
.proc_max_volt = 1150000,
697+
.sram_min_volt = 0,
698+
.sram_max_volt = 1150000,
699+
.ccifreq_supported = true,
620700
};
621701

622702
/* List of machines supported by this driver */
@@ -629,7 +709,7 @@ static const struct of_device_id mtk_cpufreq_machines[] __initconst = {
629709
{ .compatible = "mediatek,mt817x", .data = &mt2701_platform_data },
630710
{ .compatible = "mediatek,mt8173", .data = &mt2701_platform_data },
631711
{ .compatible = "mediatek,mt8176", .data = &mt2701_platform_data },
632-
{ .compatible = "mediatek,mt8183", .data = &mt2701_platform_data },
712+
{ .compatible = "mediatek,mt8183", .data = &mt8183_platform_data },
633713
{ .compatible = "mediatek,mt8365", .data = &mt2701_platform_data },
634714
{ .compatible = "mediatek,mt8516", .data = &mt2701_platform_data },
635715
{ }

0 commit comments

Comments
 (0)