From patchwork Mon Jan 26 10:07:57 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wenyou Yang X-Patchwork-Id: 5707811 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 20B569F333 for ; Mon, 26 Jan 2015 10:14:04 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 31D0B200DC for ; Mon, 26 Jan 2015 10:14:03 +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 39B7020122 for ; Mon, 26 Jan 2015 10:14:02 +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 1YFge6-0001Dg-Va; Mon, 26 Jan 2015 10:11:50 +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 1YFgdX-0000hp-8x for linux-arm-kernel@lists.infradead.org; Mon, 26 Jan 2015 10:11:16 +0000 Received: from apsmtp01.atmel.com (10.168.254.30) by eusmtp01.atmel.com (10.161.101.30) with Microsoft SMTP Server id 14.2.347.0; Mon, 26 Jan 2015 11:11:11 +0100 Received: from shaarm01.corp.atmel.com (10.168.254.13) by apsmtp01.corp.atmel.com (10.168.254.30) with Microsoft SMTP Server id 14.2.347.0; Mon, 26 Jan 2015 18:11:32 +0800 From: Wenyou Yang To: , Subject: [PATCH 5/7] pm: at91: add disable/enable the L1/L2 cache while suspend/resume Date: Mon, 26 Jan 2015 18:07:57 +0800 Message-ID: <1422266877-24628-1-git-send-email-wenyou.yang@atmel.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1422266617-24381-1-git-send-email-wenyou.yang@atmel.com> References: <1422266617-24381-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-20150126_021115_541130_367533DA X-CRM114-Status: GOOD ( 11.48 ) X-Spam-Score: -0.7 (/) Cc: sylvain.rochet@finsecur.com, Patrice.VILCHEZ@atmel.com, linux-kernel@vger.kernel.org, wenyou.yang@atmel.com, alexandre.belloni@free-electrons.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 | 9 ++++ arch/arm/mach-at91/pm_suspend.S | 107 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index f75dc32..50cde92 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -35,6 +35,9 @@ #include "generic.h" #include "pm.h" +void __weak at91_disable_l1_l2_cache(void) {} +void __weak at91_enable_l1_l2_cache(void) {} + struct at91_pm_struct at91_pm_data; static int at91_pm_valid_state(suspend_state_t state) @@ -142,8 +145,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 88cf228..e6e7f7a 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" @@ -329,3 +330,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