From b4629f9e30e865402c643de6d4668be790fc0539 Mon Sep 17 00:00:00 2001 From: Georgi Djakov Date: Tue, 8 Sep 2015 11:24:41 +0300 Subject: cpufreq-dt: Add L2 frequency scaling support Signed-off-by: Georgi Djakov Conflicts: drivers/cpufreq/cpufreq-dt.c --- drivers/cpufreq/cpufreq-dt.c | 54 ++++++++++++++++++++++++++++++++++++++------ include/linux/cpufreq.h | 2 ++ 2 files changed, 49 insertions(+), 7 deletions(-) --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -86,11 +86,13 @@ static int set_target(struct cpufreq_pol struct dev_pm_opp *opp; struct cpufreq_frequency_table *freq_table = policy->freq_table; struct clk *cpu_clk = policy->clk; + struct clk *l2_clk = policy->l2_clk; struct private_data *priv = policy->driver_data; struct device *cpu_dev = priv->cpu_dev; struct regulator *cpu_reg = priv->cpu_reg; unsigned long volt = 0, volt_old = 0, tol = 0; - unsigned int old_freq, new_freq; + unsigned int old_freq, new_freq, l2_freq; + unsigned long new_l2_freq = 0; long freq_Hz, freq_exact; unsigned long opp_freq = 0; int ret; @@ -146,6 +148,30 @@ static int set_target(struct cpufreq_pol goto out; } + if (!IS_ERR(l2_clk) && policy->l2_rate[0] && policy->l2_rate[1] && + policy->l2_rate[2]) { + static unsigned long krait_l2[CONFIG_NR_CPUS] = { }; + int cpu, ret = 0; + + if (freq_exact >= policy->l2_rate[2]) + new_l2_freq = policy->l2_rate[2]; + else if (freq_exact >= policy->l2_rate[1]) + new_l2_freq = policy->l2_rate[1]; + else + new_l2_freq = policy->l2_rate[0]; + + krait_l2[policy->cpu] = new_l2_freq; + for_each_present_cpu(cpu) + new_l2_freq = max(new_l2_freq, krait_l2[cpu]); + + l2_freq = clk_get_rate(l2_clk); + + if (l2_freq != new_l2_freq) { + /* scale l2 with the core */ + ret = clk_set_rate(l2_clk, new_l2_freq); + } + } + /* scaling down? scale voltage after frequency */ if (!IS_ERR(cpu_reg) && new_freq < old_freq) { ret = regulator_set_voltage_tol(cpu_reg, volt, tol); @@ -156,18 +182,21 @@ static int set_target(struct cpufreq_pol goto out; } } + priv->opp_freq = opp_freq; + out: mutex_unlock(&priv->lock); return ret; } static int allocate_resources(int cpu, struct device **cdev, - struct regulator **creg, struct clk **cclk) + struct regulator **creg, struct clk **cclk, + struct clk **l2) { struct device *cpu_dev; struct regulator *cpu_reg; - struct clk *cpu_clk; + struct clk *cpu_clk, *l2_clk = NULL; int ret = 0; char *reg_cpu0 = "cpu0", *reg_cpu = "cpu", *reg; @@ -227,6 +256,10 @@ try_again: *cdev = cpu_dev; *creg = cpu_reg; *cclk = cpu_clk; + + l2_clk = clk_get(cpu_dev, "l2"); + if (!IS_ERR(l2_clk)) + *l2 = l2_clk; } return ret; @@ -236,18 +269,20 @@ static int cpufreq_init(struct cpufreq_p { struct cpufreq_frequency_table *freq_table; struct device_node *np; + struct device_node *l2_np; struct private_data *priv; struct device *cpu_dev; struct regulator *cpu_reg; - struct clk *cpu_clk; struct dev_pm_opp *suspend_opp; + struct clk *cpu_clk, *l2_clk; unsigned long min_uV = ~0, max_uV = 0; unsigned int transition_latency; bool need_update = false; int ret; struct srcu_notifier_head *opp_srcu_head; - ret = allocate_resources(policy->cpu, &cpu_dev, &cpu_reg, &cpu_clk); + ret = allocate_resources(policy->cpu, &cpu_dev, &cpu_reg, &cpu_clk, + &l2_clk); if (ret) { pr_err("%s: Failed to allocate resources: %d\n", __func__, ret); return ret; @@ -398,6 +433,11 @@ static int cpufreq_init(struct cpufreq_p if (suspend_opp) policy->suspend_freq = dev_pm_opp_get_freq(suspend_opp) / 1000; rcu_read_unlock(); + policy->l2_clk = l2_clk; + + l2_np = of_find_node_by_name(NULL, "qcom,l2"); + if (l2_np) + of_property_read_u32_array(l2_np, "qcom,l2-rates", policy->l2_rate, 3); ret = cpufreq_table_validate_and_show(policy, freq_table); if (ret) { @@ -498,7 +538,7 @@ static int dt_cpufreq_probe(struct platf { struct device *cpu_dev; struct regulator *cpu_reg; - struct clk *cpu_clk; + struct clk *cpu_clk, *l2_clk; int ret; /* @@ -508,7 +548,7 @@ static int dt_cpufreq_probe(struct platf * * FIXME: Is checking this only for CPU0 sufficient ? */ - ret = allocate_resources(0, &cpu_dev, &cpu_reg, &cpu_clk); + ret = allocate_resources(0, &cpu_dev, &cpu_reg, &cpu_clk, &l2_clk); if (ret) return ret; --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -67,6 +67,8 @@ struct cpufreq_policy { unsigned int cpu; /* cpu managing this policy, must be online */ struct clk *clk; + struct clk *l2_clk; /* L2 clock */ + unsigned int l2_rate[3]; /* L2 bus clock rate thresholds */ struct cpufreq_cpuinfo cpuinfo;/* see above */ unsigned int min; /* in kHz */