diff options
Diffstat (limited to 'target/linux/ipq806x/patches-4.4/173-cpufreq-dt-Add-L2-frequency-scaling-support.patch')
-rw-r--r-- | target/linux/ipq806x/patches-4.4/173-cpufreq-dt-Add-L2-frequency-scaling-support.patch | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/target/linux/ipq806x/patches-4.4/173-cpufreq-dt-Add-L2-frequency-scaling-support.patch b/target/linux/ipq806x/patches-4.4/173-cpufreq-dt-Add-L2-frequency-scaling-support.patch new file mode 100644 index 0000000000..56930520c9 --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/173-cpufreq-dt-Add-L2-frequency-scaling-support.patch @@ -0,0 +1,161 @@ +From b4629f9e30e865402c643de6d4668be790fc0539 Mon Sep 17 00:00:00 2001 +From: Georgi Djakov <georgi.djakov@linaro.org> +Date: Tue, 8 Sep 2015 11:24:41 +0300 +Subject: cpufreq-dt: Add L2 frequency scaling support + +Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> + +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 */ |