From 85556b1e7f5f12a5edadac4c2d5cc28d7d9e997b Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Mon, 8 Nov 2021 20:12:09 +0800 Subject: [PATCH] cpufreq: rockchip: Implement rockchip_cpufreq_opp_set_rate() When enter low temperature mode, system monitor update opp table, then check and change the current voltage for cpu, but now the opp voltage inside cpu_opp_helper() may be old, the current voltage may be changed back to old value. Move the volt_adjust_mutex out of dev_pm_opp_set_rate() so that the opp voltage inside cpu_opp_helper() will be latest. Signed-off-by: Finley Xiao Change-Id: I9a91775dc9b5443e4b47b4255de6e21133c32404 --- drivers/cpufreq/cpufreq-dt.c | 4 ++ drivers/cpufreq/rockchip-cpufreq.c | 89 +++++++++++++----------------- drivers/cpufreq/rockchip-cpufreq.h | 9 ++- 3 files changed, 51 insertions(+), 51 deletions(-) diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index 5c8463fa079f..f1327e7fe361 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -62,7 +62,11 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index) struct private_data *priv = policy->driver_data; unsigned long freq = policy->freq_table[index].frequency; +#ifdef CONFIG_ARCH_ROCKCHIP + return rockchip_cpufreq_opp_set_rate(priv->cpu_dev, freq * 1000); +#else return dev_pm_opp_set_rate(priv->cpu_dev, freq * 1000); +#endif } /* diff --git a/drivers/cpufreq/rockchip-cpufreq.c b/drivers/cpufreq/rockchip-cpufreq.c index ea7d3bb2f385..d31f8d46eaea 100644 --- a/drivers/cpufreq/rockchip-cpufreq.c +++ b/drivers/cpufreq/rockchip-cpufreq.c @@ -34,14 +34,10 @@ #include "rockchip-cpufreq.h" struct cluster_info { - struct opp_table *opp_table; struct list_head list_head; struct monitor_dev_info *mdev_info; cpumask_t cpus; int scale; - bool offline; - bool freq_limit; - bool is_check_init; }; static LIST_HEAD(cluster_info_list); @@ -252,55 +248,39 @@ static int rockchip_cpufreq_set_volt(struct device *dev, { int ret; - dev_dbg(dev, "%s: %s voltages (mV): %lu %lu %lu\n", __func__, reg_name, + dev_dbg(dev, "%s: %s voltages (uV): %lu %lu %lu\n", __func__, reg_name, supply->u_volt_min, supply->u_volt, supply->u_volt_max); ret = regulator_set_voltage_triplet(reg, supply->u_volt_min, supply->u_volt, supply->u_volt_max); if (ret) - dev_err(dev, "%s: failed to set voltage (%lu %lu %lu mV): %d\n", + dev_err(dev, "%s: failed to set voltage (%lu %lu %lu uV): %d\n", __func__, supply->u_volt_min, supply->u_volt, supply->u_volt_max, ret); return ret; } -static int opp_helper(struct dev_pm_set_opp_data *data) +static int cpu_opp_helper(struct dev_pm_set_opp_data *data) { struct dev_pm_opp_supply *old_supply_vdd = &data->old_opp.supplies[0]; + struct dev_pm_opp_supply *old_supply_mem = &data->old_opp.supplies[1]; struct dev_pm_opp_supply *new_supply_vdd = &data->new_opp.supplies[0]; + struct dev_pm_opp_supply *new_supply_mem = &data->new_opp.supplies[1]; struct regulator *vdd_reg = data->regulators[0]; + struct regulator *mem_reg = data->regulators[1]; struct device *dev = data->dev; struct clk *clk = data->clk; - struct cluster_info *cluster; - struct dev_pm_opp_supply *old_supply_mem; - struct dev_pm_opp_supply *new_supply_mem; - struct regulator *mem_reg; unsigned long old_freq = data->old_opp.rate; unsigned long new_freq = data->new_opp.rate; - unsigned int regulator_count = data->regulator_count; int ret = 0; - if (regulator_count > 1) { - old_supply_mem = &data->old_opp.supplies[1]; - new_supply_mem = &data->new_opp.supplies[1]; - mem_reg = data->regulators[1]; - } - - cluster = rockchip_cluster_info_lookup(dev->id); - if (!cluster) - return -ENOMEM; - - rockchip_monitor_volt_adjust_lock(cluster->mdev_info); - /* Scaling up? Scale voltage before frequency */ if (new_freq >= old_freq) { - if (regulator_count > 1) { - ret = rockchip_cpufreq_set_volt(dev, mem_reg, - new_supply_mem, "mem"); - if (ret) - goto restore_voltage; - } + ret = rockchip_cpufreq_set_volt(dev, mem_reg, new_supply_mem, + "mem"); + if (ret) + goto restore_voltage; ret = rockchip_cpufreq_set_volt(dev, vdd_reg, new_supply_vdd, "vdd"); if (ret) @@ -322,16 +302,12 @@ static int opp_helper(struct dev_pm_set_opp_data *data) "vdd"); if (ret) goto restore_freq; - if (regulator_count > 1) { - ret = rockchip_cpufreq_set_volt(dev, mem_reg, - new_supply_mem, "mem"); - if (ret) - goto restore_freq; - } + ret = rockchip_cpufreq_set_volt(dev, mem_reg, new_supply_mem, + "mem"); + if (ret) + goto restore_freq; } - rockchip_monitor_volt_adjust_unlock(cluster->mdev_info); - return 0; restore_freq: @@ -339,12 +315,8 @@ restore_freq: dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n", __func__, old_freq); restore_voltage: - if (regulator_count > 1 && old_supply_mem->u_volt) - rockchip_cpufreq_set_volt(dev, mem_reg, old_supply_mem, "mem"); - if (old_supply_vdd->u_volt) - rockchip_cpufreq_set_volt(dev, vdd_reg, old_supply_vdd, "vdd"); - - rockchip_monitor_volt_adjust_unlock(cluster->mdev_info); + rockchip_cpufreq_set_volt(dev, mem_reg, old_supply_mem, "mem"); + rockchip_cpufreq_set_volt(dev, vdd_reg, old_supply_vdd, "vdd"); return ret; } @@ -403,12 +375,12 @@ static int rockchip_cpufreq_cluster_init(int cpu, struct cluster_info *cluster) ret = PTR_ERR(reg_table); goto pname_opp_table; } - } - - opp_table = dev_pm_opp_register_set_opp_helper(dev, opp_helper); - if (IS_ERR(opp_table)) { - ret = PTR_ERR(opp_table); - goto reg_opp_table; + opp_table = dev_pm_opp_register_set_opp_helper(dev, + cpu_opp_helper); + if (IS_ERR(opp_table)) { + ret = PTR_ERR(opp_table); + goto reg_opp_table; + } } of_node_put(np); @@ -440,6 +412,23 @@ int rockchip_cpufreq_adjust_power_scale(struct device *dev) } EXPORT_SYMBOL_GPL(rockchip_cpufreq_adjust_power_scale); +int rockchip_cpufreq_opp_set_rate(struct device *dev, unsigned long target_freq) +{ + struct cluster_info *cluster; + int ret = 0; + + cluster = rockchip_cluster_info_lookup(dev->id); + if (!cluster) + return -EINVAL; + + rockchip_monitor_volt_adjust_lock(cluster->mdev_info); + ret = dev_pm_opp_set_rate(dev, target_freq); + rockchip_monitor_volt_adjust_unlock(cluster->mdev_info); + + return ret; +} +EXPORT_SYMBOL_GPL(rockchip_cpufreq_opp_set_rate); + static int rockchip_cpufreq_suspend(struct cpufreq_policy *policy) { int ret = 0; diff --git a/drivers/cpufreq/rockchip-cpufreq.h b/drivers/cpufreq/rockchip-cpufreq.h index 43015c079a1f..b8ecce6c676d 100644 --- a/drivers/cpufreq/rockchip-cpufreq.h +++ b/drivers/cpufreq/rockchip-cpufreq.h @@ -7,10 +7,17 @@ #if IS_ENABLED(CONFIG_ARM_ROCKCHIP_CPUFREQ) int rockchip_cpufreq_adjust_power_scale(struct device *dev); +int rockchip_cpufreq_opp_set_rate(struct device *dev, unsigned long target_freq); #else static inline int rockchip_cpufreq_adjust_power_scale(struct device *dev) { - return -ENOTSUPP; + return -EOPNOTSUPP; +} + +static inline int rockchip_cpufreq_opp_set_rate(struct device *dev, + unsigned long target_freq); +{ + return -EOPNOTSUPP; } #endif /* CONFIG_ARM_ROCKCHIP_CPUFREQ */