From patchwork Wed Jan 28 02:24:04 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wenyou Yang X-Patchwork-Id: 5723761 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id C12639F1D6 for ; Wed, 28 Jan 2015 02:29:47 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D29CE201FA for ; Wed, 28 Jan 2015 02:29:46 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E54B32011D for ; Wed, 28 Jan 2015 02:29:45 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YGIMZ-0004P6-1Q; Wed, 28 Jan 2015 02:28:15 +0000 Received: from eusmtp01.atmel.com ([212.144.249.242]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YGIMT-00048h-D2 for linux-arm-kernel@lists.infradead.org; Wed, 28 Jan 2015 02:28:10 +0000 Received: from apsmtp01.atmel.com (10.168.254.31) by eusmtp01.atmel.com (10.161.101.30) with Microsoft SMTP Server id 14.2.347.0; Wed, 28 Jan 2015 03:27:43 +0100 Received: from shaarm01.corp.atmel.com (10.168.254.13) by apsmtp01.atmel.com (10.168.254.31) with Microsoft SMTP Server id 14.2.347.0; Wed, 28 Jan 2015 10:28:37 +0800 From: Wenyou Yang To: , Subject: [PATCH v2 3/3] pm: at91: add disable/enable the L1/L2 cache while suspend/resume Date: Wed, 28 Jan 2015 10:24:04 +0800 Message-ID: <1422411844-13241-1-git-send-email-wenyou.yang@atmel.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1422411707-10945-1-git-send-email-wenyou.yang@atmel.com> References: <1422411707-10945-1-git-send-email-wenyou.yang@atmel.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150127_182809_830065_28A7BDC4 X-CRM114-Status: GOOD ( 11.30 ) X-Spam-Score: -0.7 (/) Cc: sergei.shtylyov@cogentembedded.com, sylvain.rochet@finsecur.com, linux-kernel@vger.kernel.org, linux@maxim.org.za, alexandre.belloni@free-electrons.com, wenyou.yang@atmel.com, peda@axentia.se, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP For the sama5, disable L1 D-cache and L2 cache before the cpu go to wfi, after wakeing up, enable L1 D-cache and L2 cache. Signed-off-by: Wenyou Yang --- arch/arm/mach-at91/pm.c | 12 +++++ arch/arm/mach-at91/pm_suspend.S | 107 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index c547038..3442f80e 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -40,6 +40,12 @@ static struct { int memctrl; } at91_pm_data; +void __weak at91_disable_l1_l2_cache(void) {} +void __weak at91_enable_l1_l2_cache(void) {} + +void __iomem *at91_l2cc_base; +EXPORT_SYMBOL_GPL(at91_l2cc_base); + static int at91_pm_valid_state(suspend_state_t state) { switch (state) { @@ -141,8 +147,14 @@ static void at91_pm_suspend(suspend_state_t state) pm_data |= (state == PM_SUSPEND_MEM) ? AT91_PM_MODE(AT91_PM_SLOW_CLOCK) : 0; + /* Disable L1 D-cache and L2 cache */ + at91_disable_l1_l2_cache(); + at91_suspend_sram_fn(at91_pmc_base, at91_ramc_base[0], at91_ramc_base[1], pm_data); + + /* Enable L1 D-cache and L2 cache */ + at91_enable_l1_l2_cache(); } static int at91_pm_enter(suspend_state_t state) diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S index 311cc23..02d4e56 100644 --- a/arch/arm/mach-at91/pm_suspend.S +++ b/arch/arm/mach-at91/pm_suspend.S @@ -15,6 +15,7 @@ #include #include #include +#include #include "pm.h" @@ -324,3 +325,109 @@ ram_restored: ENTRY(at91_pm_suspend_in_sram_sz) .word .-at91_pm_suspend_in_sram + +/*---------------------------------------*/ + +#if defined(CONFIG_CPU_V7) + +/* + * void at91_disable_l1_l2_cache(void) + * + * This function code disables, cleans & invalidates the L1 D-cache + * and cleans, invalidates & disable the L2 cache. + */ +ENTRY(at91_disable_l1_l2_cache) + stmfd sp!, {r4 - r12, lr} + + /* + * Flush all data from the L1 D-cache before disabling + * SCTLR.C bit. + */ + bl v7_flush_dcache_all + + /* + * Clear the SCTLR.C bit to prevent further data cache + * allocation. Clearing SCTLR.C would make all the data accesses + * strongly ordered and would not hit the cache. + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #(1 << 2) @ Disable the C bit + mcr p15, 0, r0, c1, c0, 0 + isb + + /* + * Invalidate L1 D-cache. Even though only invalidate is + * necessary exported flush API is used here. Doing clean + * on already clean cache would be almost NOP. + */ + bl v7_flush_dcache_all + + /* + * Clean and invalidate the L2 cache. + * Common cache-l2x0.c functions can't be used here since it + * uses spinlocks. We are out of coherency here with data cache + * disabled. The spinlock implementation uses exclusive load/store + * instruction which can fail without data cache being enabled. + * Because of this, CPU can lead to deadlock. + */ + ldr r1, at91_l2cc_base_addr + ldr r2, [r1] + cmp r2, #0 + beq skip_l2disable + mov r0, #0xff + str r0, [r2, #L2X0_CLEAN_INV_WAY] +wait: + ldr r0, [r2, #L2X0_CLEAN_INV_WAY] + mov r1, #0xff + ands r0, r0, r1 + bne wait + + mov r0, #0 + str r0, [r2, #L2X0_CTRL] + +l2x_sync: + ldr r0, [r2, #L2X0_CACHE_SYNC] + bic r0, r0, #0x1 + str r0, [r2, #L2X0_CACHE_SYNC] +sync: + ldr r0, [r2, #L2X0_CACHE_SYNC] + ands r0, r0, #0x1 + bne sync + +skip_l2disable: + ldmfd sp!, {r4 - r12, pc} +ENDPROC(at91_disable_l1_l2_cache) + +/* + * void at91_enable_l1_l2_cache(void) + * + * This function code enables the L1 D-cache and the L2 cache. + */ +ENTRY(at91_enable_l1_l2_cache) + stmfd sp!, {r4 - r12, lr} + + /* Enable the L2 cache */ + ldr r1, at91_l2cc_base_addr + ldr r2, [r1] + cmp r2, #0 + beq skip_l2en + ldr r0, [r2, #L2X0_CTRL] + ands r0, r0, #L2X0_CTRL_EN + bne skip_l2en @ Skip if already enabled + mov r0, #L2X0_CTRL_EN + str r0, [r2, #L2X0_CTRL] +skip_l2en: + + /* Enable the L1 D-cache */ + mrc p15, 0, r0, c1, c0, 0 + tst r0, #(1 << 2) @ Check C bit enabled? + orreq r0, r0, #(1 << 2) @ Enable the C bit + mcreq p15, 0, r0, c1, c0, 0 + isb + + ldmfd sp!, {r4 - r12, pc} +ENDPROC(at91_enable_l1_l2_cache) + +at91_l2cc_base_addr: + .word at91_l2cc_base +#endif