From patchwork Mon Mar 4 17:54:05 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bastian Hecht X-Patchwork-Id: 2213471 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id 802E93FCF2 for ; Mon, 4 Mar 2013 16:58:02 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UCYef-0008Lw-Aa; Mon, 04 Mar 2013 16:54:25 +0000 Received: from mail-ee0-f49.google.com ([74.125.83.49]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UCYeQ-0008Fd-P8 for linux-arm-kernel@lists.infradead.org; Mon, 04 Mar 2013 16:54:12 +0000 Received: by mail-ee0-f49.google.com with SMTP id d41so3992167eek.8 for ; Mon, 04 Mar 2013 08:54:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=LN1tp6qzeTe/s6CdDtQeVgvVcmE4Cep/PC8o3gO2ApM=; b=wZ377j/a0KvlQRNMpOOgZzRdtB9oQywL0wADKOJIlYydMslnXxEYMhyzSb7jPpYabB sWmLFhk0hN5oRpPOzUsmPsJbaEmuI9RIY7jUDivAuNWcSVOmdYZO/HCbJl/EMHz6xgWP x1Gn5lbrjqdDwgD3AZzOYW4O8Qfi+g/5XrlOgCl0iGpkMKfbmtiy2zbp8qCOuzwOQfE4 U2Zhpmraas+fvLt+Fxre1G+nqKN/Y/tttB8xjTxMyDCXrRLouSZbUBwNpirrDHv5bOYg j/ClTmLhc/F4wSIhGEFZ6QJBuH6pUYN82kDYcJQUQOqNT8CXf794k3v8DcSxNplTZfTR 04Ew== X-Received: by 10.14.204.195 with SMTP id h43mr51723351eeo.14.1362416049208; Mon, 04 Mar 2013 08:54:09 -0800 (PST) Received: from localhost.localdomain (p4FD2413F.dip.t-dialin.net. [79.210.65.63]) by mx.google.com with ESMTPS id q5sm33018070eeo.17.2013.03.04.08.54.07 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 04 Mar 2013 08:54:08 -0800 (PST) From: Bastian Hecht To: linux-sh@vger.kernel.org Subject: [PATCH] ARM: shmobile: r8a7740: Add CPU Core Standby Mode Date: Mon, 4 Mar 2013 18:54:05 +0100 Message-Id: <1362419645-3116-2-git-send-email-hechtb+renesas@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1362419645-3116-1-git-send-email-hechtb+renesas@gmail.com> References: <1362419645-3116-1-git-send-email-hechtb+renesas@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130304_115411_126180_EEDEE19C X-CRM114-Status: GOOD ( 22.83 ) X-Spam-Score: -2.7 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [74.125.83.49 listed in list.dnswl.org] 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (hechtb[at]gmail.com) -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature Cc: Magnus Damm , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org 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 --- 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 #include +#include +#include +#include +#include #include #include +/* 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 +#include +#include +#include + +#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<