From 6f24014f962dafc3ffa9f424d9d18a568dc843d8 Mon Sep 17 00:00:00 2001 From: Xiao Feng Date: Thu, 27 Aug 2015 12:03:55 +0800 Subject: [PATCH] cpufreq: rockchip: change the frequency of cci400 dynamically when the frequency of big cluster and little cluster are bigger then 600MHz, set the frequency of cci400 to 576MHz, otherwise set the frequency of cci400 to 288MHz. Change-Id: I9e28b51bfdfcaf62464b8511c731fa2cd0ed5d9d Signed-off-by: Xiao Feng --- drivers/cpufreq/rockchip_big_little.c | 64 +++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/drivers/cpufreq/rockchip_big_little.c b/drivers/cpufreq/rockchip_big_little.c index 15cdecd8cb44..8919e21e4ca6 100644 --- a/drivers/cpufreq/rockchip_big_little.c +++ b/drivers/cpufreq/rockchip_big_little.c @@ -68,6 +68,9 @@ static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS]; #define DISABLE_FURTHER_CPUFREQ 0x10 #define ENABLE_FURTHER_CPUFREQ 0x20 #define MASK_FURTHER_CPUFREQ 0x30 +#define CPU_LOW_FREQ 600000 /* KHz */ +#define CCI_LOW_RATE 288000000 /* Hz */ +#define CCI_HIGH_RATE 576000000 /* Hz */ /* With 0x00(NOCHANGE), it depends on the previous "further" status */ #define CPUFREQ_PRIVATE 0x100 static unsigned int no_cpufreq_access[MAX_CLUSTERS] = { 0 }; @@ -82,6 +85,9 @@ static struct dvfs_node *clk_cpu_dvfs_node[MAX_CLUSTERS]; static struct dvfs_node *clk_gpu_dvfs_node; static struct dvfs_node *clk_ddr_dvfs_node; static cpumask_var_t cluster_policy_mask[MAX_CLUSTERS]; +static struct clk *aclk_cci; +static unsigned long cci_rate; +static unsigned int cpu_bl_freq[MAX_CLUSTERS]; #ifdef CONFIG_ROCKCHIP_CPUQUIET static void rockchip_bl_balanced_cpufreq_transition(unsigned int cluster, @@ -163,6 +169,51 @@ static struct notifier_block notifier_policy_block = { .notifier_call = rockchip_bl_cpufreq_notifier_policy }; +static int rockchip_bl_cpufreq_notifier_trans(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct cpufreq_freqs *freq = data; + unsigned int cluster = cpu_to_cluster(freq->cpu); + int ret; + + cpu_bl_freq[cluster] = freq->new; + + switch (val) { + case CPUFREQ_PRECHANGE: + if (cpu_bl_freq[B_CLUSTER] > CPU_LOW_FREQ || + cpu_bl_freq[L_CLUSTER] > CPU_LOW_FREQ) { + if (cci_rate != CCI_HIGH_RATE) { + ret = clk_set_rate(aclk_cci, CCI_HIGH_RATE); + if (ret) + break; + pr_debug("ccirate %ld-->%d Hz\n", + cci_rate, CCI_HIGH_RATE); + cci_rate = CCI_HIGH_RATE; + } + } + break; + case CPUFREQ_POSTCHANGE: + if (cpu_bl_freq[B_CLUSTER] <= CPU_LOW_FREQ && + cpu_bl_freq[L_CLUSTER] <= CPU_LOW_FREQ) { + if (cci_rate != CCI_LOW_RATE) { + ret = clk_set_rate(aclk_cci, CCI_LOW_RATE); + if (ret) + break; + pr_debug("ccirate %ld-->%d Hz\n", + cci_rate, CCI_LOW_RATE); + cci_rate = CCI_LOW_RATE; + } + } + break; + } + + return 0; +} + +static struct notifier_block notifier_trans_block = { + .notifier_call = rockchip_bl_cpufreq_notifier_trans, +}; + static int rockchip_bl_cpufreq_verify(struct cpufreq_policy *policy) { u32 cur_cluster = cpu_to_cluster(policy->cpu); @@ -275,6 +326,19 @@ static int rockchip_bl_cpufreq_init_cpu0(struct cpufreq_policy *policy) cpufreq_register_notifier(¬ifier_policy_block, CPUFREQ_POLICY_NOTIFIER); + aclk_cci = clk_get(NULL, "aclk_cci"); + if (!IS_ERR(aclk_cci)) { + cci_rate = clk_get_rate(aclk_cci); + if (clk_cpu_dvfs_node[L_CLUSTER]) + cpu_bl_freq[L_CLUSTER] = + clk_get_rate(clk_cpu_dvfs_node[L_CLUSTER]->clk) / 1000; + if (clk_cpu_dvfs_node[B_CLUSTER]) + cpu_bl_freq[B_CLUSTER] = + clk_get_rate(clk_cpu_dvfs_node[B_CLUSTER]->clk) / 1000; + cpufreq_register_notifier(¬ifier_trans_block, + CPUFREQ_TRANSITION_NOTIFIER); + } + pr_info("version " VERSION ", suspend freq %d %d MHz\n", suspend_freq[0] / 1000, suspend_freq[1] / 1000); return 0; -- 2.34.1