From mboxrd@z Thu Jan 1 00:00:00 1970 From: linux@arm.linux.org.uk (Russell King - ARM Linux) Date: Fri, 26 Aug 2011 09:19:14 +0100 Subject: [PATCH 2/2] Adding support for the plat-mxc cpuidle driver to mach-mx5. Tested on i.MX51 Babbage board with ARM core running at 800Mhz. Idle OS ARM core power before patch = ~400mW. Idle OS ARM core power after patch = ~1.25mW. In-Reply-To: <1314325995-29118-2-git-send-email-rob.lee@linaro.org> References: <1314325995-29118-1-git-send-email-rob.lee@linaro.org> <1314325995-29118-2-git-send-email-rob.lee@linaro.org> Message-ID: <20110826081914.GB11250@n2100.arm.linux.org.uk> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org > Subject: [PATCH 2/2] Adding support for the plat-mxc cpuidle driver to > mach-mx5. Tested on i.MX51 Babbage board with ARM core running > at 800Mhz. Idle OS ARM core power before patch = ~400mW. Idle > OS ARM core power after patch = ~1.25mW. Please don't type your entire message into the subject line box. The subject line box is supposed to be a short summary of the patch, normally less than 72 characters long. On Thu, Aug 25, 2011 at 09:33:15PM -0500, Robert Lee wrote: > Signed-off-by: Robert Lee > --- > arch/arm/mach-mx5/Kconfig | 4 ++ > arch/arm/mach-mx5/include/mach/cpuidle.h | 45 ++++++++++++++++++++++++++++++ > arch/arm/mach-mx5/system.c | 42 ++++++++++++++++++++++++++++ > 3 files changed, 91 insertions(+), 0 deletions(-) > create mode 100644 arch/arm/mach-mx5/include/mach/cpuidle.h > > diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig > index b4e7c58..1672cfe 100644 > --- a/arch/arm/mach-mx5/Kconfig > +++ b/arch/arm/mach-mx5/Kconfig > @@ -19,6 +19,7 @@ config SOC_IMX50 > select ARCH_MXC_IOMUX_V3 > select ARCH_MXC_AUDMUX_V2 > select ARCH_HAS_CPUFREQ > + select ARCH_HAS_CPUIDLE > select ARCH_MX5 > select ARCH_MX50 > > @@ -30,6 +31,7 @@ config SOC_IMX51 > select ARCH_MXC_IOMUX_V3 > select ARCH_MXC_AUDMUX_V2 > select ARCH_HAS_CPUFREQ > + select ARCH_HAS_CPUIDLE > select ARCH_MX5 > > config SOC_IMX53 > @@ -38,9 +40,11 @@ config SOC_IMX53 > select ARM_L1_CACHE_SHIFT_6 > select MXC_TZIC > select ARCH_MXC_IOMUX_V3 > + select ARCH_HAS_CPUIDLE > select ARCH_MX5 > select ARCH_MX53 > > + > if ARCH_MX50_SUPPORTED > #comment "i.MX50 machines:" > > diff --git a/arch/arm/mach-mx5/include/mach/cpuidle.h b/arch/arm/mach-mx5/include/mach/cpuidle.h > new file mode 100644 > index 0000000..6c37963 > --- /dev/null > +++ b/arch/arm/mach-mx5/include/mach/cpuidle.h > @@ -0,0 +1,45 @@ > +/* > + * This file is licensed under the terms of the GNU General Public > + * License version 2. This program is licensed "as is" without any > + * warranty of any kind, whether express or implied. > + */ > + > +#ifndef __ARCH_ARM_PLAT_MXC_CPUIDLE_H__ > +#define __ARCH_ARM_PLAT_MXC_CPUIDLE_H__ > + > + > +/* CPUIDLE state parameters: name, description, exit_latency (us) > + * exit_latencies were tested using i.MX51 running at 160MHz P-state > + * for worst case latencies as to not cause a pm_qos violation when > + * running at lower speeds. > + */ > +#define MXC_CPUIDLE_TABLE {\ > +MXC_X_MACRO(POWERED_CLOCKED, "idle cpu clocked, powered.", 12),\ > +MXC_X_MACRO(POWERED_NOCLOCK, "idle cpu powered, unclocked.", 14),\ > +MXC_X_MACRO(NOPOWER_NOCLOCK, "idle cpu unpowered, unclocked.", 20),\ > +MXC_X_MACRO(MXC_NUM_CPUIDLE_STATES, "", -1)} > + > +#define MXC_X_MACRO(a, b, c) a > +enum MXC_CPUIDLE_STATE_NAME MXC_CPUIDLE_TABLE; > +#undef MXC_X_MACRO > + > +struct imx_cpuidle_params { > + unsigned int latency; > +}; > + > +void imx_cpu_do_idle(int cpuidle_state_num); > + > +/* if you want to override the mach level params at the board level, > + * define MXC_OVERRIDE_CPUIDLE_PARAMS and pass your board level paramaters > + * into the imx_cpuidle_board_params function */ > + > +/* #define MXC_OVERRIDE_DEFAULT_CPUIDLE_PARAMS */ > + > +#ifdef CONFIG_MXC_CPUIDLE > +extern void imx_cpuidle_board_params(struct imx_cpuidle_params *cpuidle_params); > +#else > +inline void imx_cpuidle_board_params(struct imx_cpuidle_params *cpuidle_params) > +{} > +#endif > + > +#endif /* #ifndef __ARCH_ARM_PLAT_MXC_CPUIDLE_H__ */ > diff --git a/arch/arm/mach-mx5/system.c b/arch/arm/mach-mx5/system.c > index 76ae8dc..6ff938d 100644 > --- a/arch/arm/mach-mx5/system.c > +++ b/arch/arm/mach-mx5/system.c > @@ -12,9 +12,16 @@ > */ > #include > #include > +#include > +#include > #include > +#include > +#include > #include "crm_regs.h" > > +static int arch_idle_mode = WAIT_UNCLOCKED_POWER_OFF; > +static struct clk *gpc_dvfs_clk; > + > /* set cpu low power mode before WFI instruction. This function is called > * mx5 because it can be used for mx50, mx51, and mx53.*/ > void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode) > @@ -82,3 +89,38 @@ void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode) > __raw_writel(empgc1, MXC_SRPG_EMPGC1_SRPGCR); > } > } > + > +void imx_cpu_do_idle(int cpuidle_state_num) > +{ > + > + int local_arch_idle_mode = arch_idle_mode; > + > + if (gpc_dvfs_clk == NULL) > + gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs_clk"); > + /* gpc clock is needed for SRPG */ > + clk_enable(gpc_dvfs_clk); > + > + /* convert MXC_CPUIDLE_STATE_NAME to mxc_cpu_pwr_mode. */ > + switch (cpuidle_state_num) { > + case POWERED_CLOCKED: > + local_arch_idle_mode = WAIT_CLOCKED; > + break; > + case POWERED_NOCLOCK: > + local_arch_idle_mode = WAIT_UNCLOCKED; > + break; > + case NOPOWER_NOCLOCK: > + local_arch_idle_mode = WAIT_UNCLOCKED_POWER_OFF; > + break; > + default: > + break; > + } > + /* prepare registers for upcoming idle mode */ > + mx5_cpu_lp_set(local_arch_idle_mode); > + > + /* enter wfi state which on i.MX5 can trigger */ > + cpu_do_idle(); > + > + clk_disable(gpc_dvfs_clk); > +} > + > + > -- > 1.7.1 > > > _______________________________________________ > linux-arm-kernel mailing list > linux-arm-kernel at lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel