linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: linux.amoon@gmail.com (Anand Moon)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 01/12] cpufreq: arm_big_little: add cluster regulator support
Date: Thu, 3 Dec 2015 10:11:52 +0530	[thread overview]
Message-ID: <CANAwSgTMzz-pVAT2z_2Oc2dv6UVUrDioBP5KBSuzOJWsy0z0GQ@mail.gmail.com> (raw)
In-Reply-To: <1449091167-20758-2-git-send-email-ben@smart-cactus.org>

Hi Ben Gamari,

On 3 December 2015 at 02:49, Ben Gamari <ben@smart-cactus.org> wrote:
> From: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
>
> 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 <kgene.kim@samsung.com>
> Cc: Doug Anderson <dianders@chromium.org>
> Cc: Javier Martinez Canillas <javier@osg.samsung.com>
> Cc: Andreas Faerber <afaerber@suse.de>
> Cc: Sachin Kamat <sachin.kamat@linaro.org>
> Cc: Thomas Abraham <thomas.ab@samsung.com>
> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> Signed-off-by: Ben Gamari <ben@smart-cactus.org>
> ---
>  .../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 at 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

  reply	other threads:[~2015-12-03  4:41 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-02 21:19 [PATCH v5 0/12] cpufreq: Add support for Exynos 5800, 5420, and 5422 Ben Gamari
2015-12-02 21:19 ` [PATCH 01/12] cpufreq: arm_big_little: add cluster regulator support Ben Gamari
2015-12-03  4:41   ` Anand Moon [this message]
2015-12-02 21:19 ` [PATCH 02/12] clk: samsung: exynos5420: add cpu clock configuration data and instantiate cpu clock Ben Gamari
2015-12-03  6:08   ` Krzysztof Kozlowski
2015-12-03 10:30     ` Ben Gamari
2015-12-04  2:25       ` Krzysztof Kozlowski
2015-12-02 21:19 ` [PATCH 03/12] ARM: dts: Exynos5420: add CPU OPP and regulator supply property Ben Gamari
2015-12-02 21:19 ` [PATCH 04/12] ARM: Exynos: use generic cpufreq driver for Exynos5420 Ben Gamari
2015-12-02 21:19 ` [PATCH 05/12] clk: samsung: exynos5800: fix cpu clock configuration data Ben Gamari
2015-12-02 21:19 ` [PATCH 06/12] ARM: dts: Exynos5800: fix CPU OPP Ben Gamari
2015-12-02 21:19 ` [PATCH 07/12] ARM: dts: Exynos5422: fix OPP tables Ben Gamari
2015-12-02 21:19 ` [PATCH 08/12] ARM: Exynos: use generic cpufreq driver for Exynos5800 Ben Gamari
2015-12-02 21:19 ` [PATCH 09/12] ARM: dts: Exynos5420/5800: add cluster regulator supply properties Ben Gamari
2015-12-02 21:19 ` [PATCH 10/12] cpufreq: arm-big-little: accept operating-points-v2 nodes Ben Gamari
2015-12-02 21:19 ` [PATCH 11/12] cpufreq: arm-big-little: clarify frequency units Ben Gamari
2015-12-03 14:22   ` Jon Medhurst (Tixy)
2015-12-03 14:37     ` Ben Gamari
2015-12-02 21:19 ` [PATCH 12/12] cpufreq: arm-big-little: warn on invalid regulator Ben Gamari
2015-12-03  6:05 ` [PATCH v5 0/12] cpufreq: Add support for Exynos 5800, 5420, and 5422 Viresh Kumar
2015-12-03 10:26   ` Ben Gamari
2015-12-03 10:37     ` Viresh Kumar
2015-12-03 11:21       ` Ben Gamari
2015-12-03 11:25         ` Viresh Kumar
2015-12-07 21:19       ` Ben Gamari
2015-12-03 11:05   ` Sudeep Holla
2015-12-03 11:24     ` Viresh Kumar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CANAwSgTMzz-pVAT2z_2Oc2dv6UVUrDioBP5KBSuzOJWsy0z0GQ@mail.gmail.com \
    --to=linux.amoon@gmail.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).