From c00e3a0e83bfdca5ab1efa55ff863ffcf1b6e7a4 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 17 Feb 2022 12:27:50 +0800 Subject: [PATCH] cpufreq: rockchip: Set intermediate rate before change read margin Improve stability when change read margin. Signed-off-by: Finley Xiao Change-Id: I25a4b00c37b05e8de404ffbd9904a5b65288b077 --- drivers/cpufreq/rockchip-cpufreq.c | 79 ++++++++++++++---------------- 1 file changed, 37 insertions(+), 42 deletions(-) diff --git a/drivers/cpufreq/rockchip-cpufreq.c b/drivers/cpufreq/rockchip-cpufreq.c index 11d9735b8f40..dcd4132c2956 100644 --- a/drivers/cpufreq/rockchip-cpufreq.c +++ b/drivers/cpufreq/rockchip-cpufreq.c @@ -36,11 +36,6 @@ #include "cpufreq-dt.h" #include "rockchip-cpufreq.h" -#define CPUFREQ_INTERNAL_VERSION 0x80 -#define CPUFREQ_LENGTH_MARGIN 0x1 -#define CPUFREQ_INTERMEDIATE_RATE (CPUFREQ_INTERNAL_VERSION | \ - CPUFREQ_LENGTH_MARGIN) - struct cluster_info { struct list_head list_head; struct monitor_dev_info *mdev_info; @@ -328,26 +323,6 @@ static int rockchip_cpufreq_set_volt(struct device *dev, return ret; } -static int rockchip_cpufreq_set_read_margin(struct device *dev, - struct rockchip_opp_info *opp_info, - u32 rm) -{ - if (opp_info->data && opp_info->data->set_read_margin) - opp_info->data->set_read_margin(dev, opp_info, rm); - - return 0; -} - -static int -rockchip_cpufreq_set_intermediate_rate(struct rockchip_opp_info *opp_info, - struct clk *clk, unsigned long new_freq) -{ - if (opp_info->data && opp_info->data->set_read_margin) - return clk_set_rate(clk, new_freq | CPUFREQ_INTERMEDIATE_RATE); - - return 0; -} - 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]; @@ -372,10 +347,14 @@ static int cpu_opp_helper(struct dev_pm_set_opp_data *data) rockchip_get_read_margin(dev, opp_info, new_supply_vdd->u_volt, &target_rm); + /* Change frequency */ + dev_dbg(dev, "%s: switching OPP: %lu Hz --> %lu Hz\n", __func__, + old_freq, new_freq); /* Scaling up? Scale voltage before frequency */ if (new_freq >= old_freq) { - ret = rockchip_cpufreq_set_intermediate_rate(opp_info, clk, - new_freq); + ret = rockchip_set_intermediate_rate(dev, opp_info, clk, + old_freq, new_freq, + true, true); if (ret) { dev_err(dev, "%s: failed to set clk rate: %lu\n", __func__, new_freq); @@ -389,21 +368,32 @@ static int cpu_opp_helper(struct dev_pm_set_opp_data *data) "vdd"); if (ret) goto restore_voltage; - rockchip_cpufreq_set_read_margin(dev, opp_info, target_rm); - } - - /* Change frequency */ - dev_dbg(dev, "%s: switching OPP: %lu Hz --> %lu Hz\n", __func__, - old_freq, new_freq); - ret = clk_set_rate(clk, new_freq); - if (ret) { - dev_err(dev, "%s: failed to set clk rate: %d\n", __func__, ret); - goto restore_rm; - } - + rockchip_set_read_margin(dev, opp_info, target_rm, true); + ret = clk_set_rate(clk, new_freq); + if (ret) { + dev_err(dev, + "%s: failed to set clk rate: %d\n", __func__, + ret); + goto restore_rm; + } /* Scaling down? Scale voltage after frequency */ - if (new_freq < old_freq) { - rockchip_cpufreq_set_read_margin(dev, opp_info, target_rm); + } else { + ret = rockchip_set_intermediate_rate(dev, opp_info, clk, + old_freq, new_freq, + false, true); + if (ret) { + dev_err(dev, "%s: failed to set clk rate: %lu\n", + __func__, new_freq); + return -EINVAL; + } + rockchip_set_read_margin(dev, opp_info, target_rm, true); + ret = clk_set_rate(clk, new_freq); + if (ret) { + dev_err(dev, + "%s: failed to set clk rate: %d\n", __func__, + ret); + goto restore_rm; + } ret = rockchip_cpufreq_set_volt(dev, vdd_reg, new_supply_vdd, "vdd"); if (ret) @@ -423,7 +413,7 @@ restore_freq: restore_rm: rockchip_get_read_margin(dev, opp_info, old_supply_vdd->u_volt, &target_rm); - rockchip_cpufreq_set_read_margin(dev, opp_info, target_rm); + rockchip_set_read_margin(dev, opp_info, target_rm, true); restore_voltage: rockchip_cpufreq_set_volt(dev, mem_reg, old_supply_mem, "mem"); rockchip_cpufreq_set_volt(dev, vdd_reg, old_supply_vdd, "vdd"); @@ -445,6 +435,7 @@ static int rockchip_cpufreq_cluster_init(int cpu, struct cluster_info *cluster) int process = -EINVAL; int volt_sel = -EINVAL; int ret = 0; + u32 freq = 0; dev = get_cpu_device(cpu); if (!dev) @@ -483,6 +474,10 @@ static int rockchip_cpufreq_cluster_init(int cpu, struct cluster_info *cluster) opp_info->dsu_grf = NULL; rockchip_get_volt_rm_table(dev, np, "volt-mem-read-margin", &opp_info->volt_rm_tbl); + of_property_read_u32(np, "low-volt-mem-read-margin", + &opp_info->low_rm); + if (!of_property_read_u32(np, "intermediate-threshold-freq", &freq)) + opp_info->intermediate_threshold_freq = freq * 1000; } if (opp_info->data && opp_info->data->get_soc_info) opp_info->data->get_soc_info(dev, np, &bin, &process);