.. | .. |
---|
1 | 1 | // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note |
---|
2 | 2 | /* |
---|
3 | 3 | * |
---|
4 | | - * (C) COPYRIGHT 2014-2020 ARM Limited. All rights reserved. |
---|
| 4 | + * (C) COPYRIGHT 2014-2022 ARM Limited. All rights reserved. |
---|
5 | 5 | * |
---|
6 | 6 | * This program is free software and is provided to you under the terms of the |
---|
7 | 7 | * GNU General Public License version 2 as published by the Free Software |
---|
.. | .. |
---|
23 | 23 | |
---|
24 | 24 | #include <mali_kbase.h> |
---|
25 | 25 | #include <tl/mali_kbase_tracepoints.h> |
---|
| 26 | +#include <backend/gpu/mali_kbase_devfreq.h> |
---|
26 | 27 | #include <backend/gpu/mali_kbase_pm_internal.h> |
---|
27 | 28 | |
---|
28 | 29 | #include <linux/of.h> |
---|
29 | 30 | #include <linux/clk.h> |
---|
| 31 | +#include <linux/clk-provider.h> |
---|
30 | 32 | #include <linux/devfreq.h> |
---|
31 | 33 | #if IS_ENABLED(CONFIG_DEVFREQ_THERMAL) |
---|
32 | 34 | #include <linux/devfreq_cooling.h> |
---|
.. | .. |
---|
34 | 36 | |
---|
35 | 37 | #include <linux/version.h> |
---|
36 | 38 | #include <linux/pm_opp.h> |
---|
| 39 | +#include <linux/pm_runtime.h> |
---|
| 40 | +#include "mali_kbase_devfreq.h" |
---|
37 | 41 | |
---|
38 | 42 | #include <soc/rockchip/rockchip_ipa.h> |
---|
39 | 43 | #include <soc/rockchip/rockchip_opp_select.h> |
---|
.. | .. |
---|
42 | 46 | static struct devfreq_simple_ondemand_data ondemand_data; |
---|
43 | 47 | |
---|
44 | 48 | static struct monitor_dev_profile mali_mdevp = { |
---|
45 | | - .type = MONITOR_TPYE_DEV, |
---|
| 49 | + .type = MONITOR_TYPE_DEV, |
---|
46 | 50 | .low_temp_adjust = rockchip_monitor_dev_low_temp_adjust, |
---|
47 | 51 | .high_temp_adjust = rockchip_monitor_dev_high_temp_adjust, |
---|
| 52 | + .update_volt = rockchip_monitor_check_rate_volt, |
---|
48 | 53 | }; |
---|
49 | 54 | |
---|
| 55 | +/** |
---|
| 56 | + * get_voltage() - Get the voltage value corresponding to the nominal frequency |
---|
| 57 | + * used by devfreq. |
---|
| 58 | + * @kbdev: Device pointer |
---|
| 59 | + * @freq: Nominal frequency in Hz passed by devfreq. |
---|
| 60 | + * |
---|
| 61 | + * This function will be called only when the opp table which is compatible with |
---|
| 62 | + * "operating-points-v2-mali", is not present in the devicetree for GPU device. |
---|
| 63 | + * |
---|
| 64 | + * Return: Voltage value in micro volts, 0 in case of error. |
---|
| 65 | + */ |
---|
| 66 | +static unsigned long get_voltage(struct kbase_device *kbdev, unsigned long freq) |
---|
| 67 | +{ |
---|
| 68 | + struct dev_pm_opp *opp; |
---|
| 69 | + unsigned long voltage = 0; |
---|
| 70 | + |
---|
| 71 | +#if KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE |
---|
| 72 | + rcu_read_lock(); |
---|
| 73 | +#endif |
---|
| 74 | + |
---|
| 75 | + opp = dev_pm_opp_find_freq_exact(kbdev->dev, freq, true); |
---|
| 76 | + |
---|
| 77 | + if (IS_ERR_OR_NULL(opp)) |
---|
| 78 | + dev_err(kbdev->dev, "Failed to get opp (%d)\n", PTR_ERR_OR_ZERO(opp)); |
---|
| 79 | + else { |
---|
| 80 | + voltage = dev_pm_opp_get_voltage(opp); |
---|
| 81 | +#if KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE |
---|
| 82 | + dev_pm_opp_put(opp); |
---|
| 83 | +#endif |
---|
| 84 | + } |
---|
| 85 | + |
---|
| 86 | +#if KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE |
---|
| 87 | + rcu_read_unlock(); |
---|
| 88 | +#endif |
---|
| 89 | + |
---|
| 90 | + /* Return the voltage in micro volts */ |
---|
| 91 | + return voltage; |
---|
| 92 | +} |
---|
| 93 | + |
---|
50 | 94 | void kbase_devfreq_opp_translate(struct kbase_device *kbdev, unsigned long freq, |
---|
51 | | - unsigned long volt, u64 *core_mask, |
---|
52 | | - unsigned long *freqs, unsigned long *volts) |
---|
| 95 | + u64 *core_mask, unsigned long *freqs, unsigned long *volts) |
---|
53 | 96 | { |
---|
54 | 97 | unsigned int i; |
---|
55 | 98 | |
---|
.. | .. |
---|
73 | 116 | * and nominal frequency and the corresponding voltage. |
---|
74 | 117 | */ |
---|
75 | 118 | if (i == kbdev->num_opps) { |
---|
| 119 | + unsigned long voltage = get_voltage(kbdev, freq); |
---|
| 120 | + |
---|
76 | 121 | *core_mask = kbdev->gpu_props.props.raw_props.shader_present; |
---|
77 | 122 | |
---|
78 | 123 | for (i = 0; i < kbdev->nr_clocks; i++) { |
---|
79 | 124 | freqs[i] = freq; |
---|
80 | | - volts[i] = volt; |
---|
| 125 | + volts[i] = voltage; |
---|
81 | 126 | } |
---|
82 | 127 | } |
---|
83 | 128 | } |
---|
84 | 129 | |
---|
| 130 | +int kbase_devfreq_opp_helper(struct dev_pm_set_opp_data *data) |
---|
| 131 | +{ |
---|
| 132 | + struct device *dev = data->dev; |
---|
| 133 | + struct dev_pm_opp_supply *old_supply_vdd = &data->old_opp.supplies[0]; |
---|
| 134 | + struct dev_pm_opp_supply *new_supply_vdd = &data->new_opp.supplies[0]; |
---|
| 135 | + struct regulator *vdd_reg = data->regulators[0]; |
---|
| 136 | + struct dev_pm_opp_supply *old_supply_mem; |
---|
| 137 | + struct dev_pm_opp_supply *new_supply_mem; |
---|
| 138 | + struct regulator *mem_reg; |
---|
| 139 | + struct clk *clk = data->clk; |
---|
| 140 | + struct kbase_device *kbdev = dev_get_drvdata(dev); |
---|
| 141 | + struct rockchip_opp_info *opp_info = &kbdev->opp_info; |
---|
| 142 | + unsigned long old_freq = data->old_opp.rate; |
---|
| 143 | + unsigned long new_freq = data->new_opp.rate; |
---|
| 144 | + unsigned int reg_count = data->regulator_count; |
---|
| 145 | + bool is_set_rm = true; |
---|
| 146 | + bool is_set_clk = true; |
---|
| 147 | + u32 target_rm = UINT_MAX; |
---|
| 148 | + int ret = 0; |
---|
| 149 | + |
---|
| 150 | + if (reg_count > 1) { |
---|
| 151 | + old_supply_mem = &data->old_opp.supplies[1]; |
---|
| 152 | + new_supply_mem = &data->new_opp.supplies[1]; |
---|
| 153 | + mem_reg = data->regulators[1]; |
---|
| 154 | + } |
---|
| 155 | + |
---|
| 156 | + if (!pm_runtime_active(dev)) { |
---|
| 157 | + is_set_rm = false; |
---|
| 158 | + if (opp_info->scmi_clk) |
---|
| 159 | + is_set_clk = false; |
---|
| 160 | + } |
---|
| 161 | + |
---|
| 162 | + ret = clk_bulk_prepare_enable(opp_info->num_clks, opp_info->clks); |
---|
| 163 | + if (ret) { |
---|
| 164 | + dev_err(dev, "failed to enable opp clks\n"); |
---|
| 165 | + return ret; |
---|
| 166 | + } |
---|
| 167 | + rockchip_get_read_margin(dev, opp_info, new_supply_vdd->u_volt, |
---|
| 168 | + &target_rm); |
---|
| 169 | + |
---|
| 170 | + /* Change frequency */ |
---|
| 171 | + dev_dbg(dev, "switching OPP: %lu Hz --> %lu Hz\n", old_freq, new_freq); |
---|
| 172 | + /* Scaling up? Scale voltage before frequency */ |
---|
| 173 | + if (new_freq >= old_freq) { |
---|
| 174 | + rockchip_set_intermediate_rate(dev, opp_info, clk, old_freq, |
---|
| 175 | + new_freq, true, is_set_clk); |
---|
| 176 | + if (reg_count > 1) { |
---|
| 177 | + ret = regulator_set_voltage(mem_reg, |
---|
| 178 | + new_supply_mem->u_volt, |
---|
| 179 | + INT_MAX); |
---|
| 180 | + if (ret) { |
---|
| 181 | + dev_err(dev, "failed to set volt %lu uV for mem reg\n", |
---|
| 182 | + new_supply_mem->u_volt); |
---|
| 183 | + goto restore_voltage; |
---|
| 184 | + } |
---|
| 185 | + } |
---|
| 186 | + ret = regulator_set_voltage(vdd_reg, new_supply_vdd->u_volt, |
---|
| 187 | + INT_MAX); |
---|
| 188 | + if (ret) { |
---|
| 189 | + dev_err(dev, "failed to set volt %lu uV for vdd reg\n", |
---|
| 190 | + new_supply_vdd->u_volt); |
---|
| 191 | + goto restore_voltage; |
---|
| 192 | + } |
---|
| 193 | + rockchip_set_read_margin(dev, opp_info, target_rm, is_set_rm); |
---|
| 194 | + if (is_set_clk && clk_set_rate(clk, new_freq)) { |
---|
| 195 | + ret = -EINVAL; |
---|
| 196 | + dev_err(dev, "failed to set clk rate\n"); |
---|
| 197 | + goto restore_rm; |
---|
| 198 | + } |
---|
| 199 | + /* Scaling down? Scale voltage after frequency */ |
---|
| 200 | + } else { |
---|
| 201 | + rockchip_set_intermediate_rate(dev, opp_info, clk, old_freq, |
---|
| 202 | + new_freq, false, is_set_clk); |
---|
| 203 | + rockchip_set_read_margin(dev, opp_info, target_rm, is_set_rm); |
---|
| 204 | + if (is_set_clk && clk_set_rate(clk, new_freq)) { |
---|
| 205 | + ret = -EINVAL; |
---|
| 206 | + dev_err(dev, "failed to set clk rate\n"); |
---|
| 207 | + goto restore_rm; |
---|
| 208 | + } |
---|
| 209 | + ret = regulator_set_voltage(vdd_reg, new_supply_vdd->u_volt, |
---|
| 210 | + INT_MAX); |
---|
| 211 | + if (ret) { |
---|
| 212 | + dev_err(dev, "failed to set volt %lu uV for vdd reg\n", |
---|
| 213 | + new_supply_vdd->u_volt); |
---|
| 214 | + goto restore_freq; |
---|
| 215 | + } |
---|
| 216 | + if (reg_count > 1) { |
---|
| 217 | + ret = regulator_set_voltage(mem_reg, |
---|
| 218 | + new_supply_mem->u_volt, |
---|
| 219 | + INT_MAX); |
---|
| 220 | + if (ret) { |
---|
| 221 | + dev_err(dev, "failed to set volt %lu uV for mem reg\n", |
---|
| 222 | + new_supply_mem->u_volt); |
---|
| 223 | + goto restore_voltage; |
---|
| 224 | + } |
---|
| 225 | + } |
---|
| 226 | + } |
---|
| 227 | + |
---|
| 228 | + clk_bulk_disable_unprepare(opp_info->num_clks, opp_info->clks); |
---|
| 229 | + |
---|
| 230 | + return 0; |
---|
| 231 | + |
---|
| 232 | +restore_freq: |
---|
| 233 | + if (is_set_clk && clk_set_rate(clk, old_freq)) |
---|
| 234 | + dev_err(dev, "failed to restore old-freq %lu Hz\n", old_freq); |
---|
| 235 | +restore_rm: |
---|
| 236 | + rockchip_get_read_margin(dev, opp_info, old_supply_vdd->u_volt, |
---|
| 237 | + &target_rm); |
---|
| 238 | + rockchip_set_read_margin(dev, opp_info, opp_info->target_rm, is_set_rm); |
---|
| 239 | +restore_voltage: |
---|
| 240 | + if (reg_count > 1 && old_supply_mem->u_volt) |
---|
| 241 | + regulator_set_voltage(mem_reg, old_supply_mem->u_volt, INT_MAX); |
---|
| 242 | + regulator_set_voltage(vdd_reg, old_supply_vdd->u_volt, INT_MAX); |
---|
| 243 | + clk_bulk_disable_unprepare(opp_info->num_clks, opp_info->clks); |
---|
| 244 | + |
---|
| 245 | + return ret; |
---|
| 246 | +} |
---|
| 247 | + |
---|
85 | 248 | static int |
---|
86 | | -kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags) |
---|
| 249 | +kbase_devfreq_target(struct device *dev, unsigned long *freq, u32 flags) |
---|
87 | 250 | { |
---|
88 | 251 | struct kbase_device *kbdev = dev_get_drvdata(dev); |
---|
89 | 252 | struct dev_pm_opp *opp; |
---|
90 | | - unsigned long nominal_freq, nominal_volt; |
---|
91 | | - unsigned long freqs[BASE_MAX_NR_CLOCKS_REGULATORS] = {0}; |
---|
92 | | - unsigned long old_freqs[BASE_MAX_NR_CLOCKS_REGULATORS] = {0}; |
---|
93 | | - unsigned long volts[BASE_MAX_NR_CLOCKS_REGULATORS] = {0}; |
---|
94 | | - unsigned int i; |
---|
95 | | - u64 core_mask = 0; |
---|
| 253 | + int ret = 0; |
---|
96 | 254 | |
---|
97 | | - nominal_freq = *target_freq; |
---|
| 255 | + if (!mali_mdevp.is_checked) |
---|
| 256 | + return -EINVAL; |
---|
98 | 257 | |
---|
99 | | -#if KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE |
---|
100 | | - rcu_read_lock(); |
---|
101 | | -#endif |
---|
102 | | - opp = devfreq_recommended_opp(dev, &nominal_freq, flags); |
---|
103 | | - if (IS_ERR_OR_NULL(opp)) { |
---|
104 | | -#if KERNEL_VERSION(4, 11, 0) > LINUX_VERSION_CODE |
---|
105 | | - rcu_read_unlock(); |
---|
106 | | -#endif |
---|
107 | | - dev_err(dev, "Failed to get opp (%ld)\n", PTR_ERR(opp)); |
---|
| 258 | + opp = devfreq_recommended_opp(dev, freq, flags); |
---|
| 259 | + if (IS_ERR(opp)) |
---|
108 | 260 | return PTR_ERR(opp); |
---|
109 | | - } |
---|
110 | | - nominal_volt = dev_pm_opp_get_voltage(opp); |
---|
111 | | -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) |
---|
112 | | - rcu_read_unlock(); |
---|
113 | | -#endif |
---|
114 | | -#if KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE |
---|
115 | 261 | dev_pm_opp_put(opp); |
---|
116 | | -#endif |
---|
117 | 262 | |
---|
118 | | - kbase_devfreq_opp_translate(kbdev, |
---|
119 | | - nominal_freq, |
---|
120 | | - nominal_volt, |
---|
121 | | - &core_mask, |
---|
122 | | - freqs, |
---|
123 | | - volts); |
---|
124 | | - |
---|
125 | | - /* |
---|
126 | | - * Only update if there is a change of frequency |
---|
127 | | - */ |
---|
128 | | - if (kbdev->current_nominal_freq == nominal_freq) { |
---|
129 | | - unsigned int i; |
---|
130 | | - int err; |
---|
131 | | - |
---|
132 | | - *target_freq = nominal_freq; |
---|
133 | | - |
---|
134 | | -#ifdef CONFIG_REGULATOR |
---|
135 | | - for (i = 0; i < kbdev->nr_regulators; i++) { |
---|
136 | | - if (kbdev->current_voltages[i] == volts[i]) |
---|
137 | | - continue; |
---|
138 | | - |
---|
139 | | - err = regulator_set_voltage(kbdev->regulators[i], |
---|
140 | | - volts[i], |
---|
141 | | - INT_MAX); |
---|
142 | | - if (err) { |
---|
143 | | - dev_err(dev, "Failed to set voltage (%d)\n", err); |
---|
144 | | - return err; |
---|
145 | | - } |
---|
146 | | - kbdev->current_voltages[i] = volts[i]; |
---|
147 | | - } |
---|
148 | | -#endif |
---|
| 263 | + if (*freq == kbdev->current_nominal_freq) |
---|
149 | 264 | return 0; |
---|
| 265 | + rockchip_monitor_volt_adjust_lock(kbdev->mdev_info); |
---|
| 266 | + ret = dev_pm_opp_set_rate(dev, *freq); |
---|
| 267 | + if (!ret) { |
---|
| 268 | + kbdev->current_nominal_freq = *freq; |
---|
| 269 | + KBASE_TLSTREAM_AUX_DEVFREQ_TARGET(kbdev, (u64)*freq); |
---|
150 | 270 | } |
---|
| 271 | + rockchip_monitor_volt_adjust_unlock(kbdev->mdev_info); |
---|
151 | 272 | |
---|
152 | | - dev_dbg(dev, "%lu-->%lu\n", kbdev->current_nominal_freq, nominal_freq); |
---|
153 | | - |
---|
154 | | -#if IS_ENABLED(CONFIG_REGULATOR) |
---|
155 | | - /* Regulators and clocks work in pairs: every clock has a regulator, |
---|
156 | | - * and we never expect to have more regulators than clocks. |
---|
157 | | - * |
---|
158 | | - * We always need to increase the voltage before increasing |
---|
159 | | - * the frequency of a regulator/clock pair, otherwise the clock |
---|
160 | | - * wouldn't have enough power to perform the transition. |
---|
161 | | - * |
---|
162 | | - * It's always safer to decrease the frequency before decreasing |
---|
163 | | - * voltage of a regulator/clock pair, otherwise the clock could have |
---|
164 | | - * problems operating if it is deprived of the necessary power |
---|
165 | | - * to sustain its current frequency (even if that happens for a short |
---|
166 | | - * transition interval). |
---|
167 | | - */ |
---|
168 | | - |
---|
169 | | - for (i = 0; i < kbdev->nr_clocks; i++) |
---|
170 | | - old_freqs[i] = kbdev->current_freqs[i]; |
---|
171 | | - |
---|
172 | | - for (i = 0; i < kbdev->nr_clocks; i++) { |
---|
173 | | - if (kbdev->regulators[i] && |
---|
174 | | - kbdev->current_voltages[i] != volts[i] && |
---|
175 | | - old_freqs[i] < freqs[i]) { |
---|
176 | | - int err; |
---|
177 | | - |
---|
178 | | - err = regulator_set_voltage(kbdev->regulators[i], |
---|
179 | | - volts[i], INT_MAX); |
---|
180 | | - if (!err) { |
---|
181 | | - kbdev->current_voltages[i] = volts[i]; |
---|
182 | | - } else { |
---|
183 | | - dev_err(dev, "Failed to increase voltage (%d) (target %lu)\n", |
---|
184 | | - err, volts[i]); |
---|
185 | | - return err; |
---|
186 | | - } |
---|
187 | | - } |
---|
188 | | - } |
---|
189 | | -#endif |
---|
190 | | - |
---|
191 | | - for (i = 0; i < kbdev->nr_clocks; i++) { |
---|
192 | | - if (kbdev->clocks[i]) { |
---|
193 | | - int err; |
---|
194 | | - |
---|
195 | | - err = clk_set_rate(kbdev->clocks[i], freqs[i]); |
---|
196 | | - if (!err) { |
---|
197 | | - kbdev->current_freqs[i] = freqs[i]; |
---|
198 | | - } else { |
---|
199 | | - dev_err(dev, "Failed to set clock %lu (target %lu)\n", |
---|
200 | | - freqs[i], *target_freq); |
---|
201 | | - return err; |
---|
202 | | - } |
---|
203 | | - } |
---|
204 | | - } |
---|
205 | | - |
---|
206 | | -#if IS_ENABLED(CONFIG_REGULATOR) |
---|
207 | | - for (i = 0; i < kbdev->nr_clocks; i++) { |
---|
208 | | - if (kbdev->regulators[i] && |
---|
209 | | - kbdev->current_voltages[i] != volts[i] && |
---|
210 | | - old_freqs[i] > freqs[i]) { |
---|
211 | | - int err; |
---|
212 | | - |
---|
213 | | - err = regulator_set_voltage(kbdev->regulators[i], |
---|
214 | | - volts[i], INT_MAX); |
---|
215 | | - if (!err) { |
---|
216 | | - kbdev->current_voltages[i] = volts[i]; |
---|
217 | | - } else { |
---|
218 | | - dev_err(dev, "Failed to decrease voltage (%d) (target %lu)\n", |
---|
219 | | - err, volts[i]); |
---|
220 | | - return err; |
---|
221 | | - } |
---|
222 | | - } |
---|
223 | | - } |
---|
224 | | -#endif |
---|
225 | | - |
---|
226 | | - kbase_devfreq_set_core_mask(kbdev, core_mask); |
---|
227 | | - |
---|
228 | | - *target_freq = nominal_freq; |
---|
229 | | - kbdev->current_nominal_freq = nominal_freq; |
---|
230 | | - kbdev->current_core_mask = core_mask; |
---|
231 | | - if (kbdev->devfreq) |
---|
232 | | - kbdev->devfreq->last_status.current_frequency = nominal_freq; |
---|
233 | | - |
---|
234 | | - KBASE_TLSTREAM_AUX_DEVFREQ_TARGET(kbdev, (u64)nominal_freq); |
---|
235 | | - |
---|
236 | | - return 0; |
---|
| 273 | + return ret; |
---|
237 | 274 | } |
---|
238 | 275 | |
---|
239 | 276 | void kbase_devfreq_force_freq(struct kbase_device *kbdev, unsigned long freq) |
---|
.. | .. |
---|
267 | 304 | stat->private_data = NULL; |
---|
268 | 305 | |
---|
269 | 306 | #if MALI_USE_CSF && defined CONFIG_DEVFREQ_THERMAL |
---|
270 | | - kbase_ipa_reset_data(kbdev); |
---|
| 307 | + if (!kbdev->dfc_power.dyn_power_coeff) |
---|
| 308 | + kbase_ipa_reset_data(kbdev); |
---|
271 | 309 | #endif |
---|
272 | 310 | |
---|
273 | 311 | return 0; |
---|
.. | .. |
---|
318 | 356 | count, i); |
---|
319 | 357 | |
---|
320 | 358 | dp->max_state = i; |
---|
| 359 | + |
---|
321 | 360 | |
---|
322 | 361 | /* Have the lowest clock as suspend clock. |
---|
323 | 362 | * It may be overridden by 'opp-mali-errata-1485982'. |
---|
.. | .. |
---|
642 | 681 | return rockchip_ipa_get_static_power(kbdev->model_data, voltage); |
---|
643 | 682 | } |
---|
644 | 683 | |
---|
645 | | -static struct devfreq_cooling_power kbase_cooling_power = { |
---|
646 | | - .get_static_power = &kbase_devfreq_get_static_power, |
---|
647 | | -}; |
---|
648 | | - |
---|
649 | 684 | int kbase_devfreq_init(struct kbase_device *kbdev) |
---|
650 | 685 | { |
---|
651 | | - struct devfreq_cooling_power *kbase_dcp = &kbase_cooling_power; |
---|
| 686 | + struct devfreq_cooling_power *kbase_dcp = &kbdev->dfc_power; |
---|
652 | 687 | struct device_node *np = kbdev->dev->of_node; |
---|
| 688 | + struct device_node *model_node; |
---|
653 | 689 | struct devfreq_dev_profile *dp; |
---|
654 | 690 | int err; |
---|
655 | 691 | struct dev_pm_opp *opp; |
---|
656 | | - unsigned long opp_rate; |
---|
657 | 692 | unsigned int i; |
---|
| 693 | + bool free_devfreq_freq_table = true; |
---|
658 | 694 | |
---|
659 | 695 | if (kbdev->nr_clocks == 0) { |
---|
660 | 696 | dev_err(kbdev->dev, "Clock not available for devfreq\n"); |
---|
.. | .. |
---|
668 | 704 | else |
---|
669 | 705 | kbdev->current_freqs[i] = 0; |
---|
670 | 706 | } |
---|
| 707 | + if (strstr(__clk_get_name(kbdev->clocks[0]), "scmi")) |
---|
| 708 | + kbdev->opp_info.scmi_clk = kbdev->clocks[0]; |
---|
671 | 709 | kbdev->current_nominal_freq = kbdev->current_freqs[0]; |
---|
| 710 | + |
---|
| 711 | + opp = devfreq_recommended_opp(kbdev->dev, &kbdev->current_nominal_freq, 0); |
---|
| 712 | + if (IS_ERR(opp)) |
---|
| 713 | + return PTR_ERR(opp); |
---|
| 714 | + dev_pm_opp_put(opp); |
---|
672 | 715 | |
---|
673 | 716 | dp = &kbdev->devfreq_profile; |
---|
674 | 717 | |
---|
675 | | - dp->initial_freq = kbdev->current_freqs[0]; |
---|
| 718 | + dp->initial_freq = kbdev->current_nominal_freq; |
---|
676 | 719 | dp->polling_ms = 100; |
---|
677 | 720 | dp->target = kbase_devfreq_target; |
---|
678 | 721 | dp->get_dev_status = kbase_devfreq_status; |
---|
.. | .. |
---|
687 | 730 | kbdev->gpu_props.props.core_props.gpu_freq_khz_max = |
---|
688 | 731 | dp->freq_table[0] / 1000; |
---|
689 | 732 | }; |
---|
690 | | - |
---|
691 | 733 | err = kbase_devfreq_init_core_mask_table(kbdev); |
---|
692 | | - if (err) { |
---|
693 | | - kbase_devfreq_term_freq_table(kbdev); |
---|
694 | | - return err; |
---|
695 | | - } |
---|
| 734 | + if (err) |
---|
| 735 | + goto init_core_mask_table_failed; |
---|
696 | 736 | |
---|
697 | 737 | of_property_read_u32(np, "upthreshold", |
---|
698 | 738 | &ondemand_data.upthreshold); |
---|
.. | .. |
---|
703 | 743 | if (IS_ERR(kbdev->devfreq)) { |
---|
704 | 744 | err = PTR_ERR(kbdev->devfreq); |
---|
705 | 745 | kbdev->devfreq = NULL; |
---|
706 | | - kbase_devfreq_term_core_mask_table(kbdev); |
---|
707 | | - kbase_devfreq_term_freq_table(kbdev); |
---|
708 | | - dev_err(kbdev->dev, "Fail to add devfreq device(%d)\n", err); |
---|
709 | | - return err; |
---|
| 746 | + dev_err(kbdev->dev, "Fail to add devfreq device(%d)", err); |
---|
| 747 | + goto devfreq_add_dev_failed; |
---|
710 | 748 | } |
---|
| 749 | + |
---|
| 750 | + /* Explicit free of freq table isn't needed after devfreq_add_device() */ |
---|
| 751 | + free_devfreq_freq_table = false; |
---|
711 | 752 | |
---|
712 | 753 | /* Initialize devfreq suspend/resume workqueue */ |
---|
713 | 754 | err = kbase_devfreq_work_init(kbdev); |
---|
714 | 755 | if (err) { |
---|
715 | | - if (devfreq_remove_device(kbdev->devfreq)) |
---|
716 | | - dev_err(kbdev->dev, "Fail to rm devfreq\n"); |
---|
717 | | - kbdev->devfreq = NULL; |
---|
718 | | - kbase_devfreq_term_core_mask_table(kbdev); |
---|
719 | | - dev_err(kbdev->dev, "Fail to init devfreq workqueue\n"); |
---|
720 | | - return err; |
---|
| 756 | + dev_err(kbdev->dev, "Fail to init devfreq workqueue"); |
---|
| 757 | + goto devfreq_work_init_failed; |
---|
721 | 758 | } |
---|
722 | 759 | |
---|
723 | 760 | /* devfreq_add_device only copies a few of kbdev->dev's fields, so |
---|
.. | .. |
---|
728 | 765 | err = devfreq_register_opp_notifier(kbdev->dev, kbdev->devfreq); |
---|
729 | 766 | if (err) { |
---|
730 | 767 | dev_err(kbdev->dev, |
---|
731 | | - "Failed to register OPP notifier (%d)\n", err); |
---|
| 768 | + "Failed to register OPP notifier (%d)", err); |
---|
732 | 769 | goto opp_notifier_failed; |
---|
733 | 770 | } |
---|
734 | 771 | |
---|
735 | | - opp_rate = kbdev->current_freqs[0]; /* Bifrost GPU has only 1 clock. */ |
---|
736 | | - opp = devfreq_recommended_opp(kbdev->dev, &opp_rate, 0); |
---|
737 | | - if (!IS_ERR(opp)) |
---|
738 | | - dev_pm_opp_put(opp); |
---|
739 | | - kbdev->devfreq->last_status.current_frequency = opp_rate; |
---|
740 | | - |
---|
741 | 772 | mali_mdevp.data = kbdev->devfreq; |
---|
| 773 | + mali_mdevp.opp_info = &kbdev->opp_info; |
---|
742 | 774 | kbdev->mdev_info = rockchip_system_monitor_register(kbdev->dev, |
---|
743 | 775 | &mali_mdevp); |
---|
744 | 776 | if (IS_ERR(kbdev->mdev_info)) { |
---|
745 | 777 | dev_dbg(kbdev->dev, "without system monitor\n"); |
---|
746 | 778 | kbdev->mdev_info = NULL; |
---|
| 779 | + mali_mdevp.is_checked = true; |
---|
747 | 780 | } |
---|
748 | 781 | #if IS_ENABLED(CONFIG_DEVFREQ_THERMAL) |
---|
749 | | - if (of_find_compatible_node(kbdev->dev->of_node, NULL, |
---|
750 | | - "simple-power-model")) { |
---|
751 | | - of_property_read_u32(kbdev->dev->of_node, |
---|
752 | | - "dynamic-power-coefficient", |
---|
753 | | - (u32 *)&kbase_dcp->dyn_power_coeff); |
---|
754 | | - kbdev->model_data = rockchip_ipa_power_model_init(kbdev->dev, |
---|
755 | | - "gpu_leakage"); |
---|
| 782 | + of_property_read_u32(kbdev->dev->of_node, "dynamic-power-coefficient", |
---|
| 783 | + (u32 *)&kbase_dcp->dyn_power_coeff); |
---|
| 784 | + model_node = of_get_compatible_child(kbdev->dev->of_node, |
---|
| 785 | + "simple-power-model"); |
---|
| 786 | + if (model_node) { |
---|
| 787 | + of_node_put(model_node); |
---|
| 788 | + kbdev->model_data = |
---|
| 789 | + rockchip_ipa_power_model_init(kbdev->dev, |
---|
| 790 | + "gpu_leakage"); |
---|
756 | 791 | if (IS_ERR_OR_NULL(kbdev->model_data)) { |
---|
757 | 792 | kbdev->model_data = NULL; |
---|
758 | | - dev_err(kbdev->dev, "failed to initialize power model\n"); |
---|
759 | | - } else if (kbdev->model_data->dynamic_coefficient) { |
---|
760 | | - kbase_dcp->dyn_power_coeff = |
---|
761 | | - kbdev->model_data->dynamic_coefficient; |
---|
| 793 | + if (kbase_dcp->dyn_power_coeff) |
---|
| 794 | + dev_info(kbdev->dev, |
---|
| 795 | + "only calculate dynamic power\n"); |
---|
| 796 | + else |
---|
| 797 | + dev_err(kbdev->dev, |
---|
| 798 | + "failed to initialize power model\n"); |
---|
| 799 | + } else { |
---|
| 800 | + kbase_dcp->get_static_power = |
---|
| 801 | + kbase_devfreq_get_static_power; |
---|
| 802 | + if (kbdev->model_data->dynamic_coefficient) |
---|
| 803 | + kbase_dcp->dyn_power_coeff = |
---|
| 804 | + kbdev->model_data->dynamic_coefficient; |
---|
762 | 805 | } |
---|
763 | | - if (!kbase_dcp->dyn_power_coeff) { |
---|
764 | | - err = -EINVAL; |
---|
765 | | - dev_err(kbdev->dev, "failed to get dynamic-coefficient\n"); |
---|
766 | | - goto ipa_init_failed; |
---|
767 | | - } |
---|
| 806 | + } |
---|
768 | 807 | |
---|
| 808 | + if (kbase_dcp->dyn_power_coeff) { |
---|
769 | 809 | kbdev->devfreq_cooling = |
---|
770 | 810 | of_devfreq_cooling_register_power(kbdev->dev->of_node, |
---|
771 | 811 | kbdev->devfreq, |
---|
.. | .. |
---|
773 | 813 | if (IS_ERR(kbdev->devfreq_cooling)) { |
---|
774 | 814 | err = PTR_ERR(kbdev->devfreq_cooling); |
---|
775 | 815 | dev_err(kbdev->dev, "failed to register cooling device\n"); |
---|
776 | | - goto cooling_reg_failed; |
---|
| 816 | + goto ipa_init_failed; |
---|
777 | 817 | } |
---|
778 | 818 | } else { |
---|
779 | 819 | err = kbase_ipa_init(kbdev); |
---|
.. | .. |
---|
793 | 833 | err); |
---|
794 | 834 | goto cooling_reg_failed; |
---|
795 | 835 | } |
---|
796 | | - |
---|
797 | 836 | } |
---|
798 | 837 | #endif |
---|
799 | 838 | |
---|
.. | .. |
---|
809 | 848 | opp_notifier_failed: |
---|
810 | 849 | kbase_devfreq_work_term(kbdev); |
---|
811 | 850 | |
---|
| 851 | +devfreq_work_init_failed: |
---|
812 | 852 | if (devfreq_remove_device(kbdev->devfreq)) |
---|
813 | | - dev_err(kbdev->dev, "Failed to terminate devfreq (%d)\n", err); |
---|
| 853 | + dev_err(kbdev->dev, "Failed to terminate devfreq (%d)", err); |
---|
814 | 854 | |
---|
815 | 855 | kbdev->devfreq = NULL; |
---|
816 | 856 | |
---|
| 857 | +devfreq_add_dev_failed: |
---|
817 | 858 | kbase_devfreq_term_core_mask_table(kbdev); |
---|
| 859 | + |
---|
| 860 | +init_core_mask_table_failed: |
---|
| 861 | + if (free_devfreq_freq_table) |
---|
| 862 | + kbase_devfreq_term_freq_table(kbdev); |
---|
818 | 863 | |
---|
819 | 864 | return err; |
---|
820 | 865 | } |
---|
.. | .. |
---|
828 | 873 | #if IS_ENABLED(CONFIG_DEVFREQ_THERMAL) |
---|
829 | 874 | if (kbdev->devfreq_cooling) |
---|
830 | 875 | devfreq_cooling_unregister(kbdev->devfreq_cooling); |
---|
831 | | - |
---|
832 | | - if (!kbdev->model_data) |
---|
833 | | - kbase_ipa_term(kbdev); |
---|
834 | | - kfree(kbdev->model_data); |
---|
835 | 876 | #endif |
---|
836 | 877 | |
---|
837 | 878 | devfreq_unregister_opp_notifier(kbdev->dev, kbdev->devfreq); |
---|
.. | .. |
---|
845 | 886 | kbdev->devfreq = NULL; |
---|
846 | 887 | |
---|
847 | 888 | kbase_devfreq_term_core_mask_table(kbdev); |
---|
| 889 | + |
---|
| 890 | +#if IS_ENABLED(CONFIG_DEVFREQ_THERMAL) |
---|
| 891 | + if (!kbdev->model_data) |
---|
| 892 | + kbase_ipa_term(kbdev); |
---|
| 893 | + kfree(kbdev->model_data); |
---|
| 894 | +#endif |
---|
848 | 895 | } |
---|