Re: [PATCH 01/12] cpufreq: arm_big_little: add cluster regulator support

2015-12-02 Thread Anand Moon
Hi Ben Gamari,

On 3 December 2015 at 02:49, Ben Gamari  wrote:
> From: Bartlomiej Zolnierkiewicz 
>
> 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 
> Cc: Doug Anderson 
> Cc: Javier Martinez Canillas 
> Cc: Andreas Faerber 
> Cc: Sachin Kamat 
> Cc: Thomas Abraham 
> Signed-off-by: Bartlomiej Zolnierkiewicz 
> Signed-off-by: Ben Gamari 
> ---
>  .../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 
>  #include 
>  #include 
> +#include 
>
>  #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], _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: 

[PATCH 01/12] cpufreq: arm_big_little: add cluster regulator support

2015-12-02 Thread Ben Gamari
From: Bartlomiej Zolnierkiewicz 

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 
Cc: Doug Anderson 
Cc: Javier Martinez Canillas 
Cc: Andreas Faerber 
Cc: Sachin Kamat 
Cc: Thomas Abraham 
Signed-off-by: Bartlomiej Zolnierkiewicz 
Signed-off-by: Ben Gamari 
---
 .../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 
 #include 
 #include 
+#include 
 
 #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], _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
 

[PATCH 01/12] cpufreq: arm_big_little: add cluster regulator support

2015-12-02 Thread Ben Gamari
From: Bartlomiej Zolnierkiewicz 

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 
Cc: Doug Anderson 
Cc: Javier Martinez Canillas 
Cc: Andreas Faerber 
Cc: Sachin Kamat 
Cc: Thomas Abraham 
Signed-off-by: Bartlomiej Zolnierkiewicz 
Signed-off-by: Ben Gamari 
---
 .../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 
 #include 
 #include 
+#include 
 
 #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], _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, 

Re: [PATCH 01/12] cpufreq: arm_big_little: add cluster regulator support

2015-12-02 Thread Anand Moon
Hi Ben Gamari,

On 3 December 2015 at 02:49, Ben Gamari  wrote:
> From: Bartlomiej Zolnierkiewicz 
>
> 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 
> Cc: Doug Anderson 
> Cc: Javier Martinez Canillas 
> Cc: Andreas Faerber 
> Cc: Sachin Kamat 
> Cc: Thomas Abraham 
> Signed-off-by: Bartlomiej Zolnierkiewicz 
> Signed-off-by: Ben Gamari 
> ---
>  .../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 
>  #include 
>  #include 
> +#include 
>
>  #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], _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