From patchwork Thu Mar 21 13:31:37 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bastian Hecht X-Patchwork-Id: 2313411 Return-Path: X-Original-To: patchwork-linux-sh@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id B3E0D400E6 for ; Thu, 21 Mar 2013 13:31:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757340Ab3CUNbd (ORCPT ); Thu, 21 Mar 2013 09:31:33 -0400 Received: from mail-ee0-f42.google.com ([74.125.83.42]:46190 "EHLO mail-ee0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757031Ab3CUNbc (ORCPT ); Thu, 21 Mar 2013 09:31:32 -0400 Received: by mail-ee0-f42.google.com with SMTP id b47so1704015eek.1 for ; Thu, 21 Mar 2013 06:31:31 -0700 (PDT) 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=nk3wVOVfdXGyLKkegzwlcIzOo42ZijfXa8OfJZFkK1Q=; b=IztC/zBgmM2N/L2TdurjGucigxSIyiJ/dnQ/Pqzuv5/z0hmOnoyNzhUigkR9wVZ6Fp 80eUfAdsWfoLV56cYxrOgF4qUJ2Cn+J5Gz0iEpdzOBNuvAH2ihYG6xh4DCcIsqLddEw6 scZwt68Utv2M2hdHGS/RFI8l82PKLocaK+d9cOjVKaifi85QfUlt0mKPUsnYxpVCT7VU tEPvaEQPX7+scPxzznSeyWeTReLlMmbOsRUg5qT1G9xUzINiYNk+itZS+DAwHb3ZoxBQ IrMAmM+/+wl4P863J35op5hlWWmdJukBfuI/eCZXpNoCa71SmclI0FM3VrU2vQ3yjWT6 L9Pw== X-Received: by 10.14.207.73 with SMTP id m49mr82902190eeo.24.1363872691471; Thu, 21 Mar 2013 06:31:31 -0700 (PDT) Received: from localhost.localdomain (p4FD26909.dip.t-dialin.net. [79.210.105.9]) by mx.google.com with ESMTPS id q5sm8478702eeo.17.2013.03.21.06.31.30 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 21 Mar 2013 06:31:31 -0700 (PDT) From: Bastian Hecht To: linux-sh@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, Simon Horman , Magnus Damm Subject: [PATCH 2/2] ARM: shmobile: sh73a0: Suspend-to-RAM Power Off mode Date: Thu, 21 Mar 2013 14:31:37 +0100 Message-Id: <1363872697-11267-3-git-send-email-hechtb+renesas@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1363872697-11267-1-git-send-email-hechtb+renesas@gmail.com> References: <1363872697-11267-1-git-send-email-hechtb+renesas@gmail.com> Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org We add Power Off mode defined by the ARM architecture as our Suspend-to-RAM mechanism. Here the L2 cache keeps its power and we only take care to flush the L1. Different startup paths are added for the two CPUs, one leading to cpu_resume() and the other to secondary_startup(). Signed-off-by: Bastian Hecht --- arch/arm/mach-shmobile/Makefile | 2 +- arch/arm/mach-shmobile/headsmp-sh73a0.S | 72 ++++++++++++++++++++++++++ arch/arm/mach-shmobile/include/mach/common.h | 1 + arch/arm/mach-shmobile/pm-sh73a0.c | 32 ++++++++++-- arch/arm/mach-shmobile/smp-sh73a0.c | 9 +++- 5 files changed, 109 insertions(+), 7 deletions(-) create mode 100644 arch/arm/mach-shmobile/headsmp-sh73a0.S diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index c621edf..1d33d89 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -14,7 +14,7 @@ obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o clock-emev2.o # SMP objects smp-y := platsmp.o headsmp.o -smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-scu.o +smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-sh73a0.o headsmp-scu.o smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o headsmp-scu.o smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o diff --git a/arch/arm/mach-shmobile/headsmp-sh73a0.S b/arch/arm/mach-shmobile/headsmp-sh73a0.S new file mode 100644 index 0000000..6ffed46 --- /dev/null +++ b/arch/arm/mach-shmobile/headsmp-sh73a0.S @@ -0,0 +1,72 @@ +/* + * SMP support for SoC sh73a0 + * + * Copyright (C) 2013 Bastian Hecht + * + * 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. + */ + +#include +#include +#include + + __CPUINIT + +ENTRY(sh73a0_primary_resume) + bl v7_invalidate_l1 + b cpu_resume +ENDPROC(sh73a0_primary_resume) + +ENTRY(sh73a0_secondary_startup) + bl v7_invalidate_l1 + b secondary_startup +ENDPROC(sh73a0_primary_resume) + +/* + * Reset vector for both CPUs. + * + * This function will be mapped to address 0 by the SBAR register and is the + * general wakeup vector. + * For both CPUs we need to set the SCU power flag to Run Mode and invalidate + * the L1 cache so no random data get flushed out later. + * We can't use v7_invalidate_l1() directly as a normal branch is out of range + * here and so we need a long jump. We jump to the physical address as the + * MMU is still turned off. + * + * We do not need to worry about CPU1 running ahead of CPU0 as the secondary + * CPU of the sh73a0 needs to be woken using the WUPCR register. This is done + * in sh73a0_boot_secondary(). + */ + .align 12 +ENTRY(sh73a0_reset_vector) + /* Retrieve the CPU ID and keep it in r4 */ + mrc p15, 0, r4, c0, c0, 5 @ read MIPDR + and r4, r4, #3 @ mask out cpu ID + + /* + * We clear the SCU Power status flag to prepare for the + * L1 coherency mode + */ + mov r0, r4 @ copy CPU ID + lsl r0, r0, #3 @ we will shift by cpu_id * 8 bits + ldr r1, 3f + ldr r1, [r1] @ SCU base address + ldr r2, [r1, #8] @ SCU Power Status Register + mov r3, #3 + bic r2, r2, r3, lsl r0 @ Clear bits of our CPU (Run Mode) + str r2, [r1, #8] @ write back + + /* + * Depending on the CPU ID we either resume our primary core from + * sleeping or bring up the secondary CPU + */ + cmp r4, #0 @ if CPU0 + ldreq pc, 1f @ jump to sh73a0_primary_resume + ldr pc, 2f @ jump to sh73a0_secondary_startup + +1: .long sh73a0_primary_resume - PAGE_OFFSET + PLAT_PHYS_OFFSET +2: .long sh73a0_secondary_startup - PAGE_OFFSET + PLAT_PHYS_OFFSET +3: .long shmobile_scu_base - PAGE_OFFSET + PLAT_PHYS_OFFSET +ENDPROC(sh73a0_reset_vector) diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index 03f73de..842bb35 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h @@ -45,6 +45,7 @@ extern void sh73a0_add_standard_devices_dt(void); extern void sh73a0_clock_init(void); extern void sh73a0_pinmux_init(void); extern void sh73a0_pm_init(void); +extern void sh73a0_reset_vector(void); extern struct clk sh73a0_extal1_clk; extern struct clk sh73a0_extal2_clk; extern struct clk sh73a0_extcki_clk; diff --git a/arch/arm/mach-shmobile/pm-sh73a0.c b/arch/arm/mach-shmobile/pm-sh73a0.c index 99086e9..7e8e0a1 100644 --- a/arch/arm/mach-shmobile/pm-sh73a0.c +++ b/arch/arm/mach-shmobile/pm-sh73a0.c @@ -1,30 +1,54 @@ /* * sh73a0 Power management support * - * Copyright (C) 2012 Bastian Hecht + * 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 +#include +#include +#include #include #ifdef CONFIG_SUSPEND -static int sh73a0_enter_suspend(suspend_state_t suspend_state) +/* + * sh73a0_do_poweroff: Power off the main CPU + * + * The L2 cache doesn't loose power in Power Off mode - ignore it. + * After flushing the L1 cache we don't take care to disable it as we + * only work on temporary values in a UP environment and it gets invalidated + * on startup. Just straight take down the ARM core. + */ +static int sh73a0_do_poweroff(unsigned long unused) { + flush_cache_all(); + scu_power_mode(shmobile_scu_base, SCU_PM_POWEROFF); cpu_do_idle(); + + return 0; +} + +static int sh73a0_enter_poweroff_suspend(suspend_state_t suspend_state) +{ + cpu_suspend(0, sh73a0_do_poweroff); + return 0; } static void sh73a0_suspend_init(void) { - shmobile_suspend_ops.enter = sh73a0_enter_suspend; + shmobile_suspend_ops.enter = sh73a0_enter_poweroff_suspend; } #else static void sh73a0_suspend_init(void) {} -#endif +#endif /* CONFIG_SUSPEND */ void __init sh73a0_pm_init(void) { diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c index 5ae502b..348714e 100644 --- a/arch/arm/mach-shmobile/smp-sh73a0.c +++ b/arch/arm/mach-shmobile/smp-sh73a0.c @@ -70,9 +70,14 @@ static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus) { scu_enable(shmobile_scu_base); - /* Map the reset vector (in headsmp-scu.S) */ + /* + * Map the general reset vector that is hit from multiple paths: + * - Primary CPU resume at wakeup time + * - Secondary startup at boot time + * - Secondary startup at wakeup time + */ __raw_writel(0, APARMBAREA); /* 4k */ - __raw_writel(__pa(shmobile_secondary_vector_scu), SBAR); + __raw_writel(__pa(sh73a0_reset_vector), SBAR); /* enable cache coherency on booting CPU */ scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);