linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: hechtb@gmail.com (Bastian Hecht)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH] ARM: shmobile: r8a7740: Add CPU Core Standby Mode
Date: Mon,  4 Mar 2013 18:54:05 +0100	[thread overview]
Message-ID: <1362419645-3116-2-git-send-email-hechtb+renesas@gmail.com> (raw)
In-Reply-To: <1362419645-3116-1-git-send-email-hechtb+renesas@gmail.com>

In system CPU core standby mode, the cache in the system CPU enters RAM standby
state and the power supply to the system CPU logic is turned off. The on-chip
peripheral modules in the system block continue to operate in sleep mode.

We use this mode as the suspend-to-memory mechanism.

Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
---
 arch/arm/mach-shmobile/Makefile              |    2 +-
 arch/arm/mach-shmobile/include/mach/common.h |    1 +
 arch/arm/mach-shmobile/pm-r8a7740.c          |   63 ++++++++++++++++++-
 arch/arm/mach-shmobile/sleep-r8a7740.S       |   83 ++++++++++++++++++++++++++
 4 files changed, 146 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/mach-shmobile/sleep-r8a7740.S

diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index c621edf..1206a6d 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -27,7 +27,7 @@ obj-$(CONFIG_SUSPEND)		+= suspend.o
 obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o
 obj-$(CONFIG_ARCH_SHMOBILE)	+= pm-rmobile.o
 obj-$(CONFIG_ARCH_SH7372)	+= pm-sh7372.o sleep-sh7372.o
-obj-$(CONFIG_ARCH_R8A7740)	+= pm-r8a7740.o
+obj-$(CONFIG_ARCH_R8A7740)	+= pm-r8a7740.o sleep-r8a7740.o
 obj-$(CONFIG_ARCH_R8A7779)	+= pm-r8a7779.o
 obj-$(CONFIG_ARCH_SH73A0)	+= pm-sh73a0.o
 
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index c401c8d..b8960a2 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -57,6 +57,7 @@ extern void r8a7740_add_standard_devices(void);
 extern void r8a7740_clock_init(u8 md_ck);
 extern void r8a7740_pinmux_init(void);
 extern void r8a7740_pm_init(void);
+extern void r8a7740_resume_core_standby(void);
 
 extern void r8a7779_init_delay(void);
 extern void r8a7779_init_irq(void);
diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c
index 40b87aa..ee3d713 100644
--- a/arch/arm/mach-shmobile/pm-r8a7740.c
+++ b/arch/arm/mach-shmobile/pm-r8a7740.c
@@ -10,9 +10,29 @@
  */
 #include <linux/console.h>
 #include <linux/suspend.h>
+#include <asm/io.h>
+#include <asm/suspend.h>
+#include <asm/cacheflush.h>
+#include <asm/hardware/cache-l2x0.h>
 #include <mach/pm-rmobile.h>
 #include <mach/common.h>
 
