All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] arm: imx: remove unnecessary setting for DSM
@ 2014-12-09  5:28 Anson Huang
  2014-12-09  5:28 ` [PATCH 2/2] arm: imx: support arm power off in cpuidle for i.mx6sx Anson Huang
  2014-12-16  8:23 ` [PATCH 1/2] arm: imx: remove unnecessary setting for DSM Shawn Guo
  0 siblings, 2 replies; 4+ messages in thread
From: Anson Huang @ 2014-12-09  5:28 UTC (permalink / raw)
  To: linux-arm-kernel

Now we support DSM in OCRAM for all i.MX6 SoCs,
the resume entry point is set in asm code of
suspend-imx6.S, so no need to set the resume
entry point for SRC in pre-suspend flow.

Signed-off-by: Anson Huang <b20788@freescale.com>
---
 arch/arm/mach-imx/pm-imx6.c |    1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
index c653dd4..671e2a9 100644
--- a/arch/arm/mach-imx/pm-imx6.c
+++ b/arch/arm/mach-imx/pm-imx6.c
@@ -363,7 +363,6 @@ static int imx6q_pm_enter(suspend_state_t state)
 			imx6q_enable_rbc(true);
 		imx_gpc_pre_suspend(true);
 		imx_anatop_pre_suspend();
-		imx_set_cpu_jump(0, v7_cpu_resume);
 		/* Zzz ... */
 		cpu_suspend(0, imx6q_suspend_finish);
 		if (cpu_is_imx6q() || cpu_is_imx6dl())
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] arm: imx: support arm power off in cpuidle for i.mx6sx
  2014-12-09  5:28 [PATCH 1/2] arm: imx: remove unnecessary setting for DSM Anson Huang
