From 99675a7a45ed3cec54d6e1d11f13bcaacaf0909b Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 30 Oct 2009 04:24:23 +0000 Subject: sh: Add MMU and Cache handling sleep mode code Add MMU and cache handling functionality to the SuperH Mobile sleep code. The MMU and cache registers are saved and restored. The MMU is disabled and the cache is flushed and disabled before entering sleep modes if the SUSP_SH_MMU flag is set. This flag should be set in the case of R-standby and most likely for future U-standby support as well. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/shmobile/pm.c | 15 ++++++ arch/sh/kernel/cpu/shmobile/sleep.S | 92 +++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) (limited to 'arch/sh/kernel/cpu') diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c index a94dc480f0c..ca642f39e2e 100644 --- a/arch/sh/kernel/cpu/shmobile/pm.c +++ b/arch/sh/kernel/cpu/shmobile/pm.c @@ -15,6 +15,7 @@ #include #include #include +#include /* * Notifier lists for pre/post sleep notification @@ -54,6 +55,10 @@ void sh_mobile_call_standby(unsigned long mode) atomic_notifier_call_chain(&sh_mobile_pre_sleep_notifier_list, mode, NULL); + /* flush the caches if MMU flag is set */ + if (mode & SUSP_SH_MMU) + flush_cache_all(); + /* Let assembly snippet in on-chip memory handle the rest */ standby_onchip_mem(mode, ILRAM_BASE); @@ -81,6 +86,16 @@ void sh_mobile_register_self_refresh(unsigned long flags, /* part 0: data area */ sdp = onchip_mem; sdp->addr.stbcr = 0xa4150020; /* STBCR */ + sdp->addr.pteh = 0xff000000; /* PTEH */ + sdp->addr.ptel = 0xff000004; /* PTEL */ + sdp->addr.ttb = 0xff000008; /* TTB */ + sdp->addr.tea = 0xff00000c; /* TEA */ + sdp->addr.mmucr = 0xff000010; /* MMUCR */ + sdp->addr.ptea = 0xff000034; /* PTEA */ + sdp->addr.pascr = 0xff000070; /* PASCR */ + sdp->addr.irmcr = 0xff000078; /* IRMCR */ + sdp->addr.ccr = 0xff00001c; /* CCR */ + sdp->addr.ramcr = 0xff000074; /* RAMCR */ vp = sdp + 1; /* part 1: common code to enter sleep mode */ diff --git a/arch/sh/kernel/cpu/shmobile/sleep.S b/arch/sh/kernel/cpu/shmobile/sleep.S index d3221d9b88b..e620bf397af 100644 --- a/arch/sh/kernel/cpu/shmobile/sleep.S +++ b/arch/sh/kernel/cpu/shmobile/sleep.S @@ -52,6 +52,57 @@ ENTRY(sh_mobile_sleep_enter_start) bsr save_register mov #SH_SLEEP_REG_STBCR, r0 + /* save mmu and cache context if needed */ + mov.l @(SH_SLEEP_MODE, r5), r0 + tst #SUSP_SH_MMU, r0 + bt skip_mmu_save_disable + + /* save mmu state */ + bsr save_register + mov #SH_SLEEP_REG_PTEH, r0 + + bsr save_register + mov #SH_SLEEP_REG_PTEL, r0 + + bsr save_register + mov #SH_SLEEP_REG_TTB, r0 + + bsr save_register + mov #SH_SLEEP_REG_TEA, r0 + + bsr save_register + mov #SH_SLEEP_REG_MMUCR, r0 + + bsr save_register + mov #SH_SLEEP_REG_PTEA, r0 + + bsr save_register + mov #SH_SLEEP_REG_PASCR, r0 + + bsr save_register + mov #SH_SLEEP_REG_IRMCR, r0 + + /* invalidate TLBs and disable the MMU */ + bsr get_register + mov #SH_SLEEP_REG_MMUCR, r0 + mov #4, r1 + mov.l r1, @r0 + icbi @r0 + + /* save cache registers and disable caches */ + bsr save_register + mov #SH_SLEEP_REG_CCR, r0 + + bsr save_register + mov #SH_SLEEP_REG_RAMCR, r0 + + bsr get_register + mov #SH_SLEEP_REG_CCR, r0 + mov #0, r1 + mov.l r1, @r0 + icbi @r0 + +skip_mmu_save_disable: /* call self-refresh entering code if needed */ mov.l @(SH_SLEEP_MODE, r5), r0 tst #SUSP_SH_SF, r0 @@ -166,6 +217,47 @@ ENTRY(sh_mobile_sleep_resume_start) nop skip_restore_sf: + /* restore mmu and cache state if needed */ + mov.l @(SH_SLEEP_MODE, r5), r0 + tst #SUSP_SH_MMU, r0 + bt skip_restore_mmu + + /* restore mmu state */ + bsr restore_register + mov #SH_SLEEP_REG_PTEH, r0 + + bsr restore_register + mov #SH_SLEEP_REG_PTEL, r0 + + bsr restore_register + mov #SH_SLEEP_REG_TTB, r0 + + bsr restore_register + mov #SH_SLEEP_REG_TEA, r0 + + bsr restore_register + mov #SH_SLEEP_REG_PTEA, r0 + + bsr restore_register + mov #SH_SLEEP_REG_PASCR, r0 + + bsr restore_register + mov #SH_SLEEP_REG_IRMCR, r0 + + bsr restore_register + mov #SH_SLEEP_REG_MMUCR, r0 + icbi @r0 + + /* restore cache settings */ + bsr restore_register + mov #SH_SLEEP_REG_RAMCR, r0 + icbi @r0 + + bsr restore_register + mov #SH_SLEEP_REG_CCR, r0 + icbi @r0 + +skip_restore_mmu: rte nop -- cgit v1.2.3