Commit 44648f61 authored by Ben Dooks's avatar Ben Dooks Committed by Russell King

[ARM PATCH] 2217/2: S3C2410 - pm updates

Patch from Ben Dooks

This patch does the following:

 - Save S3C2410_DCLKCON over sleep
 - Save all non-SDRAM memory bank config
 - Fix bug in setting PLL before clock divisor
 - Save all IRQ level controlls
 - Restore IRQ masks _after_ configuration restored
 - No debug until core registers restored

This patch also moves the pm save/restore list code
into the header, for other parts of arch/arm/mach-s3c2410
to use. Note, this is not a general invite for external
code to use these functions.

Also applied patch from Dimitry Andric to fix up the
spelling/typos in Documentation/arm/Samsung-S3C24XX/Suspend.txt

Signed-off-by: Ben Dooks 

Signed-off-by: Dimitry Andric 
Signed-off-by: Russell King
parent 5bffe1b1
...@@ -6,7 +6,7 @@ Introduction ...@@ -6,7 +6,7 @@ Introduction
------------ ------------
The S3C2410 supports a low-power suspend mode, where the SDRAM is kept The S3C2410 supports a low-power suspend mode, where the SDRAM is kept
in Self-Refresh mode, and all but the esential peripheral blocks are in Self-Refresh mode, and all but the essential peripheral blocks are
powered down. For more information on how this works, please look powered down. For more information on how this works, please look
at the S3C2410 datasheets from Samsung. at the S3C2410 datasheets from Samsung.
...@@ -41,7 +41,7 @@ Machine Support ...@@ -41,7 +41,7 @@ Machine Support
--------------- ---------------
The machine specific functions must call the s3c2410_pm_init() function The machine specific functions must call the s3c2410_pm_init() function
to say that it's bootloader is capable of resuming. This can be as to say that its bootloader is capable of resuming. This can be as
simple as adding the following to the machine's definition: simple as adding the following to the machine's definition:
INITMACHINE(s3c2410_pm_init) INITMACHINE(s3c2410_pm_init)
...@@ -53,22 +53,22 @@ Machine Support ...@@ -53,22 +53,22 @@ Machine Support
saving the resume address, if your board requires it, then contact saving the resume address, if your board requires it, then contact
the maintainer and discuss what is required. the maintainer and discuss what is required.
Note, the origianal method of adding an late_initcall() is wrong, Note, the original method of adding an late_initcall() is wrong,
and will end up initialising all compiled machine's pm init! and will end up initialising all compiled machines' pm init!
Debugging Debugging
--------- ---------
There are several important things to rember when using PM suspend: There are several important things to remember when using PM suspend:
1) The uart drivers will disable the clocks to the UART blocks when 1) The uart drivers will disable the clocks to the UART blocks when
suspending, which means that use of printascii() or similar direct suspending, which means that use of printascii() or similar direct
access to the UARTs will cause the debug to stop. access to the UARTs will cause the debug to stop.
2) Whilst the pm code itself will attempt to re-enabled the UART clocks, 2) Whilst the pm code itself will attempt to re-enable the UART clocks,
care should be taken that any external clock sources that the UARTs care should be taken that any external clock sources that the UARTs
rely on are still enabled at that point rely on are still enabled at that point.
Configuration Configuration
......
...@@ -59,16 +59,6 @@ extern void arm920_flush_kern_cache_all(void); ...@@ -59,16 +59,6 @@ extern void arm920_flush_kern_cache_all(void);
#define PFX "s3c24xx-pm: " #define PFX "s3c24xx-pm: "
/* sleep save info */
struct sleep_save {
unsigned long reg;
unsigned long val;
};
#define SAVE_ITEM(x) \
{ .reg = (x) }
static struct sleep_save core_save[] = { static struct sleep_save core_save[] = {
SAVE_ITEM(S3C2410_LOCKTIME), SAVE_ITEM(S3C2410_LOCKTIME),
SAVE_ITEM(S3C2410_CLKCON), SAVE_ITEM(S3C2410_CLKCON),
...@@ -81,21 +71,32 @@ static struct sleep_save core_save[] = { ...@@ -81,21 +71,32 @@ static struct sleep_save core_save[] = {
* wrong here, as we modify the refresh and both pll settings. * wrong here, as we modify the refresh and both pll settings.
*/ */
SAVE_ITEM(S3C2410_REFRESH), SAVE_ITEM(S3C2410_BWSCON),
SAVE_ITEM(S3C2410_BANKCON0),
SAVE_ITEM(S3C2410_BANKCON1),
SAVE_ITEM(S3C2410_BANKCON2),
SAVE_ITEM(S3C2410_BANKCON3),
SAVE_ITEM(S3C2410_BANKCON4),
SAVE_ITEM(S3C2410_BANKCON5),
SAVE_ITEM(S3C2410_CLKDIVN),
SAVE_ITEM(S3C2410_MPLLCON), SAVE_ITEM(S3C2410_MPLLCON),
SAVE_ITEM(S3C2410_UPLLCON), SAVE_ITEM(S3C2410_UPLLCON),
SAVE_ITEM(S3C2410_CLKDIVN),
SAVE_ITEM(S3C2410_CLKSLOW), SAVE_ITEM(S3C2410_CLKSLOW),
SAVE_ITEM(S3C2410_REFRESH),
}; };
/* this lot should be really saved by the IRQ code */ /* this lot should be really saved by the IRQ code */
static struct sleep_save irq_save[] = { static struct sleep_save irq_save[] = {
SAVE_ITEM(S3C2410_EINTMASK), SAVE_ITEM(S3C2410_EXTINT0),
SAVE_ITEM(S3C2410_INTMSK), SAVE_ITEM(S3C2410_EXTINT1),
SAVE_ITEM(S3C2410_EXTINT2),
SAVE_ITEM(S3C2410_EINFLT0), SAVE_ITEM(S3C2410_EINFLT0),
SAVE_ITEM(S3C2410_EINFLT1), SAVE_ITEM(S3C2410_EINFLT1),
SAVE_ITEM(S3C2410_EINFLT2), SAVE_ITEM(S3C2410_EINFLT2),
SAVE_ITEM(S3C2410_EINFLT3) SAVE_ITEM(S3C2410_EINFLT3),
SAVE_ITEM(S3C2410_EINTMASK),
SAVE_ITEM(S3C2410_INTMSK)
}; };
static struct sleep_save gpio_save[] = { static struct sleep_save gpio_save[] = {
...@@ -129,6 +130,8 @@ static struct sleep_save gpio_save[] = { ...@@ -129,6 +130,8 @@ static struct sleep_save gpio_save[] = {
SAVE_ITEM(S3C2410_GPHCON), SAVE_ITEM(S3C2410_GPHCON),
SAVE_ITEM(S3C2410_GPHDAT), SAVE_ITEM(S3C2410_GPHDAT),
SAVE_ITEM(S3C2410_GPHUP), SAVE_ITEM(S3C2410_GPHUP),
SAVE_ITEM(S3C2410_DCLKCON),
}; };
#ifdef CONFIG_S3C2410_PM_DEBUG #ifdef CONFIG_S3C2410_PM_DEBUG
...@@ -384,7 +387,7 @@ static struct sleep_save uart_save[] = {}; ...@@ -384,7 +387,7 @@ static struct sleep_save uart_save[] = {};
/* helper functions to save and restore register state */ /* helper functions to save and restore register state */
static void s3c2410_pm_do_save(struct sleep_save *ptr, int count) void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
{ {
for (; count > 0; count--, ptr++) { for (; count > 0; count--, ptr++) {
ptr->val = __raw_readl(ptr->reg); ptr->val = __raw_readl(ptr->reg);
...@@ -400,7 +403,7 @@ static void s3c2410_pm_do_save(struct sleep_save *ptr, int count) ...@@ -400,7 +403,7 @@ static void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
* restore the UARTs state yet * restore the UARTs state yet
*/ */
static void s3c2410_pm_do_restore(struct sleep_save *ptr, int count) void s3c2410_pm_do_restore(struct sleep_save *ptr, int count)
{ {
for (; count > 0; count--, ptr++) { for (; count > 0; count--, ptr++) {
printk(KERN_DEBUG "restore %08lx (restore %08lx, was %08x)\n", printk(KERN_DEBUG "restore %08lx (restore %08lx, was %08x)\n",
...@@ -410,6 +413,21 @@ static void s3c2410_pm_do_restore(struct sleep_save *ptr, int count) ...@@ -410,6 +413,21 @@ static void s3c2410_pm_do_restore(struct sleep_save *ptr, int count)
} }
} }
/* s3c2410_pm_do_restore_core
*
* similar to s3c2410_pm_do_restore_core
*
* WARNING: Do not put any debug in here that may effect memory or use
* peripherals, as things may be changing!
*/
static void s3c2410_pm_do_restore_core(struct sleep_save *ptr, int count)
{
for (; count > 0; count--, ptr++) {
__raw_writel(ptr->val, ptr->reg);
}
}
/* s3c2410_pm_show_resume_irqs /* s3c2410_pm_show_resume_irqs
* *
* print any IRQs asserted at resume time (ie, we woke from) * print any IRQs asserted at resume time (ie, we woke from)
...@@ -578,7 +596,7 @@ static int s3c2410_pm_enter(suspend_state_t state) ...@@ -578,7 +596,7 @@ static int s3c2410_pm_enter(suspend_state_t state)
/* restore the system state */ /* restore the system state */
s3c2410_pm_do_restore(core_save, ARRAY_SIZE(core_save)); s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save)); s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));
s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save)); s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save)); s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));
......
...@@ -34,3 +34,16 @@ extern void s3c2410_cpu_suspend(unsigned long *saveblk); ...@@ -34,3 +34,16 @@ extern void s3c2410_cpu_suspend(unsigned long *saveblk);
extern void s3c2410_cpu_resume(void); extern void s3c2410_cpu_resume(void);
extern unsigned long s3c2410_sleep_save_phys; extern unsigned long s3c2410_sleep_save_phys;
/* sleep save info */
struct sleep_save {
unsigned long reg;
unsigned long val;
};
#define SAVE_ITEM(x) \
{ .reg = (x) }
extern void s3c2410_pm_do_save(struct sleep_save *ptr, int count);
extern void s3c2410_pm_do_restore(struct sleep_save *ptr, int count);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment