linux-pm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Daniel Lezcano <daniel.lezcano@linaro.org>
To: Barry Song <21cnbao@gmail.com>, rjw@sisk.pl
Cc: linux-pm@vger.kernel.org, workgroup.linux@csr.com,
	Rongjun Ying <Rongjun.Ying@csr.com>,
	Barry Song <Baohua.Song@csr.com>
Subject: Re: [PATCH] cpuidle: sirf : Add cpuidle for SiRFprimaII and SiRFatlasVI
Date: Mon, 07 Oct 2013 10:23:39 +0200	[thread overview]
Message-ID: <52526F8B.6030905@linaro.org> (raw)
In-Reply-To: <1381033577-19818-1-git-send-email-Baohua.Song@csr.com>


Hi Barry,

On 10/06/2013 06:26 AM, Barry Song wrote:
> From: Rongjun Ying <Rongjun.Ying@csr.com>
>
> This patch adds support cpuidle for CSR SiRFprimaII and SiRFatlasVI unicore
> ARM Cortex-A9 SoCs.

A new driver deserves a better description.

> Signed-off-by: Rongjun Ying <Rongjun.Ying@csr.com>
> Signed-off-by: Barry Song <Baohua.Song@csr.com>
> ---

Is there a technical reference manual accessible somewhere ?

