package: add fitblk util to release /dev/fit* devices
[openwrt/staging/jow.git] / target / linux / mediatek / patches-5.15 / 350-11-cpufreq-mediatek-Add-opp-notification-support.patch
1 From 01be227eff7e5fc01f7c8de8f6daddd5fb17ddd1 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:21 +0800
4 Subject: [PATCH 11/21] cpufreq: mediatek: Add opp notification support
5
6 From this opp notifier, cpufreq should listen to opp notification and do
7 proper actions when receiving events of disable and voltage adjustment.
8
9 One of the user for this opp notifier is MediaTek SVS.
10 The MediaTek Smart Voltage Scaling (SVS) is a hardware which calculates
11 suitable SVS bank voltages to OPP voltage table.
12
13 Signed-off-by: Andrew-sh.Cheng <andrew-sh.cheng@mediatek.com>
14 Signed-off-by: Jia-Wei Chang <jia-wei.chang@mediatek.com>
15 Signed-off-by: Rex-BC Chen <rex-bc.chen@mediatek.com>
16 Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
17 [ Viresh: Renamed opp_freq as current_freq and moved its initialization ]
18 Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
19 ---
20 drivers/cpufreq/mediatek-cpufreq.c | 90 +++++++++++++++++++++++++++---
21 1 file changed, 82 insertions(+), 8 deletions(-)
22
23 --- a/drivers/cpufreq/mediatek-cpufreq.c
24 +++ b/drivers/cpufreq/mediatek-cpufreq.c
25 @@ -46,6 +46,11 @@ struct mtk_cpu_dvfs_info {
26 int intermediate_voltage;
27 bool need_voltage_tracking;
28 int pre_vproc;
29 + /* Avoid race condition for regulators between notify and policy */
30 + struct mutex reg_lock;
31 + struct notifier_block opp_nb;
32 + unsigned int opp_cpu;
33 + unsigned long current_freq;
34 const struct mtk_cpufreq_platform_data *soc_data;
35 int vtrack_max;
36 };
37 @@ -182,6 +187,8 @@ static int mtk_cpufreq_set_target(struct
38
39 pre_freq_hz = clk_get_rate(cpu_clk);
40
41 + mutex_lock(&info->reg_lock);
42 +
43 if (unlikely(info->pre_vproc <= 0))
44 pre_vproc = regulator_get_voltage(info->proc_reg);
45 else
46 @@ -214,7 +221,7 @@ static int mtk_cpufreq_set_target(struct
47 dev_err(cpu_dev,
48 "cpu%d: failed to scale up voltage!\n", policy->cpu);
49 mtk_cpufreq_set_voltage(info, pre_vproc);
50 - return ret;
51 + goto out;
52 }
53 }
54
55 @@ -224,8 +231,7 @@ static int mtk_cpufreq_set_target(struct
56 dev_err(cpu_dev,
57 "cpu%d: failed to re-parent cpu clock!\n", policy->cpu);
58 mtk_cpufreq_set_voltage(info, pre_vproc);
59 - WARN_ON(1);
60 - return ret;
61 + goto out;
62 }
63
64 /* Set the original PLL to target rate. */
65 @@ -235,7 +241,7 @@ static int mtk_cpufreq_set_target(struct
66 "cpu%d: failed to scale cpu clock rate!\n", policy->cpu);
67 clk_set_parent(cpu_clk, armpll);
68 mtk_cpufreq_set_voltage(info, pre_vproc);
69 - return ret;
70 + goto out;
71 }
72
73 /* Set parent of CPU clock back to the original PLL. */
74 @@ -244,8 +250,7 @@ static int mtk_cpufreq_set_target(struct
75 dev_err(cpu_dev,
76 "cpu%d: failed to re-parent cpu clock!\n", policy->cpu);
77 mtk_cpufreq_set_voltage(info, inter_vproc);
78 - WARN_ON(1);
79 - return ret;
80 + goto out;
81 }
82
83 /*
84 @@ -260,15 +265,72 @@ static int mtk_cpufreq_set_target(struct
85 clk_set_parent(cpu_clk, info->inter_clk);
86 clk_set_rate(armpll, pre_freq_hz);
87 clk_set_parent(cpu_clk, armpll);
88 - return ret;
89 + goto out;
90 }
91 }
92
93 - return 0;
94 + info->current_freq = freq_hz;
95 +
96 +out:
97 + mutex_unlock(&info->reg_lock);
98 +
99 + return ret;
100 }
101
102 #define DYNAMIC_POWER "dynamic-power-coefficient"
103
104 +static int mtk_cpufreq_opp_notifier(struct notifier_block *nb,
105 + unsigned long event, void *data)
106 +{
107 + struct dev_pm_opp *opp = data;
108 + struct dev_pm_opp *new_opp;
109 + struct mtk_cpu_dvfs_info *info;
110 + unsigned long freq, volt;
111 + struct cpufreq_policy *policy;
112 + int ret = 0;
113 +
114 + info = container_of(nb, struct mtk_cpu_dvfs_info, opp_nb);
115 +
116 + if (event == OPP_EVENT_ADJUST_VOLTAGE) {
117 + freq = dev_pm_opp_get_freq(opp);
118 +
119 + mutex_lock(&info->reg_lock);
120 + if (info->current_freq == freq) {
121 + volt = dev_pm_opp_get_voltage(opp);
122 + ret = mtk_cpufreq_set_voltage(info, volt);
123 + if (ret)
124 + dev_err(info->cpu_dev,
125 + "failed to scale voltage: %d\n", ret);
126 + }
127 + mutex_unlock(&info->reg_lock);
128 + } else if (event == OPP_EVENT_DISABLE) {
129 + freq = dev_pm_opp_get_freq(opp);
130 +
131 + /* case of current opp item is disabled */
132 + if (info->current_freq == freq) {
133 + freq = 1;
134 + new_opp = dev_pm_opp_find_freq_ceil(info->cpu_dev,
135 + &freq);
136 + if (IS_ERR(new_opp)) {
137 + dev_err(info->cpu_dev,
138 + "all opp items are disabled\n");
139 + ret = PTR_ERR(new_opp);
140 + return notifier_from_errno(ret);
141 + }
142 +
143 + dev_pm_opp_put(new_opp);
144 + policy = cpufreq_cpu_get(info->opp_cpu);
145 + if (policy) {
146 + cpufreq_driver_target(policy, freq / 1000,
147 + CPUFREQ_RELATION_L);
148 + cpufreq_cpu_put(policy);
149 + }
150 + }
151 + }
152 +
153 + return notifier_from_errno(ret);
154 +}
155 +
156 static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
157 {
158 struct device *cpu_dev;
159 @@ -357,6 +419,17 @@ static int mtk_cpu_dvfs_info_init(struct
160 info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
161 dev_pm_opp_put(opp);
162
163 + mutex_init(&info->reg_lock);
164 + info->current_freq = clk_get_rate(info->cpu_clk);
165 +
166 + info->opp_cpu = cpu;
167 + info->opp_nb.notifier_call = mtk_cpufreq_opp_notifier;
168 + ret = dev_pm_opp_register_notifier(cpu_dev, &info->opp_nb);
169 + if (ret) {
170 + dev_err(cpu_dev, "cpu%d: failed to register opp notifier\n", cpu);
171 + goto out_disable_inter_clock;
172 + }
173 +
174 /*
175 * If SRAM regulator is present, software "voltage tracking" is needed
176 * for this CPU power domain.
177 @@ -421,6 +494,7 @@ static void mtk_cpu_dvfs_info_release(st
178 }
179
180 dev_pm_opp_of_cpumask_remove_table(&info->cpus);
181 + dev_pm_opp_unregister_notifier(info->cpu_dev, &info->opp_nb);
182 }
183
184 static int mtk_cpufreq_init(struct cpufreq_policy *policy)