eeaa466c326d07504bcd70a65a8c29726c3cdc81
[openwrt/staging/jow.git] / target / linux / mediatek / patches-5.15 / 350-13-cpufreq-mediatek-Link-CCI-device-to-CPU.patch
1 From 15aaf74fb734a3e69b10d00b97b322711b81e222 Mon Sep 17 00:00:00 2001
2 From: Rex-BC Chen <rex-bc.chen@mediatek.com>
3 Date: Thu, 5 May 2022 19:52:22 +0800
4 Subject: [PATCH 13/21] cpufreq: mediatek: Link CCI device to CPU
5
6 In some MediaTek SoCs, like MT8183, CPU and CCI share the same power
7 supplies. Cpufreq needs to check if CCI devfreq exists and wait until
8 CCI devfreq ready before scaling frequency.
9
10 Before CCI devfreq is ready, we record the voltage when booting to
11 kernel and use the max(cpu target voltage, booting voltage) to
12 prevent cpufreq adjust to the lower voltage which will cause the CCI
13 crash because of high frequency and low voltage.
14
15 - Add is_ccifreq_ready() to link CCI device to CPI, and CPU will start
16 DVFS when CCI is ready.
17 - Add platform data for MT8183.
18
19 Signed-off-by: Jia-Wei Chang <jia-wei.chang@mediatek.com>
20 Signed-off-by: Rex-BC Chen <rex-bc.chen@mediatek.com>
21 Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
22 Reviewed-by: Kevin Hilman <khilman@baylibre.com>
23 Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
24 ---
25 drivers/cpufreq/mediatek-cpufreq.c | 82 +++++++++++++++++++++++++++++-
26 1 file changed, 81 insertions(+), 1 deletion(-)
27
28 --- a/drivers/cpufreq/mediatek-cpufreq.c
29 +++ b/drivers/cpufreq/mediatek-cpufreq.c
30 @@ -22,6 +22,7 @@ struct mtk_cpufreq_platform_data {
31 int proc_max_volt;
32 int sram_min_volt;
33 int sram_max_volt;
34 + bool ccifreq_supported;
35 };
36
37 /*
38 @@ -38,6 +39,7 @@ struct mtk_cpufreq_platform_data {
39 struct mtk_cpu_dvfs_info {
40 struct cpumask cpus;
41 struct device *cpu_dev;
42 + struct device *cci_dev;
43 struct regulator *proc_reg;
44 struct regulator *sram_reg;
45 struct clk *cpu_clk;
46 @@ -45,6 +47,7 @@ struct mtk_cpu_dvfs_info {
47 struct list_head list_head;
48 int intermediate_voltage;
49 bool need_voltage_tracking;
50 + int vproc_on_boot;
51 int pre_vproc;
52 /* Avoid race condition for regulators between notify and policy */
53 struct mutex reg_lock;
54 @@ -53,6 +56,7 @@ struct mtk_cpu_dvfs_info {
55 unsigned long current_freq;
56 const struct mtk_cpufreq_platform_data *soc_data;
57 int vtrack_max;
58 + bool ccifreq_bound;
59 };
60
61 static struct platform_device *cpufreq_pdev;
62 @@ -171,6 +175,28 @@ static int mtk_cpufreq_set_voltage(struc
63 return ret;
64 }
65
66 +static bool is_ccifreq_ready(struct mtk_cpu_dvfs_info *info)
67 +{
68 + struct device_link *sup_link;
69 +
70 + if (info->ccifreq_bound)
71 + return true;
72 +
73 + sup_link = device_link_add(info->cpu_dev, info->cci_dev,
74 + DL_FLAG_AUTOREMOVE_CONSUMER);
75 + if (!sup_link) {
76 + dev_err(info->cpu_dev, "cpu%d: sup_link is NULL\n", info->opp_cpu);
77 + return false;
78 + }
79 +
80 + if (sup_link->supplier->links.status != DL_DEV_DRIVER_BOUND)
81 + return false;
82 +
83 + info->ccifreq_bound = true;
84 +
85 + return true;
86 +}
87 +
88 static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
89 unsigned int index)
90 {
91 @@ -213,6 +239,14 @@ static int mtk_cpufreq_set_target(struct
92 dev_pm_opp_put(opp);
93
94 /*
95 + * If MediaTek cci is supported but is not ready, we will use the value
96 + * of max(target cpu voltage, booting voltage) to prevent high freqeuncy
97 + * low voltage crash.
98 + */
99 + if (info->soc_data->ccifreq_supported && !is_ccifreq_ready(info))
100 + vproc = max(vproc, info->vproc_on_boot);
101 +
102 + /*
103 * If the new voltage or the intermediate voltage is higher than the
104 * current voltage, scale up voltage first.
105 */
106 @@ -333,6 +367,23 @@ static int mtk_cpufreq_opp_notifier(stru
107 return notifier_from_errno(ret);
108 }
109
110 +static struct device *of_get_cci(struct device *cpu_dev)
111 +{
112 + struct device_node *np;
113 + struct platform_device *pdev;
114 +
115 + np = of_parse_phandle(cpu_dev->of_node, "mediatek,cci", 0);
116 + if (IS_ERR_OR_NULL(np))
117 + return NULL;
118 +
119 + pdev = of_find_device_by_node(np);
120 + of_node_put(np);
121 + if (IS_ERR_OR_NULL(pdev))
122 + return NULL;
123 +
124 + return &pdev->dev;
125 +}
126 +
127 static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
128 {
129 struct device *cpu_dev;
130 @@ -347,6 +398,16 @@ static int mtk_cpu_dvfs_info_init(struct
131 }
132 info->cpu_dev = cpu_dev;
133
134 + info->ccifreq_bound = false;
135 + if (info->soc_data->ccifreq_supported) {
136 + info->cci_dev = of_get_cci(info->cpu_dev);
137 + if (IS_ERR_OR_NULL(info->cci_dev)) {
138 + ret = PTR_ERR(info->cci_dev);
139 + dev_err(cpu_dev, "cpu%d: failed to get cci device\n", cpu);
140 + return -ENODEV;
141 + }
142 + }
143 +
144 info->cpu_clk = clk_get(cpu_dev, "cpu");
145 if (IS_ERR(info->cpu_clk)) {
146 ret = PTR_ERR(info->cpu_clk);
147 @@ -410,6 +471,15 @@ static int mtk_cpu_dvfs_info_init(struct
148 if (ret)
149 goto out_disable_mux_clock;
150
151 + if (info->soc_data->ccifreq_supported) {
152 + info->vproc_on_boot = regulator_get_voltage(info->proc_reg);
153 + if (info->vproc_on_boot < 0) {
154 + dev_err(info->cpu_dev,
155 + "invalid Vproc value: %d\n", info->vproc_on_boot);
156 + goto out_disable_inter_clock;
157 + }
158 + }
159 +
160 /* Search a safe voltage for intermediate frequency. */
161 rate = clk_get_rate(info->inter_clk);
162 opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
163 @@ -617,6 +687,16 @@ static const struct mtk_cpufreq_platform
164 .proc_max_volt = 1150000,
165 .sram_min_volt = 0,
166 .sram_max_volt = 1150000,
167 + .ccifreq_supported = false,
168 +};
169 +
170 +static const struct mtk_cpufreq_platform_data mt8183_platform_data = {
171 + .min_volt_shift = 100000,
172 + .max_volt_shift = 200000,
173 + .proc_max_volt = 1150000,
174 + .sram_min_volt = 0,
175 + .sram_max_volt = 1150000,
176 + .ccifreq_supported = true,
177 };
178
179 /* List of machines supported by this driver */
180 @@ -629,7 +709,7 @@ static const struct of_device_id mtk_cpu
181 { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data },
182 { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data },
183 { .compatible = "mediatek,mt8176", .data = &mt2701_platform_data },
184 - { .compatible = "mediatek,mt8183", .data = &mt2701_platform_data },
185 + { .compatible = "mediatek,mt8183", .data = &mt8183_platform_data },
186 { .compatible = "mediatek,mt8365", .data = &mt2701_platform_data },
187 { .compatible = "mediatek,mt8516", .data = &mt2701_platform_data },
188 { }