| .. | .. |
|---|
| 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 | } |
|---|