@ 2014-12-09  5:28 ` Anson Huang
  2014-12-16  8:24   ` Shawn Guo
  2014-12-16  8:23 ` [PATCH 1/2] arm: imx: remove unnecessary setting for DSM Shawn Guo
  1 sibling, 1 reply; 4+ messages in thread
From: Anson Huang @ 2014-12-09  5:28 UTC (permalink / raw)
  To: linux-arm-kernel

This patch introduces an independent cpuidle driver for
i.MX6SX, and supports arm power off in idle, totally
3 levels of cpuidle are supported as below:

1. ARM WFI;
2. SOC in WAIT mode;
3. SOC in WAIT mode + ARM power off.

ARM power off can save at least 5mW power.

Signed-off-by: Anson Huang <b20788@freescale.com>
---
 arch/arm/mach-imx/Makefile         |    3 +-
 arch/arm/mach-imx/common.h         |    4 ++
 arch/arm/mach-imx/cpuidle-imx6sx.c |  107 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-imx/cpuidle.h        |    5 ++
 arch/arm/mach-imx/gpc.c            |   25 ++++++++-
 arch/arm/mach-imx/mach-imx6sx.c    |    2 +-
 arch/arm/mach-imx/pm-imx6.c        |    2 +-
 7 files changed, 142 insertions(+), 6 deletions(-)
 create mode 100644 arch/arm/mach-imx/cpuidle-imx6sx.c

diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index f5ac685..8d1b101 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -32,8 +32,7 @@ ifeq ($(CONFIG_CPU_IDLE),y)
 obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o
 obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o
 obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o
-# i.MX6SX reuses i.MX6Q cpuidle driver
-obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6q.o
+obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6sx.o
 endif
 
 ifdef CONFIG_SND_IMX_SOC
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 59ce8f3..b0da5e9 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -70,6 +70,10 @@ void imx_set_soc_revision(unsigned int rev);
 unsigned int imx_get_soc_revision(void);
 void imx_init_revision_from_anatop(void);
 struct device *imx_soc_device_init(void);
+void imx6q_enable_rbc(bool enable);
+void imx_gpc_set_arm_power_in_lpm(bool power_off);
+void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw);
+void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw);
 
 enum mxc_cpu_pwr_mode {
 	WAIT_CLOCKED,		/* wfi only */
diff --git a/arch/arm/mach-imx/cpuidle-imx6sx.c b/arch/arm/mach-imx/cpuidle-imx6sx.c
new file mode 100644
index 0000000..58106cc
--- /dev/null
+++ b/arch/arm/mach-imx/cpuidle-imx6sx.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/cpuidle.h>
+#include <linux/cpu_pm.h>
+#include <linux/module.h>
+#include <asm/cpuidle.h>
+#include <asm/proc-fns.h>
+#include <asm/suspend.h>
+
+#include "common.h"
+#include "cpuidle.h"
+
+static int imx6sx_idle_finish(unsigned long val)
+{
+	cpu_do_idle();
+
+	return 0;
+}
+
+static int imx6sx_enter_wait(struct cpuidle_device *dev,
+			    struct cpuidle_driver *drv, int index)
+{
+	imx6q_set_lpm(WAIT_UNCLOCKED);
+
+	switch (index) {
+	case 1:
+		cpu_do_idle();
+		break;
+	case 2:
+		imx6q_enable_rbc(true);
+		imx_gpc_set_arm_power_in_lpm(true);
+		imx_set_cpu_jump(0, v7_cpu_resume);
+		/* Need to notify there is a cpu pm operation. */
+		cpu_pm_enter();
+		cpu_cluster_pm_enter();
+
+		cpu_suspend(0, imx6sx_idle_finish);
+
+		cpu_cluster_pm_exit();
+		cpu_pm_exit();
+		imx_gpc_set_arm_power_in_lpm(false);
+		imx6q_enable_rbc(false);
+		break;
+	default:
+		break;
+	}
+
+	imx6q_set_lpm(WAIT_CLOCKED);
+
+	return index;
+}
+
+static struct cpuidle_driver imx6sx_cpuidle_driver = {
+	.name = "imx6sx_cpuidle",
+	.owner = THIS_MODULE,
+	.states = {
+		/* WFI */
+		ARM_CPUIDLE_WFI_STATE,
+		/* WAIT */
+		{
+			.exit_latency = 50,
+			.target_residency = 75,
+			.flags = CPUIDLE_FLAG_TIME_VALID |
+				CPUIDLE_FLAG_TIMER_STOP,
+			.enter = imx6sx_enter_wait,
+			.name = "WAIT",
+			.desc = "Clock off",
+		},
+		/* WAIT + ARM power off  */
+		{
+			/*
+			 * ARM gating 31us * 5 + RBC clear 65us
+			 * and some margin for SW execution, here set it
+			 * to 300us.
+			 */
+			.exit_latency = 300,
+			.target_residency = 500,
+			.flags = CPUIDLE_FLAG_TIME_VALID,
+			.enter = imx6sx_enter_wait,
+			.name = "LOW-POWER-IDLE",
+			.desc = "ARM power off",
+		},
+	},
+	.state_count = 3,
+	.safe_state_index = 0,
+};
+
+int __init imx6sx_cpuidle_init(void)
+{
+	imx6q_enable_rbc(false);
+	/*
+	 * set ARM power up/down timing to the fastest,
+	 * sw2iso and sw can be set to one 32K cycle = 31us
+	 * except for power up sw2iso which need to be
+	 * larger than LDO ramp up time.
+	 */
+	imx_gpc_set_arm_power_up_timing(2, 1);
+	imx_gpc_set_arm_power_down_timing(1, 1);
+
+	return cpuidle_register(&imx6sx_cpuidle_driver, NULL);
+}
diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h
index 24e3367..f914012 100644
--- a/arch/arm/mach-imx/cpuidle.h
+++ b/arch/arm/mach-imx/cpuidle.h
@@ -14,6 +14,7 @@
 extern int imx5_cpuidle_init(void);
 extern int imx6q_cpuidle_init(void);
 extern int imx6sl_cpuidle_init(void);
+extern int imx6sx_cpuidle_init(void);
 #else
 static inline int imx5_cpuidle_init(void)
 {
@@ -27,4 +28,8 @@ static inline int imx6sl_cpuidle_init(void)
 {
 	return 0;
 }
+static inline int imx6sx_cpuidle_init(void)
+{
+	return 0;
+}
 #endif
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 82ea74e..5fa43d2 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -20,6 +20,10 @@
 
 #define GPC_IMR1		0x008
 #define GPC_PGC_CPU_PDN		0x2a0
+#define GPC_PGC_CPU_PUPSCR	0x2a4
+#define GPC_PGC_CPU_PDNSCR	0x2a8
+#define GPC_PGC_SW2ISO_SHIFT	0x8
+#define GPC_PGC_SW_SHIFT	0x0
 
 #define IMR_NUM			4
 
@@ -27,6 +31,23 @@ static void __iomem *gpc_base;
 static u32 gpc_wake_irqs[IMR_NUM];
 static u32 gpc_saved_imrs[IMR_NUM];
 
+void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw)
+{
+	writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) |
+		(sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PUPSCR);
+}
+
+void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw)
+{
+	writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) |
+		(sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PDNSCR);
+}
+
+void imx_gpc_set_arm_power_in_lpm(bool power_off)
+{
+	writel_relaxed(power_off, gpc_base + GPC_PGC_CPU_PDN);
+}
+
 void imx_gpc_pre_suspend(bool arm_power_off)
 {
 	void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
@@ -34,7 +55,7 @@ void imx_gpc_pre_suspend(bool arm_power_off)
 
 	/* Tell GPC to power off ARM core when suspend */
 	if (arm_power_off)
-		writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
+		imx_gpc_set_arm_power_in_lpm(arm_power_off);
 
 	for (i = 0; i < IMR_NUM; i++) {
 		gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
@@ -48,7 +69,7 @@ void imx_gpc_post_resume(void)
 	int i;
 
 	/* Keep ARM core powered on for other low-power modes */
-	writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN);
+	imx_gpc_set_arm_power_in_lpm(false);
 
 	for (i = 0; i < IMR_NUM; i++)
 		writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c
index 7a96c65..66988eb 100644
--- a/arch/arm/mach-imx/mach-imx6sx.c
+++ b/arch/arm/mach-imx/mach-imx6sx.c
@@ -90,7 +90,7 @@ static void __init imx6sx_init_irq(void)
 
 static void __init imx6sx_init_late(void)
 {
-	imx6q_cpuidle_init();
+	imx6sx_cpuidle_init();
 
 	if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
 		platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0);
diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
index 671e2a9..cab80e2 100644
--- a/arch/arm/mach-imx/pm-imx6.c
+++ b/arch/arm/mach-imx/pm-imx6.c
@@ -205,7 +205,7 @@ void imx6q_set_int_mem_clk_lpm(bool enable)
 	writel_relaxed(val, ccm_base + CGPR);
 }
 
-static void imx6q_enable_rbc(bool enable)
+void imx6q_enable_rbc(bool enable)
 {
 	u32 val;
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 1/2] arm: imx: remove unnecessary setting for DSM
  2014-12-09  5:28 [PATCH 1/2] arm: imx: remove unnecessary setting for DSM Anson Huang
  2014-12-09  5:28 ` [PATCH 2/2] arm: imx: support arm power off in cpuidle for i.mx6sx Anson Huang