+/* CPGA */
+#define SYSTBCR IOMEM(0xe6150024)
+
+/* SYSC */
+#define STBCHR IOMEM(0xe6180000)
+#define STBCHRB IOMEM(0xe6180040)
+#define SBAR IOMEM(0xe6180020)
+#define SRSTFR IOMEM(0xe61800B4)
+
+/* SRSTFR flags */
+#define RAMST	(1 << 19)
+#define RCLNKA	(1 << 7)
+#define RCPRES	(1 << 5)
+#define RCWD1	(1 << 4)
+#define RPF	(1 << 0)
+
 #ifdef CONFIG_PM
 static int r8a7740_pd_a4s_suspend(void)
 {
@@ -62,15 +82,54 @@ void __init r8a7740_init_pm_domains(void)
 #endif /* CONFIG_PM */
 
 #ifdef CONFIG_SUSPEND
-static int r8a7740_enter_suspend(suspend_state_t suspend_state)
+static void r8a7740_set_reset_vector(unsigned long address)
+{
+	__raw_writel(address, SBAR);
+}
+
+static int r8a7740_do_idle_core_standby(unsigned long unused)
 {
+#ifdef CONFIG_CACHE_L2X0
+	/*
+	 * cpu_suspend() guarantees that all data made it to the L2.
+	 * Flush it out now.
+	 */
+	outer_flush_all();
+#endif
 	cpu_do_idle();
 	return 0;
 }
 
+static int r8a7740_enter_core_standby(suspend_state_t suspend_state)
+{
+	u32 reg32;
+
+	r8a7740_set_reset_vector(__pa(r8a7740_resume_core_standby));
+
+	/* clear all flags that lead to a cold boot */
+	__raw_writel(~(RAMST | RCLNKA | RCPRES | RCWD1 | RPF), SRSTFR);
+	/* indicate warm boot */
+	__raw_writel(0x80000000, STBCHRB);
+	/* clear other flags checked by internal ROM boot loader */
+	__raw_writel(0x00000000, STBCHR);
+
+	/* set the System CPU Core Standby flag */
+	reg32 = readl(SYSTBCR);
+	reg32 |= (1 << 4);
+	writel(reg32, SYSTBCR);
+
+	cpu_suspend(0, r8a7740_do_idle_core_standby);
+
+	/* Clear the flag so that other WFI instructions don't get affected */
+	reg32 &= ~(1 << 4);
+	writel(reg32, SYSTBCR);
+
+	return 0;
+}
+
 static void r8a7740_suspend_init(void)
 {
-	shmobile_suspend_ops.enter = r8a7740_enter_suspend;
+	shmobile_suspend_ops.enter = r8a7740_enter_core_standby;
 }
 #else
 static void r8a7740_suspend_init(void) {}
diff --git a/arch/arm/mach-shmobile/sleep-r8a7740.S b/arch/arm/mach-shmobile/sleep-r8a7740.S
new file mode 100644
index 0000000..7a2608f
--- /dev/null
+++ b/arch/arm/mach-shmobile/sleep-r8a7740.S
@@ -0,0 +1,83 @@
+/*
+ * Low level sleep code for the SoC r8a7740
+ *
+ * Copyright (C) 2013 Bastian Hecht
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/memory.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#if defined(CONFIG_SUSPEND)
+/*
+ * The secondary kernel init calls v7_flush_dcache_all before it enables
+ * the L1; however, the L1 comes out of reset in an undefined state, so
+ * the clean + invalidate performed by v7_flush_dcache_all causes a bunch
+ * of cache lines with uninitialized data and uninitialized tags to get
+ * written out to memory, which does really unpleasant things to the main
+ * processor.  We fix this by performing an invalidate, rather than a
+ * clean + invalidate, before jumping into the kernel.
+ *
+ * This funciton is cloned from arch/arm/mach-tegra/headsmp.S
+ */
+	.section ".text.head", "ax"
+ENTRY(v7_invalidate_l1)
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 0	@ invalidate I cache
+	mcr	p15, 2, r0, c0, c0, 0
+	mrc	p15, 1, r0, c0, c0, 0
+
+	ldr	r1, =0x7fff
+	and	r2, r1, r0, lsr #13
+
+	ldr	r1, =0x3ff
+
+	and	r3, r1, r0, lsr #3	@ NumWays - 1
+	add	r2, r2, #1		@ NumSets
+
+	and	r0, r0, #0x7
+	add	r0, r0, #4	@ SetShift
+
+	clz	r1, r3		@ WayShift
+	add	r4, r3, #1	@ NumWays
+1:	sub	r2, r2, #1	@ NumSets--
+	mov	r3, r4		@ Temp = NumWays
+2:	subs	r3, r3, #1	@ Temp--
+	mov	r5, r3, lsl r1
+	mov	r6, r2, lsl r0
+	orr	r5, r5, r6	@ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
+	mcr	p15, 0, r5, c7, c6, 2
+	bgt	2b
+	cmp	r2, #0
+	bgt	1b
+	dsb
+	isb
+	mov	pc, lr
+ENDPROC(v7_invalidate_l1)
+
+	.text
+ENTRY(v7_cpu_resume)
+	bl	v7_invalidate_l1
+	b	cpu_resume
+ENDPROC(v7_cpu_resume)
+
+/*
+ * The entry point of a warm reboot, used by wakeup scenarios
+ *
+ * The CPU jumps in this case to (0xfffff000 & SBAR), so we need
+ * to align this function properly.
+ * We use a long jump into the text segment and use the physical
+ * address as the MMU is still turned off.
+ */
+	.align	12
+	.text
+ENTRY(r8a7740_resume_core_standby)
+	ldr	pc, 1f
+1:	.long	v7_cpu_resume - PAGE_OFFSET + PLAT_PHYS_OFFSET
+ENDPROC(r8a7740_resume_core_standby)
+#endif
-- 
1.7.9.5

  reply	other threads:[~2013-03-04 17:54 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-04 17:54 [PATCH] Core Standby Mode and caches Bastian Hecht
2013-03-04 17:54 ` Bastian Hecht [this message]
2013-03-06 16:40   ` [PATCH] ARM: shmobile: r8a7740: Add CPU Core Standby Mode Russell King - ARM Linux
2013-03-19  3:20     ` Simon Horman
2013-03-19 10:30       ` Bastian Hecht

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=1362419645-3116-2-git-send-email-hechtb+renesas@gmail.com \
    --to=hechtb@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).