>   - this patch depens on  Rongjun Ying's "[PATCH] cpufreq: sirf: Add cpufreq
>   for SiRFprimaII and SiRFatlasVI" at:
>   http://marc.info/?l=linux-pm&m=138103042106089&w=2
>
>   arch/arm/configs/prima2_defconfig |   2 +
>   drivers/cpuidle/Kconfig.arm       |   6 ++
>   drivers/cpuidle/Makefile          |   1 +
>   drivers/cpuidle/cpuidle-sirf.c    | 131 ++++++++++++++++++++++++++++++++++++++
>   4 files changed, 140 insertions(+)
>   create mode 100644 drivers/cpuidle/cpuidle-sirf.c
>
> diff --git a/arch/arm/configs/prima2_defconfig b/arch/arm/configs/prima2_defconfig
> index 513d75e..bc0bf1f 100644
> --- a/arch/arm/configs/prima2_defconfig
> +++ b/arch/arm/configs/prima2_defconfig
> @@ -18,6 +18,8 @@ CONFIG_PREEMPT=y
>   CONFIG_AEABI=y
>   CONFIG_KEXEC=y
>   CONFIG_CPU_FREQ=y
> +CONFIG_CPU_IDLE=y
> +CONFIG_ARM_SIRF_CPUIDLE=y
>   CONFIG_BINFMT_MISC=y
>   CONFIG_PM_RUNTIME=y
>   CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
> diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
> index 8e36603..c1f5fbf 100644
> --- a/drivers/cpuidle/Kconfig.arm
> +++ b/drivers/cpuidle/Kconfig.arm
> @@ -15,6 +15,12 @@ config ARM_KIRKWOOD_CPUIDLE
>   	help
>   	  This adds the CPU Idle driver for Marvell Kirkwood SoCs.
>
> +config ARM_SIRF_CPUIDLE
> +	bool "CPU Idle Driver for CSR SiRFprimaII and CSRatlasVI SoCs"
> +	depends on ARCH_SIRF
> +	help
> +	  This adds the CPU Idle driver for CSR SiRF SoCs.
> +
>   config ARM_ZYNQ_CPUIDLE
>   	bool "CPU Idle Driver for Xilinx Zynq processors"
>   	depends on ARCH_ZYNQ
> diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
> index cea5ef5..f8cce16 100644
> --- a/drivers/cpuidle/Makefile
> +++ b/drivers/cpuidle/Makefile
> @@ -9,6 +9,7 @@ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
>   # ARM SoC drivers
>   obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE)	+= cpuidle-calxeda.o
>   obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE)	+= cpuidle-kirkwood.o
> +obj-$(CONFIG_ARM_SIRF_CPUIDLE)		+= cpuidle-sirf.o
>   obj-$(CONFIG_ARM_ZYNQ_CPUIDLE)		+= cpuidle-zynq.o
>   obj-$(CONFIG_ARM_U8500_CPUIDLE)         += cpuidle-ux500.o
>   obj-$(CONFIG_CPU_IDLE_BIG_LITTLE)	+= cpuidle-big_little.o
> diff --git a/drivers/cpuidle/cpuidle-sirf.c b/drivers/cpuidle/cpuidle-sirf.c
> new file mode 100644
> index 0000000..fc1f71e
> --- /dev/null
> +++ b/drivers/cpuidle/cpuidle-sirf.c
> @@ -0,0 +1,131 @@
> +/*
> + * CPU idle drivers for CSR SiRFprimaII
> + *
> + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
> + *
> + * Licensed under GPLv2 or later.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/cpuidle.h>
> +#include <linux/io.h>
> +#include <linux/time.h>
> +#include <asm/proc-fns.h>
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <asm/cpuidle.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/cpu.h>
> +#include <linux/opp.h>
> +
> +#define SIRFSOC_MAX_VOLTAGE	1200000
> +
> +/*
> + * now we have only 2 C state WFI
> + * 1. ARM WFI
> + * 2. WFI + switch to 26Mhz clock source + lower volatge
> + */
> +
> +static struct {
> +	struct clk		*cpu_clk;
> +	struct clk		*osc_clk;
> +	struct regulator	*vcore_regulator;
> +	struct device		*cpu_dev;
> +} sirf_cpuidle;
> +
> +static int sirf_enter_idle(struct cpuidle_device *dev,
> +				struct cpuidle_driver *drv,
> +				int index)
> +{
> +	struct clk *parent_clk;
> +	unsigned long volt_old = 0, volt_new, freq;
> +	struct opp *opp;
> +
> +	local_irq_disable();

Don't use local_irq_disable in the driver it is done by the caller.

> +	parent_clk = clk_get_parent(sirf_cpuidle.cpu_clk);
> +	clk_set_parent(sirf_cpuidle.cpu_clk, sirf_cpuidle.osc_clk);
> +
> +	if (sirf_cpuidle.vcore_regulator) {
> +		volt_old = regulator_get_voltage(sirf_cpuidle.vcore_regulator);
> +
> +		freq = clk_get_rate(sirf_cpuidle.osc_clk);
> +		rcu_read_lock();

Using rcu in the idle path is not allowed.

> +		opp = opp_find_freq_ceil(sirf_cpuidle.cpu_dev, &freq);
> +		if (IS_ERR(opp)) {
> +			rcu_read_unlock();
> +			return -EINVAL;
> +		}
> +
> +		volt_new = opp_get_voltage(opp);
> +		rcu_read_unlock();
> +
> +		regulator_set_voltage(sirf_cpuidle.vcore_regulator, volt_new,
> +				SIRFSOC_MAX_VOLTAGE);
> +	}
> +	/* Wait for interrupt state */
> +	cpu_do_idle();
> +
> +	if (sirf_cpuidle.vcore_regulator)
> +		regulator_set_voltage(sirf_cpuidle.vcore_regulator, volt_old,
> +				SIRFSOC_MAX_VOLTAGE);
> +
> +	clk_set_parent(sirf_cpuidle.cpu_clk, parent_clk);
> +	/* Todo: other C states */

It sounds very weird you have this freq/volt/opp code here.

If you hit idle, the cpufreq driver didn't put the cpu in the state you 
are trying to bring here ?

There isn't a power management unit on this board ?

> +	local_irq_enable();

Done by the caller.

> +	return index;
> +}
> +
> +static struct cpuidle_driver sirf_cpuidle_driver = {
> +	.name = "sirf_cpuidle",
> +	.states = {
> +		ARM_CPUIDLE_WFI_STATE,
> +		{
> +			.name = "WFI-LP",
> +			.desc = "WFI low power",
> +			.flags = CPUIDLE_FLAG_TIME_VALID,
> +			.exit_latency = 10,
> +			.target_residency = 10000,
> +			.enter = sirf_enter_idle,
> +		},
> +	},
> +	.state_count = 2,
> +};
> +
> +/* Initialize CPU idle by registering the idle states */
> +static int sirfsoc_init_cpuidle(void)
> +{
> +	int ret = 0;
> +
> +	sirf_cpuidle.cpu_clk = clk_get_sys("cpu", NULL);
> +	if (IS_ERR(sirf_cpuidle.cpu_clk))
> +		return PTR_ERR(sirf_cpuidle.cpu_clk);
> +
> +	sirf_cpuidle.osc_clk = clk_get_sys("osc", NULL);
> +	if (IS_ERR(sirf_cpuidle.osc_clk)) {
> +		ret = PTR_ERR(sirf_cpuidle.osc_clk);
> +		goto out_put_osc_clk;
> +	}
> +
> +	sirf_cpuidle.vcore_regulator = regulator_get(NULL, "vcore");
> +	if (IS_ERR(sirf_cpuidle.vcore_regulator))
> +		sirf_cpuidle.vcore_regulator = NULL;
> +
> +	sirf_cpuidle.cpu_dev = get_cpu_device(0);
> +	if (IS_ERR(sirf_cpuidle.cpu_dev)) {
> +		ret = PTR_ERR(sirf_cpuidle.cpu_dev);
> +		goto out_put_clk;
> +	}
> +
> +	ret = cpuidle_register(&sirf_cpuidle_driver, NULL);
> +	if (!ret)
> +		return ret;
> +
> +out_put_clk:
> +	clk_put(sirf_cpuidle.cpu_clk);
> +out_put_osc_clk:
> +	clk_put(sirf_cpuidle.osc_clk);
> +	return ret;
> +}
> +late_initcall(sirfsoc_init_cpuidle);

Please convert it to platform_driver as the other drivers are moving to 
(cf. cpuidle-kirkwood, cpuidle-ux500).

Thanks
   -- Daniel

-- 
  <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog


  reply	other threads:[~2013-10-07  8:23 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-06  4:26 [PATCH] cpuidle: sirf : Add cpuidle for SiRFprimaII and SiRFatlasVI Barry Song
2013-10-07  8:23 ` Daniel Lezcano [this message]
2013-10-08  7:44   ` 答复: " Rongjun Ying
2013-10-08 10:23     ` Daniel Lezcano
2013-10-08 13:27       ` Barry Song
2013-10-09 12:09         ` Daniel Lezcano
2013-10-10 10:24           ` Barry Song
2013-10-10 10:57             ` Daniel Lezcano
2013-10-10 13:07               ` Barry Song
2013-10-10 13:58                 ` Daniel Lezcano

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=52526F8B.6030905@linaro.org \
    --to=daniel.lezcano@linaro.org \
    --cc=21cnbao@gmail.com \
    --cc=Baohua.Song@csr.com \
    --cc=Rongjun.Ying@csr.com \
    --cc=linux-pm@vger.kernel.org \
    --cc=rjw@sisk.pl \
    --cc=workgroup.linux@csr.com \
    /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).