-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This patch contains CONFIG_SUSPEND support to the SuperH architecture. If enabled, SuperH Mobile processors will register their suspend callbacks during boot. To suspend, use "echo mem > /sys/power/state". To allow wakeup, make sure "/sys/device/platform/../power/wakeup" contains "enabled". Additional per-device driver patches are most likely needed. Signed-off-by: Magnus Damm <damm@igel.co.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
- Loading branch information
Magnus Damm
authored and
Paul Mundt
committed
Mar 16, 2009
1 parent
7a51628
commit 7759491
Showing
5 changed files
with
231 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/* | ||
* arch/sh/kernel/cpu/sh4a/pm-sh_mobile.c | ||
* | ||
* Power management support code for SuperH Mobile | ||
* | ||
* Copyright (C) 2009 Magnus Damm | ||
* | ||
* 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 <linux/init.h> | ||
#include <linux/kernel.h> | ||
#include <linux/io.h> | ||
#include <linux/suspend.h> | ||
#include <asm/suspend.h> | ||
#include <asm/uaccess.h> | ||
|
||
/* | ||
* Sleep modes available on SuperH Mobile: | ||
* | ||
* Sleep mode is just plain "sleep" instruction | ||
* Sleep Self-Refresh mode is above plus RAM put in Self-Refresh | ||
* Standby Self-Refresh mode is above plus stopped clocks | ||
*/ | ||
#define SUSP_MODE_SLEEP (SUSP_SH_SLEEP) | ||
#define SUSP_MODE_SLEEP_SF (SUSP_SH_SLEEP | SUSP_SH_SF) | ||
#define SUSP_MODE_STANDBY_SF (SUSP_SH_STANDBY | SUSP_SH_SF) | ||
|
||
/* | ||
* The following modes are not there yet: | ||
* | ||
* R-standby mode is unsupported, but will be added in the future | ||
* U-standby mode is low priority since it needs bootloader hacks | ||
* | ||
* All modes should be tied in with cpuidle. But before that can | ||
* happen we need to keep track of enabled hardware blocks so we | ||
* can avoid entering sleep modes that stop clocks to hardware | ||
* blocks that are in use even though the cpu core is idle. | ||
*/ | ||
|
||
extern const unsigned char sh_mobile_standby[]; | ||
extern const unsigned int sh_mobile_standby_size; | ||
|
||
static void sh_mobile_call_standby(unsigned long mode) | ||
{ | ||
extern void *vbr_base; | ||
void *onchip_mem = (void *)0xe5200000; /* ILRAM */ | ||
void (*standby_onchip_mem)(unsigned long) = onchip_mem; | ||
|
||
/* Note: Wake up from sleep may generate exceptions! | ||
* Setup VBR to point to on-chip ram if self-refresh is | ||
* going to be used. | ||
*/ | ||
if (mode & SUSP_SH_SF) | ||
asm volatile("ldc %0, vbr" : : "r" (onchip_mem) : "memory"); | ||
|
||
/* Copy the assembly snippet to the otherwise ununsed ILRAM */ | ||
memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size); | ||
wmb(); | ||
ctrl_barrier(); | ||
|
||
/* Let assembly snippet in on-chip memory handle the rest */ | ||
standby_onchip_mem(mode); | ||
|
||
/* Put VBR back in System RAM again */ | ||
if (mode & SUSP_SH_SF) | ||
asm volatile("ldc %0, vbr" : : "r" (&vbr_base) : "memory"); | ||
} | ||
|
||
static int sh_pm_enter(suspend_state_t state) | ||
{ | ||
local_irq_disable(); | ||
set_bl_bit(); | ||
sh_mobile_call_standby(SUSP_MODE_STANDBY_SF); | ||
local_irq_disable(); | ||
clear_bl_bit(); | ||
return 0; | ||
} | ||
|
||
static struct platform_suspend_ops sh_pm_ops = { | ||
.enter = sh_pm_enter, | ||
.valid = suspend_valid_only_mem, | ||
}; | ||
|
||
static int __init sh_pm_init(void) | ||
{ | ||
suspend_set_ops(&sh_pm_ops); | ||
return 0; | ||
} | ||
|
||
late_initcall(sh_pm_init); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
/* | ||
* arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S | ||
* | ||
* Sleep mode and Standby modes support for SuperH Mobile | ||
* | ||
* Copyright (C) 2009 Magnus Damm | ||
* | ||
* 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 <linux/sys.h> | ||
#include <linux/errno.h> | ||
#include <linux/linkage.h> | ||
#include <asm/asm-offsets.h> | ||
#include <asm/suspend.h> | ||
|
||
/* manage self-refresh and enter standby mode. | ||
* this code will be copied to on-chip memory and executed from there. | ||
*/ | ||
|
||
.balign 4096,0,4096 | ||
ENTRY(sh_mobile_standby) | ||
mov r4, r0 | ||
|
||
tst #SUSP_SH_SF, r0 | ||
bt skip_set_sf | ||
|
||
/* SDRAM: disable power down and put in self-refresh mode */ | ||
mov.l 1f, r4 | ||
mov.l 2f, r1 | ||
mov.l @r4, r2 | ||
or r1, r2 | ||
mov.l 3f, r3 | ||
and r3, r2 | ||
mov.l r2, @r4 | ||
|
||
skip_set_sf: | ||
tst #SUSP_SH_SLEEP, r0 | ||
bt test_standby | ||
|
||
/* set mode to "sleep mode" */ | ||
bra do_sleep | ||
mov #0x00, r1 | ||
|
||
test_standby: | ||
tst #SUSP_SH_STANDBY, r0 | ||
bt test_rstandby | ||
|
||
/* set mode to "software standby mode" */ | ||
bra do_sleep | ||
mov #0x80, r1 | ||
|
||
test_rstandby: | ||
tst #SUSP_SH_RSTANDBY, r0 | ||
bt test_ustandby | ||
|
||
/* set mode to "r-standby mode" */ | ||
bra do_sleep | ||
mov #0x20, r1 | ||
|
||
test_ustandby: | ||
tst #SUSP_SH_USTANDBY, r0 | ||
bt done_sleep | ||
|
||
/* set mode to "u-standby mode" */ | ||
mov #0x10, r1 | ||
|
||
/* fall-through */ | ||
|
||
do_sleep: | ||
/* setup and enter selected standby mode */ | ||
mov.l 5f, r4 | ||
mov.l r1, @r4 | ||
sleep | ||
|
||
done_sleep: | ||
/* reset standby mode to sleep mode */ | ||
mov.l 5f, r4 | ||
mov #0x00, r1 | ||
mov.l r1, @r4 | ||
|
||
tst #SUSP_SH_SF, r0 | ||
bt skip_restore_sf | ||
|
||
/* SDRAM: set auto-refresh mode */ | ||
mov.l 1f, r4 | ||
mov.l @r4, r2 | ||
mov.l 4f, r3 | ||
and r3, r2 | ||
mov.l r2, @r4 | ||
mov.l 6f, r4 | ||
mov.l 7f, r1 | ||
mov.l 8f, r2 | ||
mov.l @r4, r3 | ||
mov #-1, r4 | ||
add r4, r3 | ||
or r2, r3 | ||
mov.l r3, @r1 | ||
skip_restore_sf: | ||
rts | ||
nop | ||
|
||
.balign 4 | ||
1: .long 0xfe400008 /* SDCR0 */ | ||
2: .long 0x00000400 | ||
3: .long 0xffff7fff | ||
4: .long 0xfffffbff | ||
5: .long 0xa4150020 /* STBCR */ | ||
6: .long 0xfe40001c /* RTCOR */ | ||
7: .long 0xfe400018 /* RTCNT */ | ||
8: .long 0xa55a0000 | ||
|
||
/* interrupt vector @ 0x600 */ | ||
.balign 0x400,0,0x400 | ||
.long 0xdeadbeef | ||
.balign 0x200,0,0x200 | ||
/* sh7722 will end up here in sleep mode */ | ||
rte | ||
nop | ||
sh_mobile_standby_end: | ||
|
||
ENTRY(sh_mobile_standby_size) | ||
.long sh_mobile_standby_end - sh_mobile_standby |