X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Farm%2Fmach-s3c2410%2Fpm.c;h=ebf294dd31da7cf25410ac4327f58a230833a1b9;hb=refs%2Fheads%2Fvserver;hp=ea7c25a50c7350c2e642481dfbe77ee1ef076ca3;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c index ea7c25a50..ebf294dd3 100644 --- a/arch/arm/mach-s3c2410/pm.c +++ b/arch/arm/mach-s3c2410/pm.c @@ -1,9 +1,9 @@ /* linux/arch/arm/mach-s3c2410/pm.c * - * Copyright (c) 2004 Simtec Electronics + * Copyright (c) 2004,2006 Simtec Electronics * Ben Dooks * - * S3C2410 Power Manager (Suspend-To-RAM) support + * S3C24XX Power Manager (Suspend-To-RAM) support * * See Documentation/arm/Samsung-S3C24XX/Suspend.txt for more information * @@ -26,7 +26,6 @@ * Thanks to Dimitry Andric for debugging */ -#include #include #include #include @@ -35,7 +34,9 @@ #include #include #include +#include +#include #include #include @@ -53,10 +54,6 @@ unsigned long s3c_pm_flags; -/* cache functions from arch/arm/mm/proc-arm920.S */ - -extern void arm920_flush_kern_cache_all(void); - #define PFX "s3c24xx-pm: " static struct sleep_save core_save[] = { @@ -86,19 +83,6 @@ static struct sleep_save core_save[] = { SAVE_ITEM(S3C2410_REFRESH), }; -/* this lot should be really saved by the IRQ code */ -static struct sleep_save irq_save[] = { - SAVE_ITEM(S3C2410_EXTINT0), - SAVE_ITEM(S3C2410_EXTINT1), - SAVE_ITEM(S3C2410_EXTINT2), - SAVE_ITEM(S3C2410_EINFLT0), - SAVE_ITEM(S3C2410_EINFLT1), - SAVE_ITEM(S3C2410_EINFLT2), - SAVE_ITEM(S3C2410_EINFLT3), - SAVE_ITEM(S3C2410_EINTMASK), - SAVE_ITEM(S3C2410_INTMSK) -}; - static struct sleep_save gpio_save[] = { SAVE_ITEM(S3C2410_GPACON), SAVE_ITEM(S3C2410_GPADAT), @@ -144,9 +128,11 @@ static struct sleep_save gpio_save[] = { SAVE_ITEM((va) + S3C2410_UBRDIV) static struct sleep_save uart_save[] = { - SAVE_UART(S3C2410_VA_UART0), - SAVE_UART(S3C2410_VA_UART1), - SAVE_UART(S3C2410_VA_UART2), + SAVE_UART(S3C24XX_VA_UART0), + SAVE_UART(S3C24XX_VA_UART1), +#ifndef CONFIG_CPU_S3C2400 + SAVE_UART(S3C24XX_VA_UART2), +#endif }; /* debug @@ -157,7 +143,7 @@ static struct sleep_save uart_save[] = { extern void printascii(const char *); -static void pm_dbg(const char *fmt, ...) +void pm_dbg(const char *fmt, ...) { va_list va; char buff[256]; @@ -391,7 +377,7 @@ void s3c2410_pm_do_save(struct sleep_save *ptr, int count) { for (; count > 0; count--, ptr++) { ptr->val = __raw_readl(ptr->reg); - DBG("saved %08lx value %08lx\n", ptr->reg, ptr->val); + DBG("saved %p value %08lx\n", ptr->reg, ptr->val); } } @@ -406,7 +392,7 @@ void s3c2410_pm_do_save(struct sleep_save *ptr, int count) void s3c2410_pm_do_restore(struct sleep_save *ptr, int count) { for (; count > 0; count--, ptr++) { - printk(KERN_DEBUG "restore %08lx (restore %08lx, was %08x)\n", + printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n", ptr->reg, ptr->val, __raw_readl(ptr->reg)); __raw_writel(ptr->val, ptr->reg); @@ -465,15 +451,14 @@ static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs) irqstate = s3c_irqwake_eintmask & (1L<>= S3C2410_GPIO_OFFSET(pin)*2; if (!irqstate) { - if (pinstate == 0x02) + if (pinstate == S3C2410_GPIO_IRQ) DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin); } else { - if (pinstate == 0x02) { + if (pinstate == S3C2410_GPIO_IRQ) { DBG("Disabling IRQ %d (pin %d)\n", irq, pin); - s3c2410_gpio_cfgpin(pin, 0x00); + s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT); } } } @@ -501,6 +486,9 @@ static void s3c2410_pm_configure_extint(void) } } +void (*pm_cpu_prep)(void); +void (*pm_cpu_sleep)(void); + #define any_allowed(mask, allow) (((mask) & (allow)) != (allow)) /* s3c2410_pm_enter @@ -511,7 +499,6 @@ static void s3c2410_pm_configure_extint(void) static int s3c2410_pm_enter(suspend_state_t state) { unsigned long regs_save[16]; - unsigned long tmp; /* ensure the debug is initialised (if enabled) */ @@ -519,6 +506,11 @@ static int s3c2410_pm_enter(suspend_state_t state) DBG("s3c2410_pm_enter(%d)\n", state); + if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) { + printk(KERN_ERR PFX "error: no cpu sleep functions set\n"); + return -EINVAL; + } + if (state != PM_SUSPEND_MEM) { printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n"); return -EINVAL; @@ -546,17 +538,9 @@ static int s3c2410_pm_enter(suspend_state_t state) DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys); - /* ensure at least GESTATUS3 has the resume address */ - - __raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3); - - DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3)); - DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4)); - /* save all necessary core registers not covered by the drivers */ s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save)); - s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save)); s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save)); s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save)); @@ -573,32 +557,40 @@ static int s3c2410_pm_enter(suspend_state_t state) /* ack any outstanding external interrupts before we go to sleep */ __raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND); + __raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND); + __raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND); + + /* call cpu specific preperation */ + + pm_cpu_prep(); /* flush cache back to ram */ - arm920_flush_kern_cache_all(); + flush_cache_all(); s3c2410_pm_check_store(); - // need to make some form of time-delta - /* send the cpu to sleep... */ __raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */ - s3c2410_cpu_suspend(regs_save); + /* s3c2410_cpu_save will also act as our return point from when + * we resume as it saves its own register state, so use the return + * code to differentiate return from save and return from sleep */ + + if (s3c2410_cpu_save(regs_save) == 0) { + flush_cache_all(); + pm_cpu_sleep(); + } - /* unset the return-from-sleep flag, to ensure reset */ + /* restore the cpu state */ - tmp = __raw_readl(S3C2410_GSTATUS2); - tmp &= S3C2410_GSTATUS2_OFFRESET; - __raw_writel(tmp, S3C2410_GSTATUS2); + cpu_init(); /* restore the system state */ 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(irq_save, ARRAY_SIZE(irq_save)); s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save)); s3c2410_pm_debug_init();