Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 173463
b: refs/heads/master
c: 323ef8d
h: refs/heads/master
i:
  173461: 8413a63
  173459: 9956840
  173455: c964671
v: v3
  • Loading branch information
Magnus Damm authored and Paul Mundt committed Oct 30, 2009
1 parent 271cc9f commit 7e8fdd5
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 165 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: eb0cd9e88c6a6561055b32a17d44d8918aecc3c7
refs/heads/master: 323ef8dba67fb7b9c709457bd0374d88cfb8f25f
27 changes: 27 additions & 0 deletions trunk/arch/sh/include/asm/suspend.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,33 @@ extern struct atomic_notifier_head sh_mobile_post_sleep_notifier_list;
void sh_mobile_register_self_refresh(unsigned long flags,
void *pre_start, void *pre_end,
void *post_start, void *post_end);

/* register structure for address/data information */
struct sh_sleep_regs {
unsigned long stbcr;
};

/* data area for low-level sleep code */
struct sh_sleep_data {
/* current sleep mode (SUSP_SH_...) */
unsigned long mode;

/* addresses of board specific self-refresh snippets */
unsigned long sf_pre;
unsigned long sf_post;

/* register state saved and restored by the assembly code */
unsigned long vbr;
unsigned long spc;
unsigned long sr;

/* structure for keeping register addresses */
struct sh_sleep_regs addr;

/* structure for saving/restoring register state */
struct sh_sleep_regs data;
};

#endif

/* flags passed to assembly suspend code */
Expand Down
10 changes: 10 additions & 0 deletions trunk/arch/sh/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,15 @@ int main(void)
DEFINE(PBE_NEXT, offsetof(struct pbe, next));
DEFINE(SWSUSP_ARCH_REGS_SIZE, sizeof(struct swsusp_arch_regs));
#endif

DEFINE(SH_SLEEP_MODE, offsetof(struct sh_sleep_data, mode));
DEFINE(SH_SLEEP_SF_PRE, offsetof(struct sh_sleep_data, sf_pre));
DEFINE(SH_SLEEP_SF_POST, offsetof(struct sh_sleep_data, sf_post));
DEFINE(SH_SLEEP_VBR, offsetof(struct sh_sleep_data, vbr));
DEFINE(SH_SLEEP_SPC, offsetof(struct sh_sleep_data, spc));
DEFINE(SH_SLEEP_SR, offsetof(struct sh_sleep_data, sr));
DEFINE(SH_SLEEP_BASE_ADDR, offsetof(struct sh_sleep_data, addr));
DEFINE(SH_SLEEP_BASE_DATA, offsetof(struct sh_sleep_data, data));
DEFINE(SH_SLEEP_REG_STBCR, offsetof(struct sh_sleep_regs, stbcr));
return 0;
}
54 changes: 43 additions & 11 deletions trunk/arch/sh/kernel/cpu/shmobile/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@ ATOMIC_NOTIFIER_HEAD(sh_mobile_post_sleep_notifier_list);

#define ILRAM_BASE 0xe5200000

extern const unsigned char sh_mobile_standby[];
extern const unsigned int sh_mobile_standby_size;

void sh_mobile_call_standby(unsigned long mode)
{
void *onchip_mem = (void *)ILRAM_BASE;
void (*standby_onchip_mem)(unsigned long, unsigned long) = onchip_mem;
struct sh_sleep_data *sdp = onchip_mem;
void (*standby_onchip_mem)(unsigned long, unsigned long);

/* code located directly after data structure */
standby_onchip_mem = (void *)(sdp + 1);

atomic_notifier_call_chain(&sh_mobile_pre_sleep_notifier_list,
mode, NULL);
Expand All @@ -60,10 +61,48 @@ void sh_mobile_call_standby(unsigned long mode)
mode, NULL);
}

extern char sh_mobile_sleep_enter_start;
extern char sh_mobile_sleep_enter_end;

extern char sh_mobile_sleep_resume_start;
extern char sh_mobile_sleep_resume_end;

void sh_mobile_register_self_refresh(unsigned long flags,
void *pre_start, void *pre_end,
void *post_start, void *post_end)
{
void *onchip_mem = (void *)ILRAM_BASE;
void *vp;
struct sh_sleep_data *sdp;
int n;

/* part 0: data area */
sdp = onchip_mem;
sdp->addr.stbcr = 0xa4150020; /* STBCR */
vp = sdp + 1;

/* part 1: common code to enter sleep mode */
n = &sh_mobile_sleep_enter_end - &sh_mobile_sleep_enter_start;
memcpy(vp, &sh_mobile_sleep_enter_start, n);
vp += roundup(n, 4);

/* part 2: board specific code to enter self-refresh mode */
n = pre_end - pre_start;
memcpy(vp, pre_start, n);
sdp->sf_pre = (unsigned long)vp;
vp += roundup(n, 4);

/* part 3: board specific code to resume from self-refresh mode */
n = post_end - post_start;
memcpy(vp, post_start, n);
sdp->sf_post = (unsigned long)vp;
vp += roundup(n, 4);

/* part 4: common code to resume from sleep mode */
WARN_ON(vp > (onchip_mem + 0x600));
vp = onchip_mem + 0x600; /* located at interrupt vector */
n = &sh_mobile_sleep_resume_end - &sh_mobile_sleep_resume_start;
memcpy(vp, &sh_mobile_sleep_resume_start, n);
}

static int sh_pm_enter(suspend_state_t state)
Expand All @@ -83,13 +122,6 @@ static struct platform_suspend_ops sh_pm_ops = {

static int __init sh_pm_init(void)
{
void *onchip_mem = (void *)ILRAM_BASE;

/* Copy the assembly snippet to the otherwise ununsed ILRAM */
memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size);
wmb();
ctrl_barrier();

suspend_set_ops(&sh_pm_ops);
sh_mobile_setup_cpuidle();
return 0;
Expand Down
Loading

0 comments on commit 7e8fdd5

Please sign in to comment.