This patch series adds cpufreq support for the Exynos 5800, 5420, and 5422
SOCs. In particular, it adds support for operating-points-v2 bindings to the
arm-big-little cpufreq driver and updates the above-mentioned SOCs' devicetrees
to take advantage of this support. There are also a couple of patches improving
the clarify of the arm-big-little implementation. It is built on a set posted
by Bartlomiej Zolnierkiewicz in April 2015.
The most signficant change from the original series is porting to the
operating-points-v2 devicetree bindings. The series has been tested by me on
and Odroid XU4 and by Javier Martinez Canillas on a Peach Pit.
Cheers,
- Ben
From: Bartlomiej Zolnierkiewicz <[email protected]>
Add cluster regulator support as a preparation to adding
generic arm_big_little_dt cpufreq_dt driver support for
ODROID-XU3 board. This allows arm_big_little[_dt] driver
to set not only the frequency but also the voltage (which
is obtained from operating point's voltage value) for CPU
clusters.
Cc: Kukjin Kim <[email protected]>
Cc: Doug Anderson <[email protected]>
Cc: Javier Martinez Canillas <[email protected]>
Cc: Andreas Faerber <[email protected]>
Cc: Sachin Kamat <[email protected]>
Cc: Thomas Abraham <[email protected]>
Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]>
Signed-off-by: Ben Gamari <[email protected]>
---
.../bindings/cpufreq/arm_big_little_dt.txt | 4 +
drivers/cpufreq/arm_big_little.c | 155 ++++++++++++++++++---
2 files changed, 142 insertions(+), 17 deletions(-)
diff --git a/Documentation/devicetree/bindings/cpufreq/arm_big_little_dt.txt b/Documentation/devicetree/bindings/cpufreq/arm_big_little_dt.txt
index 0715695..8ca4a12 100644
--- a/Documentation/devicetree/bindings/cpufreq/arm_big_little_dt.txt
+++ b/Documentation/devicetree/bindings/cpufreq/arm_big_little_dt.txt
@@ -18,6 +18,10 @@ Required properties:
Optional properties:
- clock-latency: Specify the possible maximum transition latency for clock,
in unit of nanoseconds.
+- cpu-cluster.0-supply: Provides the regulator node supplying voltage to CPU
+ cluster 0.
+- cpu-cluster.1-supply: Provides the regulator node supplying voltage to CPU
+ cluster 1.
Examples:
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index c5d256c..855599b 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -31,6 +31,7 @@
#include <linux/slab.h>
#include <linux/topology.h>
#include <linux/types.h>
+#include <linux/regulator/consumer.h>
#include "arm_big_little.h"
@@ -57,6 +58,9 @@ static bool bL_switching_enabled;
static struct cpufreq_arm_bL_ops *arm_bL_ops;
static struct clk *clk[MAX_CLUSTERS];
+static struct regulator *reg[MAX_CLUSTERS];
+static struct device *cpu_devs[MAX_CLUSTERS];
+static int transition_latencies[MAX_CLUSTERS];
static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS + 1];
static atomic_t cluster_usage[MAX_CLUSTERS + 1];
@@ -125,6 +129,75 @@ static unsigned int bL_cpufreq_get_rate(unsigned int cpu)
}
}
+static int
+bL_cpufreq_set_rate_cluster(u32 cpu, u32 cluster, u32 new_rate)
+{
+ unsigned long volt = 0, volt_old = 0;
+ long freq_Hz;
+ u32 old_rate;
+ int ret;
+
+ freq_Hz = new_rate * 1000;
+ old_rate = clk_get_rate(clk[cluster]) / 1000;
+
+ if (!IS_ERR(reg[cluster])) {
+ struct dev_pm_opp *opp;
+ unsigned long opp_freq;
+
+ rcu_read_lock();
+ opp = dev_pm_opp_find_freq_ceil(cpu_devs[cluster], &freq_Hz);
+ if (IS_ERR(opp)) {
+ rcu_read_unlock();
+ pr_err("%s: cpu %d, cluster: %d, failed to find OPP for %ld\n",
+ __func__, cpu, cluster, freq_Hz);
+ return PTR_ERR(opp);
+ }
+ volt = dev_pm_opp_get_voltage(opp);
+ opp_freq = dev_pm_opp_get_freq(opp);
+ rcu_read_unlock();
+ volt_old = regulator_get_voltage(reg[cluster]);
+ pr_debug("%s: cpu %d, cluster: %d, Found OPP: %ld kHz, %ld uV\n",
+ __func__, cpu, cluster, opp_freq / 1000, volt);
+ }
+
+ pr_debug("%s: cpu %d, cluster: %d, %u MHz, %ld mV --> %u MHz, %ld mV\n",
+ __func__, cpu, cluster,
+ old_rate / 1000, (volt_old > 0) ? volt_old / 1000 : -1,
+ new_rate / 1000, volt ? volt / 1000 : -1);
+
+ /* scaling up? scale voltage before frequency */
+ if (!IS_ERR(reg[cluster]) && new_rate > old_rate) {
+ ret = regulator_set_voltage_tol(reg[cluster], volt, 0);
+ if (ret) {
+ pr_err("%s: cpu: %d, cluster: %d, failed to scale voltage up: %d\n",
+ __func__, cpu, cluster, ret);
+ return ret;
+ }
+ }
+
+ ret = clk_set_rate(clk[cluster], new_rate * 1000);
+ if (WARN_ON(ret)) {
+ pr_err("%s: clk_set_rate failed: %d, cluster: %d\n",
+ __func__, cluster, ret);
+ if (!IS_ERR(reg[cluster]) && volt_old > 0)
+ regulator_set_voltage_tol(reg[cluster], volt_old, 0);
+ return ret;
+ }
+
+ /* scaling down? scale voltage after frequency */
+ if (!IS_ERR(reg[cluster]) && new_rate < old_rate) {
+ ret = regulator_set_voltage_tol(reg[cluster], volt, 0);
+ if (ret) {
+ pr_err("%s: cpu: %d, cluster: %d, failed to scale voltage down: %d\n",
+ __func__, cpu, cluster, ret);
+ clk_set_rate(clk[cluster], old_rate * 1000);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
static unsigned int
bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
{
@@ -148,7 +221,7 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
pr_debug("%s: cpu: %d, old cluster: %d, new cluster: %d, freq: %d\n",
__func__, cpu, old_cluster, new_cluster, new_rate);
- ret = clk_set_rate(clk[new_cluster], new_rate * 1000);
+ ret = bL_cpufreq_set_rate_cluster(cpu, new_cluster, new_rate);
if (!ret) {
/*
* FIXME: clk_set_rate hasn't returned an error here however it
@@ -160,22 +233,15 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
*/
if (clk_get_rate(clk[new_cluster]) != new_rate * 1000)
ret = -EIO;
- }
-
- if (WARN_ON(ret)) {
- pr_err("clk_set_rate failed: %d, new cluster: %d\n", ret,
- new_cluster);
- if (bLs) {
- per_cpu(cpu_last_req_freq, cpu) = prev_rate;
- per_cpu(physical_cluster, cpu) = old_cluster;
- }
+ } else if (ret && bLs) {
+ per_cpu(cpu_last_req_freq, cpu) = prev_rate;
+ per_cpu(physical_cluster, cpu) = old_cluster;
+ }
- mutex_unlock(&cluster_lock[new_cluster]);
+ mutex_unlock(&cluster_lock[new_cluster]);
+ if(ret)
return ret;
- }
-
- mutex_unlock(&cluster_lock[new_cluster]);
/* Recalc freq for old cluster when switching clusters */
if (old_cluster != new_cluster) {
@@ -195,9 +261,10 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
pr_debug("%s: Updating rate of old cluster: %d, to freq: %d\n",
__func__, old_cluster, new_rate);
- if (clk_set_rate(clk[old_cluster], new_rate * 1000))
- pr_err("%s: clk_set_rate failed: %d, old cluster: %d\n",
- __func__, ret, old_cluster);
+ if (bL_cpufreq_set_rate_cluster(cpu, old_cluster, new_rate)) {
+ pr_err("%s: bL_cpufreq_set_rate_cluster failed\n",
+ __func__);
+ }
}
mutex_unlock(&cluster_lock[old_cluster]);
}
@@ -304,6 +371,8 @@ static void _put_cluster_clk_and_freq_table(struct device *cpu_dev)
return;
clk_put(clk[cluster]);
+ if (!IS_ERR(reg[cluster]))
+ regulator_put(reg[cluster]);
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]);
if (arm_bL_ops->free_opp_table)
arm_bL_ops->free_opp_table(cpu_dev);
@@ -337,7 +406,9 @@ static void put_cluster_clk_and_freq_table(struct device *cpu_dev)
static int _get_cluster_clk_and_freq_table(struct device *cpu_dev)
{
+ unsigned long min_uV = ~0, max_uV = 0;
u32 cluster = raw_cpu_to_cluster(cpu_dev->id);
+ char name[14] = "cpu-cluster.";
int ret;
if (freq_table[cluster])
@@ -350,6 +421,51 @@ static int _get_cluster_clk_and_freq_table(struct device *cpu_dev)
goto out;
}
+ name[12] = cluster + '0';
+ reg[cluster] = regulator_get_optional(cpu_dev, name);
+ if (!IS_ERR(reg[cluster])) {
+ unsigned long opp_freq = 0;
+
+ dev_dbg(cpu_dev, "%s: reg: %p, cluster: %d\n",
+ __func__, reg[cluster], cluster);
+ cpu_devs[cluster] = cpu_dev;
+
+ /*
+ * Disable any OPPs where the connected regulator isn't able to
+ * provide the specified voltage and record minimum and maximum
+ * voltage levels.
+ */
+ while (1) {
+ struct dev_pm_opp *opp;
+ unsigned long opp_uV;
+
+ rcu_read_lock();
+ opp = dev_pm_opp_find_freq_ceil(cpu_dev, &opp_freq);
+ if (IS_ERR(opp)) {
+ rcu_read_unlock();
+ break;
+ }
+ opp_uV = dev_pm_opp_get_voltage(opp);
+ rcu_read_unlock();
+
+ if (regulator_is_supported_voltage(reg[cluster], opp_uV,
+ opp_uV)) {
+ if (opp_uV < min_uV)
+ min_uV = opp_uV;
+ if (opp_uV > max_uV)
+ max_uV = opp_uV;
+ } else {
+ dev_pm_opp_disable(cpu_dev, opp_freq);
+ }
+
+ opp_freq++;
+ }
+
+ ret = regulator_set_voltage_time(reg[cluster], min_uV, max_uV);
+ if (ret > 0)
+ transition_latencies[cluster] = ret * 1000;
+ }
+
ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table[cluster]);
if (ret) {
dev_err(cpu_dev, "%s: failed to init cpufreq table, cpu: %d, err: %d\n",
@@ -483,6 +599,11 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
else
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+ if (cur_cluster < MAX_CLUSTERS &&
+ policy->cpuinfo.transition_latency != CPUFREQ_ETERNAL)
+ policy->cpuinfo.transition_latency
+ += transition_latencies[cur_cluster];
+
if (is_bL_switching_enabled())
per_cpu(cpu_last_req_freq, policy->cpu) = clk_get_cpu_rate(policy->cpu);
--
2.6.2
From: Thomas Abraham <[email protected]>
With the addition of the new Samsung specific cpu-clock type, the
arm clock can be represented as a cpu-clock type. Add the CPU clock
configuration data and instantiate the CPU clock type for Exynos5420.
Changes by Bartlomiej:
- split Exynos5420 support from the original patches
- moved E5420_[EGL,KFC]_DIV0() macros to clk-exynos5420.c
Changes by Ben Gamari:
- Rebased
Cc: Tomasz Figa <[email protected]>
Cc: Mike Turquette <[email protected]>
Cc: Javier Martinez Canillas <[email protected]>
Signed-off-by: Thomas Abraham <[email protected]>
Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]>
Signed-off-by: Ben Gamari <[email protected]>
---
drivers/clk/samsung/clk-exynos5420.c | 58 ++++++++++++++++++++++++++++++++--
include/dt-bindings/clock/exynos5420.h | 2 ++
2 files changed, 58 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index 389af3c..2288052 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -18,6 +18,7 @@
#include <linux/syscore_ops.h>
#include "clk.h"
+#include "clk-cpu.h"
#define APLL_LOCK 0x0
#define APLL_CON0 0x100
@@ -616,9 +617,11 @@ static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = {
MUX(0, "mout_mspll_kfc", mout_mspll_cpu_p, SRC_TOP7, 8, 2),
MUX(0, "mout_mspll_cpu", mout_mspll_cpu_p, SRC_TOP7, 12, 2),
- MUX(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1),
+ MUX_F(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
+ CLK_SET_RATE_PARENT, 0),
MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
- MUX(0, "mout_kpll", mout_kpll_p, SRC_KFC, 0, 1),
+ MUX_F(0, "mout_kpll", mout_kpll_p, SRC_KFC, 0, 1,
+ CLK_SET_RATE_PARENT, 0),
MUX(0, "mout_kfc", mout_kfc_p, SRC_KFC, 16, 1),
MUX(0, "mout_aclk200", mout_group1_p, SRC_TOP0, 8, 2),
@@ -1246,6 +1249,50 @@ static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = {
KPLL_CON0, NULL),
};
+#define E5420_EGL_DIV0(apll, pclk_dbg, atb, cpud) \
+ ((((apll) << 24) | ((pclk_dbg) << 20) | ((atb) << 16) | \
+ ((cpud) << 4)))
+
+static const struct exynos_cpuclk_cfg_data exynos5420_eglclk_d[] __initconst = {
+ { 1800000, E5420_EGL_DIV0(3, 7, 7, 4), },
+ { 1700000, E5420_EGL_DIV0(3, 7, 7, 3), },
+ { 1600000, E5420_EGL_DIV0(3, 7, 7, 3), },
+ { 1500000, E5420_EGL_DIV0(3, 7, 7, 3), },
+ { 1400000, E5420_EGL_DIV0(3, 7, 7, 3), },
+ { 1300000, E5420_EGL_DIV0(3, 7, 7, 2), },
+ { 1200000, E5420_EGL_DIV0(3, 7, 7, 2), },
+ { 1100000, E5420_EGL_DIV0(3, 7, 7, 2), },
+ { 1000000, E5420_EGL_DIV0(3, 6, 6, 2), },
+ { 900000, E5420_EGL_DIV0(3, 6, 6, 2), },
+ { 800000, E5420_EGL_DIV0(3, 5, 5, 2), },
+ { 700000, E5420_EGL_DIV0(3, 5, 5, 2), },
+ { 600000, E5420_EGL_DIV0(3, 4, 4, 2), },
+ { 500000, E5420_EGL_DIV0(3, 3, 3, 2), },
+ { 400000, E5420_EGL_DIV0(3, 3, 3, 2), },
+ { 300000, E5420_EGL_DIV0(3, 3, 3, 2), },
+ { 200000, E5420_EGL_DIV0(3, 3, 3, 2), },
+ { 0 },
+};
+
+#define E5420_KFC_DIV(kpll, pclk, aclk) \
+ ((((kpll) << 24) | ((pclk) << 20) | ((aclk) << 4)))
+
+static const struct exynos_cpuclk_cfg_data exynos5420_kfcclk_d[] __initconst = {
+ { 1300000, E5420_KFC_DIV(3, 5, 2), },
+ { 1200000, E5420_KFC_DIV(3, 5, 2), },
+ { 1100000, E5420_KFC_DIV(3, 5, 2), },
+ { 1000000, E5420_KFC_DIV(3, 5, 2), },
+ { 900000, E5420_KFC_DIV(3, 5, 2), },
+ { 800000, E5420_KFC_DIV(3, 5, 2), },
+ { 700000, E5420_KFC_DIV(3, 4, 2), },
+ { 600000, E5420_KFC_DIV(3, 4, 2), },
+ { 500000, E5420_KFC_DIV(3, 4, 2), },
+ { 400000, E5420_KFC_DIV(3, 3, 2), },
+ { 300000, E5420_KFC_DIV(3, 3, 2), },
+ { 200000, E5420_KFC_DIV(3, 3, 2), },
+ { 0 },
+};
+
static const struct of_device_id ext_clk_match[] __initconst = {
{ .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, },
{ },
@@ -1310,6 +1357,13 @@ static void __init exynos5x_clk_init(struct device_node *np,
ARRAY_SIZE(exynos5800_gate_clks));
}
+ exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
+ mout_cpu_p[0], mout_cpu_p[1], 0x200,
+ exynos5420_eglclk_d, ARRAY_SIZE(exynos5420_eglclk_d), 0);
+ exynos_register_cpu_clock(ctx, CLK_KFC_CLK, "kfcclk",
+ mout_kfc_p[0], mout_kfc_p[1], 0x28200,
+ exynos5420_kfcclk_d, ARRAY_SIZE(exynos5420_kfcclk_d), 0);
+
exynos5420_clk_sleep_init();
samsung_clk_of_add_provider(np, ctx);
diff --git a/include/dt-bindings/clock/exynos5420.h b/include/dt-bindings/clock/exynos5420.h
index 99da0d1..dde9664 100644
--- a/include/dt-bindings/clock/exynos5420.h
+++ b/include/dt-bindings/clock/exynos5420.h
@@ -25,6 +25,8 @@
#define CLK_FOUT_MPLL 10
#define CLK_FOUT_BPLL 11
#define CLK_FOUT_KPLL 12
+#define CLK_ARM_CLK 13
+#define CLK_KFC_CLK 14
/* gate for special clocks (sclk) */
#define CLK_SCLK_UART0 128
--
2.6.2
From: Thomas Abraham <[email protected]>
For Exynos5420 platforms, add CPU operating points and CPU
regulator supply properties for migrating from Exynos specific
cpufreq driver to using generic cpufreq driver.
Changes by Bartlomiej:
- split Exynos5420 support from the original patch
Changes by Ben Gamari:
- Port to operating-points-v2
Cc: Kukjin Kim <[email protected]>
Cc: Doug Anderson <[email protected]>
Cc: Javier Martinez Canillas <[email protected]>
Cc: Andreas Faerber <[email protected]>
Cc: Sachin Kamat <[email protected]>
Cc: Thomas Abraham <[email protected]>
Cc: Bartlomiej Zolnierkiewicz <[email protected]>
Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]>
Signed-off-by: Ben Gamari <[email protected]>
---
arch/arm/boot/dts/exynos5420.dtsi | 122 ++++++++++++++++++++++++++++++++++++++
1 file changed, 122 insertions(+)
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 1b3d6c7..262a7d8 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -50,6 +50,116 @@
usbdrdphy1 = &usbdrd_phy1;
};
+ cpu0_opp_table: opp_table0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+ opp00 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <1250000>;
+ clock-latency-ns = <140000>;
+ };
+ opp01 {
+ opp-hz = /bits/ 64 <1700000000>;
+ opp-microvolt = <1212500>;
+ clock-latency-ns = <140000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <1600000000>;
+ opp-microvolt = <1175000>;
+ clock-latency-ns = <140000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <1500000000>;
+ opp-microvolt = <1137500>;
+ clock-latency-ns = <140000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1400000000>;
+ opp-microvolt = <1112500>;
+ clock-latency-ns = <140000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <1300000000>;
+ opp-microvolt = <1062500>;
+ clock-latency-ns = <140000>;
+ };
+ opp06 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <1037500>;
+ clock-latency-ns = <140000>;
+ };
+ opp07 {
+ opp-hz = /bits/ 64 <1100000000>;
+ opp-microvolt = <1012500>;
+ clock-latency-ns = <140000>;
+ };
+ opp08 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = < 987500>;
+ clock-latency-ns = <140000>;
+ };
+ opp09 {
+ opp-hz = /bits/ 64 <900000000>;
+ opp-microvolt = < 962500>;
+ clock-latency-ns = <140000>;
+ };
+ opp10 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = < 937500>;
+ clock-latency-ns = <140000>;
+ };
+ opp11 {
+ opp-hz = /bits/ 64 <700000000>;
+ opp-microvolt = < 912500>;
+ clock-latency-ns = <140000>;
+ };
+ };
+
+ cpu1_opp_table: opp_table1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+ opp00 {
+ opp-hz = /bits/ 64 <1300000000>;
+ opp-microvolt = <1275000>;
+ clock-latency-ns = <140000>;
+ };
+ opp01 {
+ opp-hz = /bits/ 64 <1140000000>;
+ opp-microvolt = <1212500>;
+ clock-latency-ns = <140000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <1100000000>;
+ opp-microvolt = <1162500>;
+ clock-latency-ns = <140000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <1112500>;
+ clock-latency-ns = <140000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <900000000>;
+ opp-microvolt = <1062500>;
+ clock-latency-ns = <140000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <1025000>;
+ clock-latency-ns = <140000>;
+ };
+ opp06 {
+ opp-hz = /bits/ 64 <700000000>;
+ opp-microvolt = <975000>;
+ clock-latency-ns = <140000>;
+ };
+ opp07 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <937500>;
+ clock-latency-ns = <140000>;
+ };
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
@@ -58,8 +168,11 @@
device_type = "cpu";
compatible = "arm,cortex-a15";
reg = <0x0>;
+ clocks = <&clock CLK_ARM_CLK>;
+ clock-names = "cpu-cluster.0";
clock-frequency = <1800000000>;
cci-control-port = <&cci_control1>;
+ operating-points-v2 = <&cpu0_opp_table>;
};
cpu1: cpu@1 {
@@ -68,6 +181,7 @@
reg = <0x1>;
clock-frequency = <1800000000>;
cci-control-port = <&cci_control1>;
+ operating-points-v2 = <&cpu0_opp_table>;
};
cpu2: cpu@2 {
@@ -76,6 +190,7 @@
reg = <0x2>;
clock-frequency = <1800000000>;
cci-control-port = <&cci_control1>;
+ operating-points-v2 = <&cpu0_opp_table>;
};
cpu3: cpu@3 {
@@ -84,14 +199,18 @@
reg = <0x3>;
clock-frequency = <1800000000>;
cci-control-port = <&cci_control1>;
+ operating-points-v2 = <&cpu0_opp_table>;
};
cpu4: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a7";
reg = <0x100>;
+ clocks = <&clock CLK_KFC_CLK>;
+ clock-names = "cpu-cluster.1";
clock-frequency = <1000000000>;
cci-control-port = <&cci_control0>;
+ operating-points-v2 = <&cpu1_opp_table>;
};
cpu5: cpu@101 {
@@ -100,6 +219,7 @@
reg = <0x101>;
clock-frequency = <1000000000>;
cci-control-port = <&cci_control0>;
+ operating-points-v2 = <&cpu1_opp_table>;
};
cpu6: cpu@102 {
@@ -108,6 +228,7 @@
reg = <0x102>;
clock-frequency = <1000000000>;
cci-control-port = <&cci_control0>;
+ operating-points-v2 = <&cpu1_opp_table>;
};
cpu7: cpu@103 {
@@ -116,6 +237,7 @@
reg = <0x103>;
clock-frequency = <1000000000>;
cci-control-port = <&cci_control0>;
+ operating-points-v2 = <&cpu1_opp_table>;
};
};
--
2.6.2
From: Thomas Abraham <[email protected]>
The new CPU clock type allows the use of generic arm_big_little_dt
cpufreq driver for Exynos5420.
Changes by Bartlomiej:
- split Exynos5420 support from the original patch
- disable cpufreq if big.LITTLE switcher support is enabled
Changes by Ben Gamari:
- rebase
Cc: Tomasz Figa <[email protected]>
Cc: Mike Turquette <[email protected]>
Cc: Thomas Abraham <[email protected]>
Cc: Bartlomiej Zolnierkiewicz <[email protected]>
Cc: Javier Martinez Canillas <[email protected]> (Mon. 15:01)
Signed-off-by: Thomas Abraham <[email protected]>
Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]>
Signed-off-by: Ben Gamari <[email protected]>
---
arch/arm/mach-exynos/exynos.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index 1c47aee..818e6a0 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -230,6 +230,13 @@ static const struct of_device_id exynos_cpufreq_matches[] = {
{ .compatible = "samsung,exynos4212", .data = "cpufreq-dt" },
{ .compatible = "samsung,exynos4412", .data = "cpufreq-dt" },
{ .compatible = "samsung,exynos5250", .data = "cpufreq-dt" },
+ /*
+ * FIXME: When big.LITTLE switcher is enabled system lockups during
+ * ondemand governor stress testing (observed on ODROID-XU3 board).
+ */
+#ifndef CONFIG_BL_SWITCHER
+ { .compatible = "samsung,exynos5420", .data = "arm-bL-cpufreq-dt" },
+#endif
{ /* sentinel */ }
};
--
2.6.2
From: Bartlomiej Zolnierkiewicz <[email protected]>
Fix cpu clock configuration data for Exynos5800 (it uses
higher PCLK_DBG divider values than Exynos5420 and supports
additional frequencies).
Based on Hardkernel's kernel for ODROID-XU3 board.
Cc: Tomasz Figa <[email protected]>
Cc: Mike Turquette <[email protected]>
Cc: Javier Martinez Canillas <[email protected]>
Cc: Thomas Abraham <[email protected]>
Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]>
Signed-off-by: Ben Gamari <[email protected]>
---
drivers/clk/samsung/clk-exynos5420.c | 36 +++++++++++++++++++++++++++++++++---
1 file changed, 33 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index 2288052..aa44bb7 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -1274,10 +1274,34 @@ static const struct exynos_cpuclk_cfg_data exynos5420_eglclk_d[] __initconst = {
{ 0 },
};
+static const struct exynos_cpuclk_cfg_data exynos5800_eglclk_d[] __initconst = {
+ { 2000000, E5420_EGL_DIV0(3, 7, 7, 4), },
+ { 1900000, E5420_EGL_DIV0(3, 7, 7, 4), },
+ { 1800000, E5420_EGL_DIV0(3, 7, 7, 4), },
+ { 1700000, E5420_EGL_DIV0(3, 7, 7, 3), },
+ { 1600000, E5420_EGL_DIV0(3, 7, 7, 3), },
+ { 1500000, E5420_EGL_DIV0(3, 7, 7, 3), },
+ { 1400000, E5420_EGL_DIV0(3, 7, 7, 3), },
+ { 1300000, E5420_EGL_DIV0(3, 7, 7, 2), },
+ { 1200000, E5420_EGL_DIV0(3, 7, 7, 2), },
+ { 1100000, E5420_EGL_DIV0(3, 7, 7, 2), },
+ { 1000000, E5420_EGL_DIV0(3, 7, 6, 2), },
+ { 900000, E5420_EGL_DIV0(3, 7, 6, 2), },
+ { 800000, E5420_EGL_DIV0(3, 7, 5, 2), },
+ { 700000, E5420_EGL_DIV0(3, 7, 5, 2), },
+ { 600000, E5420_EGL_DIV0(3, 7, 4, 2), },
+ { 500000, E5420_EGL_DIV0(3, 7, 3, 2), },
+ { 400000, E5420_EGL_DIV0(3, 7, 3, 2), },
+ { 300000, E5420_EGL_DIV0(3, 7, 3, 2), },
+ { 200000, E5420_EGL_DIV0(3, 7, 3, 2), },
+ { 0 },
+};
+
#define E5420_KFC_DIV(kpll, pclk, aclk) \
((((kpll) << 24) | ((pclk) << 20) | ((aclk) << 4)))
static const struct exynos_cpuclk_cfg_data exynos5420_kfcclk_d[] __initconst = {
+ { 1400000, E5420_KFC_DIV(3, 5, 3), }, /* for Exynos5800 */
{ 1300000, E5420_KFC_DIV(3, 5, 2), },
{ 1200000, E5420_KFC_DIV(3, 5, 2), },
{ 1100000, E5420_KFC_DIV(3, 5, 2), },
@@ -1357,9 +1381,15 @@ static void __init exynos5x_clk_init(struct device_node *np,
ARRAY_SIZE(exynos5800_gate_clks));
}
- exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
- mout_cpu_p[0], mout_cpu_p[1], 0x200,
- exynos5420_eglclk_d, ARRAY_SIZE(exynos5420_eglclk_d), 0);
+ if (soc == EXYNOS5420) {
+ exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
+ mout_cpu_p[0], mout_cpu_p[1], 0x200,
+ exynos5420_eglclk_d, ARRAY_SIZE(exynos5420_eglclk_d), 0);
+ } else {
+ exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
+ mout_cpu_p[0], mout_cpu_p[1], 0x200,
+ exynos5800_eglclk_d, ARRAY_SIZE(exynos5800_eglclk_d), 0);
+ }
exynos_register_cpu_clock(ctx, CLK_KFC_CLK, "kfcclk",
mout_kfc_p[0], mout_kfc_p[1], 0x28200,
exynos5420_kfcclk_d, ARRAY_SIZE(exynos5420_kfcclk_d), 0);
--
2.6.2
From: Bartlomiej Zolnierkiewicz <[email protected]>
Fix CPU operating points for Exynos5800 (it uses different
voltages than Exynos5420 and supports additional frequencies).
However don't use 2000MHz & 1900MHz OPPs (for A15 cores) and
1400MHz OPP (for A7 cores) until there is a separate DTS for
ODROID-XU3 Lite board (which doesn't support these higher
OPPs).
Based on Hardkernel's kernel for ODROID-XU3 board.
Cc: Kukjin Kim <[email protected]>
Cc: Doug Anderson <[email protected]>
Cc: Javier Martinez Canillas <[email protected]>
Cc: Andreas Faerber <[email protected]>
Cc: Sachin Kamat <[email protected]>
Cc: Thomas Abraham <[email protected]>
Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]>
Signed-off-by: Ben Gamari <[email protected]>
---
arch/arm/boot/dts/exynos5800.dtsi | 136 ++++++++++++++++++++++++++++++++++++++
1 file changed, 136 insertions(+)
diff --git a/arch/arm/boot/dts/exynos5800.dtsi b/arch/arm/boot/dts/exynos5800.dtsi
index c0bb356..43d42f4 100644
--- a/arch/arm/boot/dts/exynos5800.dtsi
+++ b/arch/arm/boot/dts/exynos5800.dtsi
@@ -17,8 +17,144 @@
/ {
compatible = "samsung,exynos5800", "samsung,exynos5";
+
+ cpu0_opp_table: opp_table0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+ opp00 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <1250000>;
+ };
+ opp01 {
+ opp-hz = /bits/ 64 <1700000000>;
+ opp-microvolt = <1250000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <1600000000>;
+ opp-microvolt = <1250000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <1500000000>;
+ opp-microvolt = <1100000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1400000000>;
+ opp-microvolt = <1100000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <1300000000>;
+ opp-microvolt = <1100000>;
+ };
+ opp06 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <1000000>;
+ };
+ opp07 {
+ opp-hz = /bits/ 64 <1100000000>;
+ opp-microvolt = <1000000>;
+ };
+ opp08 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <1000000>;
+ };
+ opp09 {
+ opp-hz = /bits/ 64 <900000000>;
+ opp-microvolt = <1000000>;
+ };
+ opp10 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <900000>;
+ };
+ opp11 {
+ opp-hz = /bits/ 64 <700000000>;
+ opp-microvolt = <900000>;
+ };
+ opp12 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <900000>;
+ };
+ opp13 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <900000>;
+ };
+ opp14 {
+ opp-hz = /bits/ 64 <400000000>;
+ opp-microvolt = <900000>;
+ };
+ opp15 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-microvolt = <900000>;
+ };
+ opp16 {
+ opp-hz = /bits/ 64 <200000000>;
+ opp-microvolt = <900000>;
+ };
+ };
+
+ cpu1_opp_table: opp_table1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+ opp00 {
+ opp-hz = /bits/ 64 <1300000000>;
+ opp-microvolt = <1250000>;
+ };
+ opp01 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <1250000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <1100000000>;
+ opp-microvolt = <1250000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <1100000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <900000000>;
+ opp-microvolt = <1100000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <1100000>;
+ };
+ opp06 {
+ opp-hz = /bits/ 64 <700000000>;
+ opp-microvolt = <1000000>;
+ };
+ opp07 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <1000000>;
+ };
+ opp08 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <1000000>;
+ };
+ opp09 {
+ opp-hz = /bits/ 64 <400000000>;
+ opp-microvolt = <1000000>;
+ };
+ opp10 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-microvolt = <900000>;
+ };
+ opp11 {
+ opp-hz = /bits/ 64 <200000000>;
+ opp-microvolt = <900000>;
+ };
+ };
};
+&cpu0 { operating-points-v2 = <&cpu0_opp_table>; };
+&cpu1 { operating-points-v2 = <&cpu0_opp_table>; };
+&cpu2 { operating-points-v2 = <&cpu0_opp_table>; };
+&cpu3 { operating-points-v2 = <&cpu0_opp_table>; };
+
+&cpu4 { operating-points-v2 = <&cpu1_opp_table>; };
+&cpu5 { operating-points-v2 = <&cpu1_opp_table>; };
+&cpu6 { operating-points-v2 = <&cpu1_opp_table>; };
+&cpu7 { operating-points-v2 = <&cpu1_opp_table>; };
+
&clock {
compatible = "samsung,exynos5800-clock";
};
--
2.6.2
The Exynos 5422 is identical to the 5800 except for the fact that it
boots from the A7 cores. Consequently, the core numbering is different:
cores 0-3 are A7s whereas 4-7 are A15s.
We can reuse the device tree of the 5800 for the 5422 but we must take
care to override the OPP tables and CPU clocks. These are otherwise
inherited from the exynos5800 devicetree, which has the CPU clusters
reversed compared to the 5422. This results in the A15 cores only
reaching 1.4GHz, the maximum rate of the KFC clock.
Cc: Javier Martinez Canillas <[email protected]>
Signed-off-by: Ben Gamari <[email protected]>
---
arch/arm/boot/dts/exynos5422-cpus.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm/boot/dts/exynos5422-cpus.dtsi b/arch/arm/boot/dts/exynos5422-cpus.dtsi
index b7f60c8..9a5131d 100644
--- a/arch/arm/boot/dts/exynos5422-cpus.dtsi
+++ b/arch/arm/boot/dts/exynos5422-cpus.dtsi
@@ -20,8 +20,10 @@
device_type = "cpu";
compatible = "arm,cortex-a7";
reg = <0x100>;
+ clocks = <&clock CLK_KFC_CLK>;
clock-frequency = <1000000000>;
cci-control-port = <&cci_control0>;
+ operating-points-v2 = <&cpu1_opp_table>;
};
&cpu1 {
@@ -30,6 +32,7 @@
reg = <0x101>;
clock-frequency = <1000000000>;
cci-control-port = <&cci_control0>;
+ operating-points-v2 = <&cpu1_opp_table>;
};
&cpu2 {
@@ -38,6 +41,7 @@
reg = <0x102>;
clock-frequency = <1000000000>;
cci-control-port = <&cci_control0>;
+ operating-points-v2 = <&cpu1_opp_table>;
};
&cpu3 {
@@ -46,14 +50,17 @@
reg = <0x103>;
clock-frequency = <1000000000>;
cci-control-port = <&cci_control0>;
+ operating-points-v2 = <&cpu1_opp_table>;
};
&cpu4 {
device_type = "cpu";
compatible = "arm,cortex-a15";
reg = <0x0>;
+ clocks = <&clock CLK_ARM_CLK>;
clock-frequency = <1800000000>;
cci-control-port = <&cci_control1>;
+ operating-points-v2 = <&cpu0_opp_table>;
};
&cpu5 {
@@ -62,6 +69,7 @@
reg = <0x1>;
clock-frequency = <1800000000>;
cci-control-port = <&cci_control1>;
+ operating-points-v2 = <&cpu0_opp_table>;
};
&cpu6 {
@@ -70,6 +78,7 @@
reg = <0x2>;
clock-frequency = <1800000000>;
cci-control-port = <&cci_control1>;
+ operating-points-v2 = <&cpu0_opp_table>;
};
&cpu7 {
@@ -78,4 +87,5 @@
reg = <0x3>;
clock-frequency = <1800000000>;
cci-control-port = <&cci_control1>;
+ operating-points-v2 = <&cpu0_opp_table>;
};
--
2.6.2
From: Thomas Abraham <[email protected]>
The new CPU clock type allows the use of generic arm_big_little_dt
cpufreq driver for Exynos5800.
Changes by Bartlomiej:
- split Exynos5800 support from the original patch
- disable cpufreq if big.LITTLE switcher support is enabled
Changes by Ben Gamari:
- rebase
Cc: Tomasz Figa <[email protected]>
Cc: Kukjin Kim <[email protected]>
Cc: Javier Martinez Canillas <[email protected]>
Signed-off-by: Thomas Abraham <[email protected]>
Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]>
Signed-off-by: Ben Gamari <[email protected]>
---
arch/arm/mach-exynos/exynos.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index 818e6a0..9289412 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -236,6 +236,7 @@ static const struct of_device_id exynos_cpufreq_matches[] = {
*/
#ifndef CONFIG_BL_SWITCHER
{ .compatible = "samsung,exynos5420", .data = "arm-bL-cpufreq-dt" },
+ { .compatible = "samsung,exynos5800", .data = "arm-bL-cpufreq-dt" },
#endif
{ /* sentinel */ }
};
--
2.6.2
From: Bartlomiej Zolnierkiewicz <[email protected]>
Add cluster regulator supply properties as a preparation to adding
generic arm_big_little_dt cpufreq driver support for Exynos5420 and
Exynos5800 based boards.
Changes by Ben Gamari:
- Add regulators to odroidxu4
Cc: Kukjin Kim <[email protected]>
Cc: Doug Anderson <[email protected]>
Cc: Javier Martinez Canillas <[email protected]>
Cc: Andreas Faerber <[email protected]>
Cc: Sachin Kamat <[email protected]>
Cc: Thomas Abraham <[email protected]>
Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]>
Signed-off-by: Ben Gamari <[email protected]>
---
arch/arm/boot/dts/exynos5420-arndale-octa.dts | 9 +++++++++
arch/arm/boot/dts/exynos5420-peach-pit.dts | 8 ++++++++
arch/arm/boot/dts/exynos5420-smdk5420.dts | 8 ++++++++
arch/arm/boot/dts/exynos5422-odroidxu3.dts | 8 ++++++++
arch/arm/boot/dts/exynos5422-odroidxu4.dts | 10 ++++++++++
arch/arm/boot/dts/exynos5800-peach-pi.dts | 8 ++++++++
6 files changed, 51 insertions(+)
diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts b/arch/arm/boot/dts/exynos5420-arndale-octa.dts
index 4ecef69..a044da7 100644
--- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts
+++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts
@@ -52,6 +52,15 @@
};
};
+&cpu0 {
+ cpu-cluster.0-supply = <&buck2_reg>;
+};
+
+&cpu4 {
+ cpu-cluster.1-supply = <&buck6_reg>;
+};
+
+
&usbdrd_dwc3_1 {
dr_mode = "host";
};
diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
index 72ba6f0..eea0aa6 100644
--- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
+++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
@@ -676,6 +676,14 @@
};
};
+&cpu0 {
+ cpu-cluster.0-supply = <&buck2_reg>;
+};
+
+&cpu4 {
+ cpu-cluster.1-supply = <&buck6_reg>;
+};
+
&i2c_2 {
status = "okay";
samsung,i2c-sda-delay = <100>;
diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts
index ac35aef..d44a280 100644
--- a/arch/arm/boot/dts/exynos5420-smdk5420.dts
+++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts
@@ -423,3 +423,11 @@
&usbdrd_phy1 {
vbus-supply = <&usb301_vbus_reg>;
};
+
+&cpu0 {
+ cpu-cluster.0-supply = <&buck2_reg>;
+};
+
+&cpu4 {
+ cpu-cluster.1-supply = <&buck6_reg>;
+};
diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3.dts b/arch/arm/boot/dts/exynos5422-odroidxu3.dts
index 0c0bbdb..d6650a1 100644
--- a/arch/arm/boot/dts/exynos5422-odroidxu3.dts
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3.dts
@@ -53,6 +53,14 @@
};
};
+&cpu0 {
+ cpu-cluster.0-supply = <&buck2_reg>;
+};
+
+&cpu4 {
+ cpu-cluster.1-supply = <&buck6_reg>;
+};
+
&i2c_0 {
status = "okay";
diff --git a/arch/arm/boot/dts/exynos5422-odroidxu4.dts b/arch/arm/boot/dts/exynos5422-odroidxu4.dts
index 2faf886..9f88c34 100644
--- a/arch/arm/boot/dts/exynos5422-odroidxu4.dts
+++ b/arch/arm/boot/dts/exynos5422-odroidxu4.dts
@@ -32,6 +32,16 @@
};
};
+&cpu0 {
+ cpu-cluster.0-supply = <&buck2_reg>;
+ cpu-cluster.1-supply = <&buck6_reg>;
+};
+
+&cpu4 {
+ cpu-cluster.0-supply = <&buck2_reg>;
+ cpu-cluster.1-supply = <&buck6_reg>;
+};
+
&pwm {
/*
* PWM 0 -- fan
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
index 49a4f43..a06587b 100644
--- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
+++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
@@ -638,6 +638,14 @@
};
};
+&cpu0 {
+ cpu-cluster.0-supply = <&buck2_reg>;
+};
+
+&cpu4 {
+ cpu-cluster.1-supply = <&buck6_reg>;
+};
+
&i2c_2 {
status = "okay";
samsung,i2c-sda-delay = <100>;
--
2.6.2
The arm_big_little cpufreq driver can use operating points from
operating-points-v2 nodes without any trouble.
Cc: Javier Martinez Canillas <[email protected]>
Signed-off-by: Ben Gamari <[email protected]>
---
drivers/cpufreq/arm_big_little_dt.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/cpufreq/arm_big_little_dt.c b/drivers/cpufreq/arm_big_little_dt.c
index 16ddeef..be7f632 100644
--- a/drivers/cpufreq/arm_big_little_dt.c
+++ b/drivers/cpufreq/arm_big_little_dt.c
@@ -35,12 +35,16 @@ static struct device_node *get_cpu_node_with_valid_op(int cpu)
{
struct device_node *np = of_cpu_device_node_get(cpu);
- if (!of_get_property(np, "operating-points", NULL)) {
- of_node_put(np);
- np = NULL;
+ if (of_get_property(np, "operating-points-v2", NULL)) {
+ return np;
}
- return np;
+ if (of_get_property(np, "operating-points", NULL)) {
+ return np;
+ }
+
+ of_node_put(np);
+ return NULL;
}
static int dt_init_opp_table(struct device *cpu_dev)
--
2.6.2
The frequency units are very confusing in this area as OPPs use Hz
whereas cpufreq uses kHz. Be explicit about this in variable naming.
Cc: Javier Martinez Canillas <[email protected]>
Signed-off-by: Ben Gamari <[email protected]>
---
drivers/cpufreq/arm_big_little.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index 855599b..2d5761c 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -130,14 +130,14 @@ static unsigned int bL_cpufreq_get_rate(unsigned int cpu)
}
static int
-bL_cpufreq_set_rate_cluster(u32 cpu, u32 cluster, u32 new_rate)
+bL_cpufreq_set_rate_cluster(u32 cpu, u32 cluster, u32 new_rate_kHz)
{
unsigned long volt = 0, volt_old = 0;
long freq_Hz;
u32 old_rate;
int ret;
- freq_Hz = new_rate * 1000;
+ freq_Hz = new_rate_kHz * 1000;
old_rate = clk_get_rate(clk[cluster]) / 1000;
if (!IS_ERR(reg[cluster])) {
@@ -163,10 +163,10 @@ bL_cpufreq_set_rate_cluster(u32 cpu, u32 cluster, u32 new_rate)
pr_debug("%s: cpu %d, cluster: %d, %u MHz, %ld mV --> %u MHz, %ld mV\n",
__func__, cpu, cluster,
old_rate / 1000, (volt_old > 0) ? volt_old / 1000 : -1,
- new_rate / 1000, volt ? volt / 1000 : -1);
+ new_rate_kHz / 1000, volt ? volt / 1000 : -1);
/* scaling up? scale voltage before frequency */
- if (!IS_ERR(reg[cluster]) && new_rate > old_rate) {
+ if (!IS_ERR(reg[cluster]) && new_rate_kHz > old_rate) {
ret = regulator_set_voltage_tol(reg[cluster], volt, 0);
if (ret) {
pr_err("%s: cpu: %d, cluster: %d, failed to scale voltage up: %d\n",
@@ -175,7 +175,7 @@ bL_cpufreq_set_rate_cluster(u32 cpu, u32 cluster, u32 new_rate)
}
}
- ret = clk_set_rate(clk[cluster], new_rate * 1000);
+ ret = clk_set_rate(clk[cluster], new_rate_kHz * 1000);
if (WARN_ON(ret)) {
pr_err("%s: clk_set_rate failed: %d, cluster: %d\n",
__func__, cluster, ret);
@@ -185,7 +185,7 @@ bL_cpufreq_set_rate_cluster(u32 cpu, u32 cluster, u32 new_rate)
}
/* scaling down? scale voltage after frequency */
- if (!IS_ERR(reg[cluster]) && new_rate < old_rate) {
+ if (!IS_ERR(reg[cluster]) && new_rate_kHz < old_rate) {
ret = regulator_set_voltage_tol(reg[cluster], volt, 0);
if (ret) {
pr_err("%s: cpu: %d, cluster: %d, failed to scale voltage down: %d\n",
@@ -199,7 +199,7 @@ bL_cpufreq_set_rate_cluster(u32 cpu, u32 cluster, u32 new_rate)
}
static unsigned int
-bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
+bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate_kHz)
{
u32 new_rate, prev_rate;
int ret;
@@ -209,13 +209,13 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
if (bLs) {
prev_rate = per_cpu(cpu_last_req_freq, cpu);
- per_cpu(cpu_last_req_freq, cpu) = rate;
+ per_cpu(cpu_last_req_freq, cpu) = rate_kHz;
per_cpu(physical_cluster, cpu) = new_cluster;
new_rate = find_cluster_maxfreq(new_cluster);
new_rate = ACTUAL_FREQ(new_cluster, new_rate);
} else {
- new_rate = rate;
+ new_rate = rate_kHz;
}
pr_debug("%s: cpu: %d, old cluster: %d, new cluster: %d, freq: %d\n",
@@ -236,7 +236,7 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
} else if (ret && bLs) {
per_cpu(cpu_last_req_freq, cpu) = prev_rate;
per_cpu(physical_cluster, cpu) = old_cluster;
- }
+ }
mutex_unlock(&cluster_lock[new_cluster]);
--
2.6.2
Cc: Javier Martinez Canillas <[email protected]>
Signed-off-by: Ben Gamari <[email protected]>
---
drivers/cpufreq/arm_big_little.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index 2d5761c..5d30c26 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -158,6 +158,9 @@ bL_cpufreq_set_rate_cluster(u32 cpu, u32 cluster, u32 new_rate_kHz)
volt_old = regulator_get_voltage(reg[cluster]);
pr_debug("%s: cpu %d, cluster: %d, Found OPP: %ld kHz, %ld uV\n",
__func__, cpu, cluster, opp_freq / 1000, volt);
+ } else {
+ pr_err("%s: cpu %d, cluster: %d, Have no regulator\n",
+ __func__, cpu, cluster);
}
pr_debug("%s: cpu %d, cluster: %d, %u MHz, %ld mV --> %u MHz, %ld mV\n",
--
2.6.2
Hi Ben Gamari,
On 3 December 2015 at 02:49, Ben Gamari <[email protected]> wrote:
> From: Bartlomiej Zolnierkiewicz <[email protected]>
>
> Add cluster regulator support as a preparation to adding
> generic arm_big_little_dt cpufreq_dt driver support for
> ODROID-XU3 board. This allows arm_big_little[_dt] driver
> to set not only the frequency but also the voltage (which
> is obtained from operating point's voltage value) for CPU
> clusters.
>
> Cc: Kukjin Kim <[email protected]>
> Cc: Doug Anderson <[email protected]>
> Cc: Javier Martinez Canillas <[email protected]>
> Cc: Andreas Faerber <[email protected]>
> Cc: Sachin Kamat <[email protected]>
> Cc: Thomas Abraham <[email protected]>
> Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]>
> Signed-off-by: Ben Gamari <[email protected]>
> ---
> .../bindings/cpufreq/arm_big_little_dt.txt | 4 +
> drivers/cpufreq/arm_big_little.c | 155 ++++++++++++++++++---
> 2 files changed, 142 insertions(+), 17 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/cpufreq/arm_big_little_dt.txt b/Documentation/devicetree/bindings/cpufreq/arm_big_little_dt.txt
> index 0715695..8ca4a12 100644
> --- a/Documentation/devicetree/bindings/cpufreq/arm_big_little_dt.txt
> +++ b/Documentation/devicetree/bindings/cpufreq/arm_big_little_dt.txt
> @@ -18,6 +18,10 @@ Required properties:
> Optional properties:
> - clock-latency: Specify the possible maximum transition latency for clock,
> in unit of nanoseconds.
> +- cpu-cluster.0-supply: Provides the regulator node supplying voltage to CPU
> + cluster 0.
> +- cpu-cluster.1-supply: Provides the regulator node supplying voltage to CPU
> + cluster 1.
>
> Examples:
>
> diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
> index c5d256c..855599b 100644
> --- a/drivers/cpufreq/arm_big_little.c
> +++ b/drivers/cpufreq/arm_big_little.c
> @@ -31,6 +31,7 @@
> #include <linux/slab.h>
> #include <linux/topology.h>
> #include <linux/types.h>
> +#include <linux/regulator/consumer.h>
>
> #include "arm_big_little.h"
>
> @@ -57,6 +58,9 @@ static bool bL_switching_enabled;
>
> static struct cpufreq_arm_bL_ops *arm_bL_ops;
> static struct clk *clk[MAX_CLUSTERS];
> +static struct regulator *reg[MAX_CLUSTERS];
> +static struct device *cpu_devs[MAX_CLUSTERS];
> +static int transition_latencies[MAX_CLUSTERS];
> static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS + 1];
> static atomic_t cluster_usage[MAX_CLUSTERS + 1];
>
> @@ -125,6 +129,75 @@ static unsigned int bL_cpufreq_get_rate(unsigned int cpu)
> }
> }
>
> +static int
> +bL_cpufreq_set_rate_cluster(u32 cpu, u32 cluster, u32 new_rate)
> +{
> + unsigned long volt = 0, volt_old = 0;
> + long freq_Hz;
> + u32 old_rate;
> + int ret;
> +
> + freq_Hz = new_rate * 1000;
> + old_rate = clk_get_rate(clk[cluster]) / 1000;
> +
> + if (!IS_ERR(reg[cluster])) {
> + struct dev_pm_opp *opp;
> + unsigned long opp_freq;
> +
> + rcu_read_lock();
> + opp = dev_pm_opp_find_freq_ceil(cpu_devs[cluster], &freq_Hz);
> + if (IS_ERR(opp)) {
> + rcu_read_unlock();
> + pr_err("%s: cpu %d, cluster: %d, failed to find OPP for %ld\n",
> + __func__, cpu, cluster, freq_Hz);
> + return PTR_ERR(opp);
> + }
> + volt = dev_pm_opp_get_voltage(opp);
> + opp_freq = dev_pm_opp_get_freq(opp);
> + rcu_read_unlock();
> + volt_old = regulator_get_voltage(reg[cluster]);
> + pr_debug("%s: cpu %d, cluster: %d, Found OPP: %ld kHz, %ld uV\n",
> + __func__, cpu, cluster, opp_freq / 1000, volt);
> + }
> +
> + pr_debug("%s: cpu %d, cluster: %d, %u MHz, %ld mV --> %u MHz, %ld mV\n",
> + __func__, cpu, cluster,
> + old_rate / 1000, (volt_old > 0) ? volt_old / 1000 : -1,
> + new_rate / 1000, volt ? volt / 1000 : -1);
> +
> + /* scaling up? scale voltage before frequency */
> + if (!IS_ERR(reg[cluster]) && new_rate > old_rate) {
> + ret = regulator_set_voltage_tol(reg[cluster], volt, 0);
> + if (ret) {
> + pr_err("%s: cpu: %d, cluster: %d, failed to scale voltage up: %d\n",
> + __func__, cpu, cluster, ret);
> + return ret;
> + }
> + }
> +
> + ret = clk_set_rate(clk[cluster], new_rate * 1000);
> + if (WARN_ON(ret)) {
> + pr_err("%s: clk_set_rate failed: %d, cluster: %d\n",
> + __func__, cluster, ret);
> + if (!IS_ERR(reg[cluster]) && volt_old > 0)
> + regulator_set_voltage_tol(reg[cluster], volt_old, 0);
> + return ret;
> + }
> +
> + /* scaling down? scale voltage after frequency */
> + if (!IS_ERR(reg[cluster]) && new_rate < old_rate) {
> + ret = regulator_set_voltage_tol(reg[cluster], volt, 0);
> + if (ret) {
> + pr_err("%s: cpu: %d, cluster: %d, failed to scale voltage down: %d\n",
> + __func__, cpu, cluster, ret);
> + clk_set_rate(clk[cluster], old_rate * 1000);
> + return ret;
> + }
> + }
> +
> + return 0;
> +}
> +
> static unsigned int
> bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
> {
> @@ -148,7 +221,7 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
> pr_debug("%s: cpu: %d, old cluster: %d, new cluster: %d, freq: %d\n",
> __func__, cpu, old_cluster, new_cluster, new_rate);
>
> - ret = clk_set_rate(clk[new_cluster], new_rate * 1000);
> + ret = bL_cpufreq_set_rate_cluster(cpu, new_cluster, new_rate);
> if (!ret) {
> /*
> * FIXME: clk_set_rate hasn't returned an error here however it
> @@ -160,22 +233,15 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
> */
> if (clk_get_rate(clk[new_cluster]) != new_rate * 1000)
> ret = -EIO;
> - }
> -
> - if (WARN_ON(ret)) {
> - pr_err("clk_set_rate failed: %d, new cluster: %d\n", ret,
> - new_cluster);
> - if (bLs) {
> - per_cpu(cpu_last_req_freq, cpu) = prev_rate;
> - per_cpu(physical_cluster, cpu) = old_cluster;
> - }
> + } else if (ret && bLs) {
> + per_cpu(cpu_last_req_freq, cpu) = prev_rate;
> + per_cpu(physical_cluster, cpu) = old_cluster;
> + }
>
> - mutex_unlock(&cluster_lock[new_cluster]);
> + mutex_unlock(&cluster_lock[new_cluster]);
>
> + if(ret)
> return ret;
> - }
> -
> - mutex_unlock(&cluster_lock[new_cluster]);
>
> /* Recalc freq for old cluster when switching clusters */
> if (old_cluster != new_cluster) {
> @@ -195,9 +261,10 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
> pr_debug("%s: Updating rate of old cluster: %d, to freq: %d\n",
> __func__, old_cluster, new_rate);
>
> - if (clk_set_rate(clk[old_cluster], new_rate * 1000))
> - pr_err("%s: clk_set_rate failed: %d, old cluster: %d\n",
> - __func__, ret, old_cluster);
> + if (bL_cpufreq_set_rate_cluster(cpu, old_cluster, new_rate)) {
> + pr_err("%s: bL_cpufreq_set_rate_cluster failed\n",
> + __func__);
> + }
> }
> mutex_unlock(&cluster_lock[old_cluster]);
> }
> @@ -304,6 +371,8 @@ static void _put_cluster_clk_and_freq_table(struct device *cpu_dev)
> return;
>
> clk_put(clk[cluster]);
> + if (!IS_ERR(reg[cluster]))
> + regulator_put(reg[cluster]);
> dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]);
> if (arm_bL_ops->free_opp_table)
> arm_bL_ops->free_opp_table(cpu_dev);
> @@ -337,7 +406,9 @@ static void put_cluster_clk_and_freq_table(struct device *cpu_dev)
>
> static int _get_cluster_clk_and_freq_table(struct device *cpu_dev)
> {
> + unsigned long min_uV = ~0, max_uV = 0;
> u32 cluster = raw_cpu_to_cluster(cpu_dev->id);
> + char name[14] = "cpu-cluster.";
> int ret;
>
> if (freq_table[cluster])
> @@ -350,6 +421,51 @@ static int _get_cluster_clk_and_freq_table(struct device *cpu_dev)
> goto out;
> }
>
> + name[12] = cluster + '0';
> + reg[cluster] = regulator_get_optional(cpu_dev, name);
> + if (!IS_ERR(reg[cluster])) {
> + unsigned long opp_freq = 0;
> +
> + dev_dbg(cpu_dev, "%s: reg: %p, cluster: %d\n",
> + __func__, reg[cluster], cluster);
> + cpu_devs[cluster] = cpu_dev;
> +
> + /*
> + * Disable any OPPs where the connected regulator isn't able to
> + * provide the specified voltage and record minimum and maximum
> + * voltage levels.
> + */
> + while (1) {
> + struct dev_pm_opp *opp;
> + unsigned long opp_uV;
> +
> + rcu_read_lock();
> + opp = dev_pm_opp_find_freq_ceil(cpu_dev, &opp_freq);
> + if (IS_ERR(opp)) {
> + rcu_read_unlock();
> + break;
> + }
> + opp_uV = dev_pm_opp_get_voltage(opp);
> + rcu_read_unlock();
> +
> + if (regulator_is_supported_voltage(reg[cluster], opp_uV,
> + opp_uV)) {
> + if (opp_uV < min_uV)
> + min_uV = opp_uV;
> + if (opp_uV > max_uV)
> + max_uV = opp_uV;
> + } else {
> + dev_pm_opp_disable(cpu_dev, opp_freq);
> + }
> +
> + opp_freq++;
> + }
> +
> + ret = regulator_set_voltage_time(reg[cluster], min_uV, max_uV);
> + if (ret > 0)
> + transition_latencies[cluster] = ret * 1000;
> + }
> +
> ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table[cluster]);
> if (ret) {
> dev_err(cpu_dev, "%s: failed to init cpufreq table, cpu: %d, err: %d\n",
> @@ -483,6 +599,11 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
> else
> policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
>
> + if (cur_cluster < MAX_CLUSTERS &&
> + policy->cpuinfo.transition_latency != CPUFREQ_ETERNAL)
> + policy->cpuinfo.transition_latency
> + += transition_latencies[cur_cluster];
> +
> if (is_bL_switching_enabled())
> per_cpu(cpu_last_req_freq, policy->cpu) = clk_get_cpu_rate(policy->cpu);
>
> --
> 2.6.2
>
I am getting following warning when I am trying to use git am
root@odroidxu4:/usr/src/odroidxu3-4.y-final# git am -s cpuf1.patch
Applying: cpufreq: arm_big_little: add cluster regulator support
/usr/src/odroidxu3-4.y-final/.git/rebase-apply/patch:144: trailing whitespace.
}
warning: 1 line adds whitespace errors.
-----------------------------------------------------------
Also I have disabled and enabled following config options.
-CONFIG_BL_SWITCHER=y
-CONFIG_BL_SWITCHER_DUMMY_IF=y
CONFIG_ARM_BIG_LITTLE_CPUFREQ=y
CONFIG_ARM_DT_BL_CPUFREQ=y
But I could not see the cpu frequency working on my Odroid XU4. Am I
missing some thing.
Every 2.0s: cpupower -c 4 frequency-info
Thu Dec
3 04:02:36 2015
analyzing CPU 4:
driver: arm-big-little
CPUs which run at the same hardware frequency: 4 5 6 7
CPUs which need to have their frequency coordinated by software: 4 5 6 7
maximum transition latency: 0.00 ms.
hardware limits: 200 MHz - 1.80 GHz
available frequency steps: 200 MHz, 300 MHz, 400 MHz, 500 MHz, 600
MHz, 700 MHz, 800 MHz, 900 MHz, 1000 MHz, 1.10 GHz, 1.20 GHz, 1.30
GHz, 1.40 GHz, 1.50 GH
z, 1.60 GHz, 1.70 GHz, 1.80 GHz
available cpufreq governors: ondemand, performance
current policy: frequency should be within 200 MHz and 1.80 GHz.
The governor "performance" may decide which speed to use
within this range.
current CPU frequency is 1.80 GHz (asserted by call to hardware).
cpufreq stats: 200 MHz:0.00%, 300 MHz:0.00%, 400 MHz:0.00%, 500
MHz:0.00%, 600 MHz:0.00%, 700 MHz:0.00%, 800 MHz:0.00%, 900 MHz:0.00%,
1000 MHz:0.00%, 1.10
GHz:0.00%, 1.20 GHz:0.00%, 1.30 GHz:0.00%, 1.40 GHz:0.00%, 1.50
GHz:0.00%, 1.60 GHz:0.00%, 1.70 GHz:0.00%, 1.80 GHz:100.00% (1)
-Anand Moon
Hi Ben,
On 02-12-15, 22:19, Ben Gamari wrote:
>
> This patch series adds cpufreq support for the Exynos 5800, 5420, and 5422
> SOCs. In particular, it adds support for operating-points-v2 bindings to the
> arm-big-little cpufreq driver and updates the above-mentioned SOCs' devicetrees
> to take advantage of this support. There are also a couple of patches improving
> the clarify of the arm-big-little implementation. It is built on a set posted
> by Bartlomiej Zolnierkiewicz in April 2015.
>
> The most signficant change from the original series is porting to the
> operating-points-v2 devicetree bindings. The series has been tested by me on
> and Odroid XU4 and by Javier Martinez Canillas on a Peach Pit.
Thanks for working with opp-v2 bindings, really appreciate it.
But, before I start reviewing this series, I have few comments.
- We weren't able to use cpufreq-dt driver for big LITTLE platforms
earlier, as it never had multi cluster support and we wanted
clock-sharing information via DT.
- That is all fixed now.
- I want Samsung's big LITTLE platforms to use cpufreq-dt and drop
arm_big_little driver completely.
- The only case for which it (arm_big_little) driver might be useful
is the IKS solution. Which I don't believe you are going to use in
future :)
My plan for the arm-big-little driver:
- Migrate all platforms to use cpufreq-dt instead for non-IKS
solution
- Make arm-big-little driver arm-big-little-iks only driver.
@Sudeep: What would it take you to use cpufreq-dt for ARM's platforms
?
--
viresh
On 03.12.2015 06:19, Ben Gamari wrote:
> From: Thomas Abraham <[email protected]>
>
> With the addition of the new Samsung specific cpu-clock type, the
> arm clock can be represented as a cpu-clock type. Add the CPU clock
> configuration data and instantiate the CPU clock type for Exynos5420.
>
> Changes by Bartlomiej:
> - split Exynos5420 support from the original patches
> - moved E5420_[EGL,KFC]_DIV0() macros to clk-exynos5420.c
>
> Changes by Ben Gamari:
> - Rebased
If only rebasing then you should retain the Lukasz's review tag. He
doesn't have to review it again, right? :)
>
> Cc: Tomasz Figa <[email protected]>
> Cc: Mike Turquette <[email protected]>
> Cc: Javier Martinez Canillas <[email protected]>
> Signed-off-by: Thomas Abraham <[email protected]>
> Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]>
> Signed-off-by: Ben Gamari <[email protected]>
> ---
> drivers/clk/samsung/clk-exynos5420.c | 58 ++++++++++++++++++++++++++++++++--
> include/dt-bindings/clock/exynos5420.h | 2 ++
> 2 files changed, 58 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
> index 389af3c..2288052 100644
> --- a/drivers/clk/samsung/clk-exynos5420.c
> +++ b/drivers/clk/samsung/clk-exynos5420.c
> @@ -18,6 +18,7 @@
> #include <linux/syscore_ops.h>
>
> #include "clk.h"
> +#include "clk-cpu.h"
>
> #define APLL_LOCK 0x0
> #define APLL_CON0 0x100
> @@ -616,9 +617,11 @@ static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = {
> MUX(0, "mout_mspll_kfc", mout_mspll_cpu_p, SRC_TOP7, 8, 2),
> MUX(0, "mout_mspll_cpu", mout_mspll_cpu_p, SRC_TOP7, 12, 2),
>
> - MUX(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1),
> + MUX_F(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
> + CLK_SET_RATE_PARENT, 0),
> MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
> - MUX(0, "mout_kpll", mout_kpll_p, SRC_KFC, 0, 1),
> + MUX_F(0, "mout_kpll", mout_kpll_p, SRC_KFC, 0, 1,
> + CLK_SET_RATE_PARENT, 0),
> MUX(0, "mout_kfc", mout_kfc_p, SRC_KFC, 16, 1),
>
> MUX(0, "mout_aclk200", mout_group1_p, SRC_TOP0, 8, 2),
> @@ -1246,6 +1249,50 @@ static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = {
> KPLL_CON0, NULL),
> };
>
> +#define E5420_EGL_DIV0(apll, pclk_dbg, atb, cpud) \
> + ((((apll) << 24) | ((pclk_dbg) << 20) | ((atb) << 16) | \
> + ((cpud) << 4)))
> +
> +static const struct exynos_cpuclk_cfg_data exynos5420_eglclk_d[] __initconst = {
> + { 1800000, E5420_EGL_DIV0(3, 7, 7, 4), },
> + { 1700000, E5420_EGL_DIV0(3, 7, 7, 3), },
> + { 1600000, E5420_EGL_DIV0(3, 7, 7, 3), },
> + { 1500000, E5420_EGL_DIV0(3, 7, 7, 3), },
> + { 1400000, E5420_EGL_DIV0(3, 7, 7, 3), },
> + { 1300000, E5420_EGL_DIV0(3, 7, 7, 2), },
> + { 1200000, E5420_EGL_DIV0(3, 7, 7, 2), },
> + { 1100000, E5420_EGL_DIV0(3, 7, 7, 2), },
> + { 1000000, E5420_EGL_DIV0(3, 6, 6, 2), },
> + { 900000, E5420_EGL_DIV0(3, 6, 6, 2), },
> + { 800000, E5420_EGL_DIV0(3, 5, 5, 2), },
> + { 700000, E5420_EGL_DIV0(3, 5, 5, 2), },
> + { 600000, E5420_EGL_DIV0(3, 4, 4, 2), },
> + { 500000, E5420_EGL_DIV0(3, 3, 3, 2), },
> + { 400000, E5420_EGL_DIV0(3, 3, 3, 2), },
> + { 300000, E5420_EGL_DIV0(3, 3, 3, 2), },
> + { 200000, E5420_EGL_DIV0(3, 3, 3, 2), },
> + { 0 },
The vendor code (Galaxy S5 with Exynos5422) sets pclk_dbg divider to 7.
In the same time APLL divider is only 1.
For the ACLK divider (of KFC below) the vendor sets 3, not 2.
The values also don't match the Exynos5420 from Note 3.
The Exynos5800 apparently has values more similar to 5422.
The question is: for which exact model this is? We can of course choose
the safest values here but probably these would be with the highest
dividers?
Best regards,
Krzyztof
> +};
> +
> +#define E5420_KFC_DIV(kpll, pclk, aclk) \
> + ((((kpll) << 24) | ((pclk) << 20) | ((aclk) << 4)))
> +
> +static const struct exynos_cpuclk_cfg_data exynos5420_kfcclk_d[] __initconst = {
> + { 1300000, E5420_KFC_DIV(3, 5, 2), },
> + { 1200000, E5420_KFC_DIV(3, 5, 2), },
> + { 1100000, E5420_KFC_DIV(3, 5, 2), },
> + { 1000000, E5420_KFC_DIV(3, 5, 2), },
> + { 900000, E5420_KFC_DIV(3, 5, 2), },
> + { 800000, E5420_KFC_DIV(3, 5, 2), },
> + { 700000, E5420_KFC_DIV(3, 4, 2), },
> + { 600000, E5420_KFC_DIV(3, 4, 2), },
> + { 500000, E5420_KFC_DIV(3, 4, 2), },
> + { 400000, E5420_KFC_DIV(3, 3, 2), },
> + { 300000, E5420_KFC_DIV(3, 3, 2), },
> + { 200000, E5420_KFC_DIV(3, 3, 2), },
> + { 0 },
> +};
> +
> static const struct of_device_id ext_clk_match[] __initconst = {
> { .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, },
> { },
> @@ -1310,6 +1357,13 @@ static void __init exynos5x_clk_init(struct device_node *np,
> ARRAY_SIZE(exynos5800_gate_clks));
> }
>
> + exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
> + mout_cpu_p[0], mout_cpu_p[1], 0x200,
> + exynos5420_eglclk_d, ARRAY_SIZE(exynos5420_eglclk_d), 0);
> + exynos_register_cpu_clock(ctx, CLK_KFC_CLK, "kfcclk",
> + mout_kfc_p[0], mout_kfc_p[1], 0x28200,
> + exynos5420_kfcclk_d, ARRAY_SIZE(exynos5420_kfcclk_d), 0);
> +
> exynos5420_clk_sleep_init();
>
> samsung_clk_of_add_provider(np, ctx);
> diff --git a/include/dt-bindings/clock/exynos5420.h b/include/dt-bindings/clock/exynos5420.h
> index 99da0d1..dde9664 100644
> --- a/include/dt-bindings/clock/exynos5420.h
> +++ b/include/dt-bindings/clock/exynos5420.h
> @@ -25,6 +25,8 @@
> #define CLK_FOUT_MPLL 10
> #define CLK_FOUT_BPLL 11
> #define CLK_FOUT_KPLL 12
> +#define CLK_ARM_CLK 13
> +#define CLK_KFC_CLK 14
>
> /* gate for special clocks (sclk) */
> #define CLK_SCLK_UART0 128
>
Viresh Kumar <[email protected]> writes:
> Hi Ben,
Hi Viresh,
> On 02-12-15, 22:19, Ben Gamari wrote:
>>
>> This patch series adds cpufreq support for the Exynos 5800, 5420, and 5422
>> SOCs. In particular, it adds support for operating-points-v2 bindings to the
>> arm-big-little cpufreq driver and updates the above-mentioned SOCs' devicetrees
>> to take advantage of this support. There are also a couple of patches improving
>> the clarify of the arm-big-little implementation. It is built on a set posted
>> by Bartlomiej Zolnierkiewicz in April 2015.
>>
>> The most signficant change from the original series is porting to the
>> operating-points-v2 devicetree bindings. The series has been tested by me on
>> and Odroid XU4 and by Javier Martinez Canillas on a Peach Pit.
>
> Thanks for working with opp-v2 bindings, really appreciate it.
My pleasure.
> But, before I start reviewing this series, I have few comments.
> - We weren't able to use cpufreq-dt driver for big LITTLE platforms
> earlier, as it never had multi cluster support and we wanted
> clock-sharing information via DT.
Fair enough.
> - That is all fixed now.
I did not see any mention of this in the cpufreq-dt driver binding
documentation, otherwise I would have tried going this route.
Do you have any references? I'd be happy to examine what would be
necessary to go this route although, being an independent contributor,
it may take time.
> - I want Samsung's big LITTLE platforms to use cpufreq-dt and drop
> arm_big_little driver completely.
That sounds like a great direction going forward. However, I would still
kindly request that you consider this series.
The existence of future plans of course does not change the fact that
users have real hardware today; hardware that they have spent money on
and would like to use. Cpufreq support has already been deferred once
for similar reasons of interface churn which essentially forestalled
working functionality from entering the kernel by eight months; I'd
really like to avoid having this happen again.
> - The only case for which it (arm_big_little) driver might be useful
> is the IKS solution. Which I don't believe you are going to use in
> future :)
Indeed.
> My plan for the arm-big-little driver:
> - Migrate all platforms to use cpufreq-dt instead for non-IKS
> solution
> - Make arm-big-little driver arm-big-little-iks only driver.
Sounds reasonable to me. However, I'd just like to reiterate that this
line of work can be pursued independently from the upstreaming of this
series.
Thanks for your time,
- Ben
Krzysztof Kozlowski <[email protected]> writes:
> On 03.12.2015 06:19, Ben Gamari wrote:
>> From: Thomas Abraham <[email protected]>
>>
>> With the addition of the new Samsung specific cpu-clock type, the
>> arm clock can be represented as a cpu-clock type. Add the CPU clock
>> configuration data and instantiate the CPU clock type for Exynos5420.
>>
>> Changes by Bartlomiej:
>> - split Exynos5420 support from the original patches
>> - moved E5420_[EGL,KFC]_DIV0() macros to clk-exynos5420.c
>>
>> Changes by Ben Gamari:
>> - Rebased
>
> If only rebasing then you should retain the Lukasz's review tag. He
> doesn't have to review it again, right? :)
Yep, very true.
>> +static const struct exynos_cpuclk_cfg_data exynos5420_eglclk_d[] __initconst = {
>> + { 1800000, E5420_EGL_DIV0(3, 7, 7, 4), },
>> + { 1700000, E5420_EGL_DIV0(3, 7, 7, 3), },
>> + { 1600000, E5420_EGL_DIV0(3, 7, 7, 3), },
>> + { 1500000, E5420_EGL_DIV0(3, 7, 7, 3), },
>> + { 1400000, E5420_EGL_DIV0(3, 7, 7, 3), },
>> + { 1300000, E5420_EGL_DIV0(3, 7, 7, 2), },
>> + { 1200000, E5420_EGL_DIV0(3, 7, 7, 2), },
>> + { 1100000, E5420_EGL_DIV0(3, 7, 7, 2), },
>> + { 1000000, E5420_EGL_DIV0(3, 6, 6, 2), },
>> + { 900000, E5420_EGL_DIV0(3, 6, 6, 2), },
>> + { 800000, E5420_EGL_DIV0(3, 5, 5, 2), },
>> + { 700000, E5420_EGL_DIV0(3, 5, 5, 2), },
>> + { 600000, E5420_EGL_DIV0(3, 4, 4, 2), },
>> + { 500000, E5420_EGL_DIV0(3, 3, 3, 2), },
>> + { 400000, E5420_EGL_DIV0(3, 3, 3, 2), },
>> + { 300000, E5420_EGL_DIV0(3, 3, 3, 2), },
>> + { 200000, E5420_EGL_DIV0(3, 3, 3, 2), },
>> + { 0 },
>
> The vendor code (Galaxy S5 with Exynos5422) sets pclk_dbg divider to 7.
> In the same time APLL divider is only 1.
>
> For the ACLK divider (of KFC below) the vendor sets 3, not 2.
>
> The values also don't match the Exynos5420 from Note 3.
>
> The Exynos5800 apparently has values more similar to 5422.
>
> The question is: for which exact model this is? We can of course choose
> the safest values here but probably these would be with the highest
> dividers?
>
I'm afraid I can't comment here. Thomas, perhaps you could offer some
insight?
Cheers,
- Ben
On 03-12-15, 11:26, Ben Gamari wrote:
> Viresh Kumar <[email protected]> writes:
> > But, before I start reviewing this series, I have few comments.
> > - We weren't able to use cpufreq-dt driver for big LITTLE platforms
> > earlier, as it never had multi cluster support and we wanted
> > clock-sharing information via DT.
>
> Fair enough.
>
> > - That is all fixed now.
>
> I did not see any mention of this in the cpufreq-dt driver binding
> documentation, otherwise I would have tried going this route.
>
> Do you have any references? I'd be happy to examine what would be
> necessary to go this route although, being an independent contributor,
> it may take time.
You wouldn't find in cpufreq-dt documentation as its not specific to
that. I have seen you DT patches now, and you have created the OPP
tables mostly correctly. Just create the cpufreq-platform device for
cpufreq-dt instead of arm-big-little one. And it should just work.
> > - I want Samsung's big LITTLE platforms to use cpufreq-dt and drop
> > arm_big_little driver completely.
>
> That sounds like a great direction going forward. However, I would still
> kindly request that you consider this series.
>
> The existence of future plans of course does not change the fact that
> users have real hardware today; hardware that they have spent money on
> and would like to use. Cpufreq support has already been deferred once
> for similar reasons of interface churn which essentially forestalled
> working functionality from entering the kernel by eight months; I'd
> really like to avoid having this happen again.
I am not talking about any future plans here that need some work to be
done. Its all working today, you just need to use a different driver.
> Sounds reasonable to me. However, I'd just like to reiterate that this
> line of work can be pursued independently from the upstreaming of this
> series.
I think this is the right time to upstream the right solution. Just
try it once, if you face lots of difficulties or issues, then we can
ofcourse see..
NOTE: Check how OPP nodes are required to be created now in
linux-next. They should be named like opp@<freq-hz>. Something I
noticed in your DTs.
--
viresh
On 03/12/15 06:05, Viresh Kumar wrote:
[...]
>
> @Sudeep: What would it take you to use cpufreq-dt for ARM's platforms
> ?
>
The main difference is that we get the OPPs from the firmware rather
than DT. We may just need to abstract that part and we should be able to
use it. I will have a look at it and get back to you will more details.
It has been a while since I looked at cpufreq-dt.
--
Regards,
Sudeep
Viresh Kumar <[email protected]> writes:
> On 03-12-15, 11:26, Ben Gamari wrote:
>> Viresh Kumar <[email protected]> writes:
>> > But, before I start reviewing this series, I have few comments.
>> > - We weren't able to use cpufreq-dt driver for big LITTLE platforms
>> > earlier, as it never had multi cluster support and we wanted
>> > clock-sharing information via DT.
>>
>> Fair enough.
>>
>> > - That is all fixed now.
>>
>> I did not see any mention of this in the cpufreq-dt driver binding
>> documentation, otherwise I would have tried going this route.
>>
>> Do you have any references? I'd be happy to examine what would be
>> necessary to go this route although, being an independent contributor,
>> it may take time.
>
> You wouldn't find in cpufreq-dt documentation as its not specific to
> that. I have seen you DT patches now, and you have created the OPP
> tables mostly correctly. Just create the cpufreq-platform device for
> cpufreq-dt instead of arm-big-little one. And it should just work.
>
Do you mean something along these lines? [1]
>> Sounds reasonable to me. However, I'd just like to reiterate that this
>> line of work can be pursued independently from the upstreaming of this
>> series.
>
> I think this is the right time to upstream the right solution. Just
> try it once, if you face lots of difficulties or issues, then we can
> ofcourse see..
>
Sure. I didn't realize things were so close to being functional. Thanks
for the hint. I'll give it a shot next time my XU4 is free.
> NOTE: Check how OPP nodes are required to be created now in
> linux-next. They should be named like opp@<freq-hz>. Something I
> noticed in your DTs.
>
I've fixed this in the branch.
Thanks again.
Cheers,
- Ben
[1] https://github.com/bgamari/linux/commit/285778aaff464d4dcf152f3e9e0df3d8c6909576
On 03-12-15, 11:05, Sudeep Holla wrote:
> The main difference is that we get the OPPs from the firmware rather
> than DT. We may just need to abstract that part and we should be able to
> use it. I will have a look at it and get back to you will more details.
> It has been a while since I looked at cpufreq-dt.
I forgot that :( .. but we can then create OPPs at runtime based on
what's available from firmware. And we also have an API now to set
which CPUs share OPPs... so that might be used as well..
--
viresh
On 03-12-15, 12:21, Ben Gamari wrote:
> Do you mean something along these lines? [1]
Yeah.
--
viresh
On Wed, 2015-12-02 at 22:19 +0100, Ben Gamari wrote:
> The frequency units are very confusing in this area as OPPs use Hz
> whereas cpufreq uses kHz. Be explicit about this in variable naming.
>
> Cc: Javier Martinez Canillas <[email protected]>
> Signed-off-by: Ben Gamari <[email protected]>
> ---
> drivers/cpufreq/arm_big_little.c | 20 ++++++++++----------
> 1 file changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
> index 855599b..2d5761c 100644
> --- a/drivers/cpufreq/arm_big_little.c
> +++ b/drivers/cpufreq/arm_big_little.c
> @@ -130,14 +130,14 @@ static unsigned int bL_cpufreq_get_rate(unsigned int cpu)
> }
>
> static int
> -bL_cpufreq_set_rate_cluster(u32 cpu, u32 cluster, u32 new_rate)
> +bL_cpufreq_set_rate_cluster(u32 cpu, u32 cluster, u32 new_rate_kHz)
> {
> unsigned long volt = 0, volt_old = 0;
> long freq_Hz;
> u32 old_rate;
IMO variable renaming doesn't seem necessary, if cpufreq uses kHz then
in a cpufreq driver adding 'kHz' to variable seems redundant, especially
if Hz values like freq_Hz above are named especially to signal their
different units. However, if renaming is going to happen it should at
least be consistent within the same function i.e. also rename the old
old_rate variable above.
> int ret;
>
> - freq_Hz = new_rate * 1000;
> + freq_Hz = new_rate_kHz * 1000;
> old_rate = clk_get_rate(clk[cluster]) / 1000;
>
> if (!IS_ERR(reg[cluster])) {
> @@ -163,10 +163,10 @@ bL_cpufreq_set_rate_cluster(u32 cpu, u32 cluster, u32 new_rate)
> pr_debug("%s: cpu %d, cluster: %d, %u MHz, %ld mV --> %u MHz, %ld mV\n",
> __func__, cpu, cluster,
> old_rate / 1000, (volt_old > 0) ? volt_old / 1000 : -1,
> - new_rate / 1000, volt ? volt / 1000 : -1);
> + new_rate_kHz / 1000, volt ? volt / 1000 : -1);
>
> /* scaling up? scale voltage before frequency */
> - if (!IS_ERR(reg[cluster]) && new_rate > old_rate) {
> + if (!IS_ERR(reg[cluster]) && new_rate_kHz > old_rate) {
> ret = regulator_set_voltage_tol(reg[cluster], volt, 0);
> if (ret) {
> pr_err("%s: cpu: %d, cluster: %d, failed to scale voltage up: %d\n",
> @@ -175,7 +175,7 @@ bL_cpufreq_set_rate_cluster(u32 cpu, u32 cluster, u32 new_rate)
> }
> }
>
> - ret = clk_set_rate(clk[cluster], new_rate * 1000);
> + ret = clk_set_rate(clk[cluster], new_rate_kHz * 1000);
> if (WARN_ON(ret)) {
> pr_err("%s: clk_set_rate failed: %d, cluster: %d\n",
> __func__, cluster, ret);
> @@ -185,7 +185,7 @@ bL_cpufreq_set_rate_cluster(u32 cpu, u32 cluster, u32 new_rate)
> }
>
> /* scaling down? scale voltage after frequency */
> - if (!IS_ERR(reg[cluster]) && new_rate < old_rate) {
> + if (!IS_ERR(reg[cluster]) && new_rate_kHz < old_rate) {
> ret = regulator_set_voltage_tol(reg[cluster], volt, 0);
> if (ret) {
> pr_err("%s: cpu: %d, cluster: %d, failed to scale voltage down: %d\n",
> @@ -199,7 +199,7 @@ bL_cpufreq_set_rate_cluster(u32 cpu, u32 cluster, u32 new_rate)
> }
>
> static unsigned int
> -bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
> +bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate_kHz)
> {
> u32 new_rate, prev_rate;
Ditto. Rename these too to add '_kHz' ?
> int ret;
> @@ -209,13 +209,13 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
>
> if (bLs) {
> prev_rate = per_cpu(cpu_last_req_freq, cpu);
> - per_cpu(cpu_last_req_freq, cpu) = rate;
> + per_cpu(cpu_last_req_freq, cpu) = rate_kHz;
> per_cpu(physical_cluster, cpu) = new_cluster;
>
> new_rate = find_cluster_maxfreq(new_cluster);
> new_rate = ACTUAL_FREQ(new_cluster, new_rate);
> } else {
> - new_rate = rate;
> + new_rate = rate_kHz;
> }
>
> pr_debug("%s: cpu: %d, old cluster: %d, new cluster: %d, freq: %d\n",
> @@ -236,7 +236,7 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
> } else if (ret && bLs) {
> per_cpu(cpu_last_req_freq, cpu) = prev_rate;
> per_cpu(physical_cluster, cpu) = old_cluster;
> - }
> + }
There's a spurious whitespace change here. I know the space you deleted
shouldn't have been there, but doing tidyups like that generally isn't
done in patches that don't otherwise affect the code in question.
>
> mutex_unlock(&cluster_lock[new_cluster]);
>
--
Tixy
"Jon Medhurst (Tixy)" <[email protected]> writes:
> On Wed, 2015-12-02 at 22:19 +0100, Ben Gamari wrote:
>> The frequency units are very confusing in this area as OPPs use Hz
>> whereas cpufreq uses kHz. Be explicit about this in variable naming.
>>
>> Cc: Javier Martinez Canillas <[email protected]>
>> Signed-off-by: Ben Gamari <[email protected]>
>> ---
>> drivers/cpufreq/arm_big_little.c | 20 ++++++++++----------
>> 1 file changed, 10 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
>> index 855599b..2d5761c 100644
>> --- a/drivers/cpufreq/arm_big_little.c
>> +++ b/drivers/cpufreq/arm_big_little.c
>> @@ -130,14 +130,14 @@ static unsigned int bL_cpufreq_get_rate(unsigned int cpu)
>> }
>>
>> static int
>> -bL_cpufreq_set_rate_cluster(u32 cpu, u32 cluster, u32 new_rate)
>> +bL_cpufreq_set_rate_cluster(u32 cpu, u32 cluster, u32 new_rate_kHz)
>> {
>> unsigned long volt = 0, volt_old = 0;
>> long freq_Hz;
>> u32 old_rate;
>
> IMO variable renaming doesn't seem necessary, if cpufreq uses kHz then
> in a cpufreq driver adding 'kHz' to variable seems redundant, especially
> if Hz values like freq_Hz above are named especially to signal their
> different units.
>
Correct; it isn't strictly necessary but it would have saved me half an
hour of poking around trying work out the intent of this code.
> However, if renaming is going to happen it should at
> least be consistent within the same function i.e. also rename the old
> old_rate variable above.
>
That's a reasonable objection. I'd be happy to do that.
snip
>> static unsigned int
>> -bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
>> +bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate_kHz)
>> {
>> u32 new_rate, prev_rate;
>
> Ditto. Rename these too to add '_kHz' ?
>
Sure.
>> int ret;
>> @@ -209,13 +209,13 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
>>
>> if (bLs) {
>> prev_rate = per_cpu(cpu_last_req_freq, cpu);
>> - per_cpu(cpu_last_req_freq, cpu) = rate;
>> + per_cpu(cpu_last_req_freq, cpu) = rate_kHz;
>> per_cpu(physical_cluster, cpu) = new_cluster;
>>
>> new_rate = find_cluster_maxfreq(new_cluster);
>> new_rate = ACTUAL_FREQ(new_cluster, new_rate);
>> } else {
>> - new_rate = rate;
>> + new_rate = rate_kHz;
>> }
>>
>> pr_debug("%s: cpu: %d, old cluster: %d, new cluster: %d, freq: %d\n",
>> @@ -236,7 +236,7 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
>> } else if (ret && bLs) {
>> per_cpu(cpu_last_req_freq, cpu) = prev_rate;
>> per_cpu(physical_cluster, cpu) = old_cluster;
>> - }
>> + }
>
> There's a spurious whitespace change here. I know the space you deleted
> shouldn't have been there, but doing tidyups like that generally isn't
> done in patches that don't otherwise affect the code in question.
>
Alright, I can drop that change.
Cheers,
- Ben
On 03.12.2015 19:30, Ben Gamari wrote:
> Krzysztof Kozlowski <[email protected]> writes:
>
>> On 03.12.2015 06:19, Ben Gamari wrote:
>>> From: Thomas Abraham <[email protected]>
>>>
>>> With the addition of the new Samsung specific cpu-clock type, the
>>> arm clock can be represented as a cpu-clock type. Add the CPU clock
>>> configuration data and instantiate the CPU clock type for Exynos5420.
>>>
>>> Changes by Bartlomiej:
>>> - split Exynos5420 support from the original patches
>>> - moved E5420_[EGL,KFC]_DIV0() macros to clk-exynos5420.c
>>>
>>> Changes by Ben Gamari:
>>> - Rebased
>>
>> If only rebasing then you should retain the Lukasz's review tag. He
>> doesn't have to review it again, right? :)
>
> Yep, very true.
>
>>> +static const struct exynos_cpuclk_cfg_data exynos5420_eglclk_d[] __initconst = {
>>> + { 1800000, E5420_EGL_DIV0(3, 7, 7, 4), },
>>> + { 1700000, E5420_EGL_DIV0(3, 7, 7, 3), },
>>> + { 1600000, E5420_EGL_DIV0(3, 7, 7, 3), },
>>> + { 1500000, E5420_EGL_DIV0(3, 7, 7, 3), },
>>> + { 1400000, E5420_EGL_DIV0(3, 7, 7, 3), },
>>> + { 1300000, E5420_EGL_DIV0(3, 7, 7, 2), },
>>> + { 1200000, E5420_EGL_DIV0(3, 7, 7, 2), },
>>> + { 1100000, E5420_EGL_DIV0(3, 7, 7, 2), },
>>> + { 1000000, E5420_EGL_DIV0(3, 6, 6, 2), },
>>> + { 900000, E5420_EGL_DIV0(3, 6, 6, 2), },
>>> + { 800000, E5420_EGL_DIV0(3, 5, 5, 2), },
>>> + { 700000, E5420_EGL_DIV0(3, 5, 5, 2), },
>>> + { 600000, E5420_EGL_DIV0(3, 4, 4, 2), },
>>> + { 500000, E5420_EGL_DIV0(3, 3, 3, 2), },
>>> + { 400000, E5420_EGL_DIV0(3, 3, 3, 2), },
>>> + { 300000, E5420_EGL_DIV0(3, 3, 3, 2), },
>>> + { 200000, E5420_EGL_DIV0(3, 3, 3, 2), },
>>> + { 0 },
>>
>> The vendor code (Galaxy S5 with Exynos5422) sets pclk_dbg divider to 7.
>> In the same time APLL divider is only 1.
>>
>> For the ACLK divider (of KFC below) the vendor sets 3, not 2.
>>
>> The values also don't match the Exynos5420 from Note 3.
>>
>> The Exynos5800 apparently has values more similar to 5422.
>>
>> The question is: for which exact model this is? We can of course choose
>> the safest values here but probably these would be with the highest
>> dividers?
>>
> I'm afraid I can't comment here. Thomas, perhaps you could offer some
> insight?
Actually I found your patch #5 adding support for 5800 with the values
more like matching 5422. So actually the difference should be between
5420 and 5422. The Exynos5420 mainline boards are:
- Peach Pit - chromeos tree could be a good vendor reference,
- Arndale Octa,
- SMDK5420.
For the last two I don't know where to get the vendor reference.
Unfortunately sometimes the particular values (supported frequencies and
clock dividers) differ for one SoC between products but we don't support
the ASV here.
Overall probably this means that we should not care about such details,
except maybe the difference between 5420 and 5422? (where 5422=5800)
Best regards,
Krzysztof
Viresh Kumar <[email protected]> writes:
> On 03-12-15, 11:26, Ben Gamari wrote:
>> Sounds reasonable to me. However, I'd just like to reiterate that this
>> line of work can be pursued independently from the upstreaming of this
>> series.
>
> I think this is the right time to upstream the right solution. Just
> try it once, if you face lots of difficulties or issues, then we can
> ofcourse see..
>
It looks like Bartlomiej has picked up this set. Regardless, while
tracking down various devicetree issues I noticed that the cpu-supply
and cpu%d-supply bindings appear to be completely undocumented. It
seem as though this ought to be fixed.
Cheers,
- Ben