@ 2014-12-16  8:23 ` Shawn Guo
  1 sibling, 0 replies; 4+ messages in thread
From: Shawn Guo @ 2014-12-16  8:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Dec 09, 2014 at 01:28:38PM +0800, Anson Huang wrote:
> Now we support DSM in OCRAM for all i.MX6 SoCs,
> the resume entry point is set in asm code of
> suspend-imx6.S, so no need to set the resume
> entry point for SRC in pre-suspend flow.
> 
> Signed-off-by: Anson Huang <b20788@freescale.com>

Again, change "arm: " to "ARM: " please, as I want to keep it consistent
for all IMX patches I collect.

Shawn

> ---
>  arch/arm/mach-imx/pm-imx6.c |    1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
> index c653dd4..671e2a9 100644
> --- a/arch/arm/mach-imx/pm-imx6.c
> +++ b/arch/arm/mach-imx/pm-imx6.c
> @@ -363,7 +363,6 @@ static int imx6q_pm_enter(suspend_state_t state)
>  			imx6q_enable_rbc(true);
>  		imx_gpc_pre_suspend(true);
>  		imx_anatop_pre_suspend();
> -		imx_set_cpu_jump(0, v7_cpu_resume);
>  		/* Zzz ... */
>  		cpu_suspend(0, imx6q_suspend_finish);
>  		if (cpu_is_imx6q() || cpu_is_imx6dl())
> -- 
> 1.7.9.5
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 2/2] arm: imx: support arm power off in cpuidle for i.mx6sx
  2014-12-09  5:28 ` [PATCH 2/2] arm: imx: support arm power off in cpuidle for i.mx6sx Anson Huang
@ 2014-12-16  8:24   ` Shawn Guo
  0 siblings, 0 replies; 4+ messages in thread
From: Shawn Guo @ 2014-12-16  8:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Dec 09, 2014 at 01:28:39PM +0800, Anson Huang wrote:
> This patch introduces an independent cpuidle driver for
> i.MX6SX, and supports arm power off in idle, totally
> 3 levels of cpuidle are supported as below:
> 
> 1. ARM WFI;
> 2. SOC in WAIT mode;
> 3. SOC in WAIT mode + ARM power off.
> 
> ARM power off can save at least 5mW power.
> 
> Signed-off-by: Anson Huang <b20788@freescale.com>

Looks pretty nice, except one small comment below.

> ---
>  arch/arm/mach-imx/Makefile         |    3 +-
>  arch/arm/mach-imx/common.h         |    4 ++
>  arch/arm/mach-imx/cpuidle-imx6sx.c |  107 ++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-imx/cpuidle.h        |    5 ++
>  arch/arm/mach-imx/gpc.c            |   25 ++++++++-
>  arch/arm/mach-imx/mach-imx6sx.c    |    2 +-
>  arch/arm/mach-imx/pm-imx6.c        |    2 +-
>  7 files changed, 142 insertions(+), 6 deletions(-)
>  create mode 100644 arch/arm/mach-imx/cpuidle-imx6sx.c

...

> --- a/arch/arm/mach-imx/pm-imx6.c
> +++ b/arch/arm/mach-imx/pm-imx6.c
> @@ -205,7 +205,7 @@ void imx6q_set_int_mem_clk_lpm(bool enable)
>  	writel_relaxed(val, ccm_base + CGPR);
>  }
>  
> -static void imx6q_enable_rbc(bool enable)
> +void imx6q_enable_rbc(bool enable)

We may want to take the chance to rename it to imx6_enable_rbc().

Shawn

>  {
>  	u32 val;
>  
> -- 
> 1.7.9.5
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2014-12-16  8:24 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-12-09  5:28 [PATCH 1/2] arm: imx: remove unnecessary setting for DSM Anson Huang
2014-12-09  5:28 ` [PATCH 2/2] arm: imx: support arm power off in cpuidle for i.mx6sx Anson Huang
2014-12-16  8:24   ` Shawn Guo
2014-12-16  8:23 ` [PATCH 1/2] arm: imx: remove unnecessary setting for DSM Shawn Guo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.