]> git.karo-electronics.de Git - linux-beck.git/commitdiff
[ARM] S3C: Move plat-s3c24xx pm.c support into plat-s3c
authorBen Dooks <ben-linux@fluff.org>
Fri, 12 Dec 2008 00:24:08 +0000 (00:24 +0000)
committerBen Dooks <ben-linux@fluff.org>
Sun, 8 Mar 2009 12:33:51 +0000 (12:33 +0000)
Move parts of the core and debug suspend code into the
plat-s3c for use with the new s3c64xx code.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>
arch/arm/plat-s3c/include/plat/pm.h
arch/arm/plat-s3c/pm.c
arch/arm/plat-s3c24xx/include/plat/pm-core.h [new file with mode: 0644]
arch/arm/plat-s3c24xx/pm.c

index 95c2612d49768371efb0ff7eab77d6c486129d8b..42c75e6d2ba5c78bcd0e680a1dda7db10c84b31d 100644 (file)
@@ -113,3 +113,30 @@ extern void s3c_pm_check_store(void);
 #define s3c_pm_check_restore() do { } while(0)
 #define s3c_pm_check_store()   do { } while(0)
 #endif
+
+/**
+ * s3c_pm_configure_extint() - ensure pins are correctly set for IRQ
+ *
+ * Setup all the necessary GPIO pins for waking the system on external
+ * interrupt.
+ */
+extern void s3c_pm_configure_extint(void);
+
+/**
+ * s3c_pm_restore_gpios() - restore the state of the gpios after sleep.
+ *
+ * Restore the state of the GPIO pins after sleep, which may involve ensuring
+ * that we do not glitch the state of the pins from that the bootloader's
+ * resume code has done.
+*/
+extern void s3c_pm_restore_gpios(void);
+
+/**
+ * s3c_pm_save_gpios() - save the state of the GPIOs for restoring after sleep.
+ *
+ * Save the GPIO states for resotration on resume. See s3c_pm_restore_gpios().
+ */
+extern void s3c_pm_save_gpios(void);
+
+extern void s3c_pm_save_core(void);
+extern void s3c_pm_restore_core(void);
index 122e9b91a7f41b99b64e5eb2358b61ae2a045ff3..fea58bea973d310390b3175cf7c3ac283a114e90 100644 (file)
 #include <linux/init.h>
 #include <linux/suspend.h>
 #include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/serial_core.h>
 #include <linux/io.h>
 
+#include <asm/cacheflush.h>
+#include <mach/hardware.h>
+
+#include <plat/regs-serial.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-mem.h>
+#include <mach/regs-irq.h>
+
 #include <plat/pm.h>
+#include <plat/pm-core.h>
 
 /* for external use */
 
 unsigned long s3c_pm_flags;
 
+/* Debug code:
+ *
+ * This code supports debug output to the low level UARTs for use on
+ * resume before the console layer is available.
+*/
+
 #ifdef CONFIG_S3C2410_PM_DEBUG
 extern void printascii(const char *);
 
@@ -37,8 +55,51 @@ void s3c_pm_dbg(const char *fmt, ...)
 
        printascii(buff);
 }
+
+static inline void s3c_pm_debug_init(void)
+{
+       /* restart uart clocks so we can use them to output */
+       s3c_pm_debug_init_uart();
+}
+
+#else
+#define s3c_pm_debug_init() do { } while(0)
+
 #endif /* CONFIG_S3C2410_PM_DEBUG */
 
+/* Save the UART configurations if we are configured for debug. */
+
+#ifdef CONFIG_S3C2410_PM_DEBUG
+
+#define SAVE_UART(va) \
+       SAVE_ITEM((va) + S3C2410_ULCON), \
+       SAVE_ITEM((va) + S3C2410_UCON), \
+       SAVE_ITEM((va) + S3C2410_UFCON), \
+       SAVE_ITEM((va) + S3C2410_UMCON), \
+       SAVE_ITEM((va) + S3C2410_UBRDIV)
+
+static struct sleep_save uart_save[] = {
+       SAVE_UART(S3C_VA_UART0),
+       SAVE_UART(S3C_VA_UART1),
+#ifndef CONFIG_CPU_S3C2400
+       SAVE_UART(S3C_VA_UART2),
+#endif
+};
+
+static void s3c_pm_save_uart(void)
+{
+       s3c_pm_do_save(uart_save, ARRAY_SIZE(uart_save));
+}
+
+static void s3c_pm_restore_uart(void)
+{
+       s3c_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));
+}
+#else
+static void s3c_pm_save_uart(void) { }
+static void s3c_pm_restore_uart(void) { }
+#endif
+
 
 /* helper functions to save and restore register state */
 
@@ -95,3 +156,153 @@ void s3c_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
+ *
+ * print any IRQs asserted at resume time (ie, we woke from)
+*/
+static void s3c_pm_show_resume_irqs(int start, unsigned long which,
+                                   unsigned long mask)
+{
+       int i;
+
+       which &= ~mask;
+
+       for (i = 0; i <= 31; i++) {
+               if (which & (1L<<i)) {
+                       S3C_PMDBG("IRQ %d asserted at resume\n", start+i);
+               }
+       }
+}
+
+
+void (*pm_cpu_prep)(void);
+void (*pm_cpu_sleep)(void);
+
+#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
+
+/* s3c_pm_enter
+ *
+ * central control for sleep/resume process
+*/
+
+static int s3c_pm_enter(suspend_state_t state)
+{
+       unsigned long regs_save[16];
+
+       /* ensure the debug is initialised (if enabled) */
+
+       s3c_pm_debug_init();
+
+       S3C_PMDBG("%s(%d)\n", __func__, state);
+
+       if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
+               printk(KERN_ERR "%s: error: no cpu sleep function\n", __func__);
+               return -EINVAL;
+       }
+
+       /* check if we have anything to wake-up with... bad things seem
+        * to happen if you suspend with no wakeup (system will often
+        * require a full power-cycle)
+       */
+
+       if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
+           !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
+               printk(KERN_ERR "%s: No wake-up sources!\n", __func__);
+               printk(KERN_ERR "%s: Aborting sleep\n", __func__);
+               return -EINVAL;
+       }
+
+       /* prepare check area if configured */
+
+       s3c_pm_check_prepare();
+
+       /* store the physical address of the register recovery block */
+
+       s3c_sleep_save_phys = virt_to_phys(regs_save);
+
+       S3C_PMDBG("s3c_sleep_save_phys=0x%08lx\n", s3c_sleep_save_phys);
+
+       /* save all necessary core registers not covered by the drivers */
+
+       s3c_pm_save_gpios();
+       s3c_pm_save_uart();
+       s3c_pm_save_core();
+
+       /* set the irq configuration for wake */
+
+       s3c_pm_configure_extint();
+
+       S3C_PMDBG("sleep: irq wakeup masks: %08lx,%08lx\n",
+           s3c_irqwake_intmask, s3c_irqwake_eintmask);
+
+       s3c_pm_arch_prepare_irqs();
+
+       /* call cpu specific preparation */
+
+       pm_cpu_prep();
+
+       /* flush cache back to ram */
+
+       flush_cache_all();
+
+       s3c_pm_check_store();
+
+       /* send the cpu to sleep... */
+
+       s3c_pm_arch_stop_clocks();
+
+       /* 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();
+       }
+
+       /* restore the cpu state using the kernel's cpu init code. */
+
+       cpu_init();
+
+       /* restore the system state */
+
+       s3c_pm_restore_core();
+       s3c_pm_restore_uart();
+       s3c_pm_restore_gpios();
+
+       s3c_pm_debug_init();
+
+       /* check what irq (if any) restored the system */
+
+       s3c_pm_arch_show_resume_irqs();
+
+       S3C_PMDBG("%s: post sleep, preparing to return\n", __func__);
+
+       s3c_pm_check_restore();
+
+       /* ok, let's return from sleep */
+
+       S3C_PMDBG("S3C PM Resume (post-restore)\n");
+       return 0;
+}
+
+static struct platform_suspend_ops s3c_pm_ops = {
+       .enter          = s3c_pm_enter,
+       .valid          = suspend_valid_only_mem,
+};
+
+/* s3c2410_pm_init
+ *
+ * Attach the power management functions. This should be called
+ * from the board specific initialisation if the board supports
+ * it.
+*/
+
+int __init s3c2410_pm_init(void)
+{
+       printk("S3C Power Management, Copyright 2004 Simtec Electronics\n");
+
+       suspend_set_ops(&s3c_pm_ops);
+       return 0;
+}
diff --git a/arch/arm/plat-s3c24xx/include/plat/pm-core.h b/arch/arm/plat-s3c24xx/include/plat/pm-core.h
new file mode 100644 (file)
index 0000000..c758821
--- /dev/null
@@ -0,0 +1,59 @@
+/* linux/arch/arm/plat-s3c24xx/include/plat/pll.h
+ *
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C24xx - PM core support for arch/arm/plat-s3c/pm.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+static inline void s3c_pm_debug_init_uart(void)
+{
+       unsigned long tmp = __raw_readl(S3C2410_CLKCON);
+
+       /* re-start uart clocks */
+       tmp |= S3C2410_CLKCON_UART0;
+       tmp |= S3C2410_CLKCON_UART1;
+       tmp |= S3C2410_CLKCON_UART2;
+
+       __raw_writel(tmp, S3C2410_CLKCON);
+       udelay(10);
+}
+
+static inline void s3c_pm_arch_prepare_irqs(void)
+{
+       __raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
+       __raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
+
+       /* 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);
+
+}
+
+static inline void s3c_pm_arch_stop_clocks(void)
+{
+       __raw_writel(0x00, S3C2410_CLKCON);  /* turn off clocks over sleep */
+}
+
+static void s3c_pm_show_resume_irqs(int start, unsigned long which,
+                                   unsigned long mask);
+
+static inline void s3c_pm_arch_show_resume_irqs(void)
+{
+       S3C_PMDBG("post sleep: IRQs 0x%08x, 0x%08x\n",
+                 __raw_readl(S3C2410_SRCPND),
+                 __raw_readl(S3C2410_EINTPEND));
+
+       s3c_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
+                               s3c_irqwake_intmask);
+
+       s3c_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
+                               s3c_irqwake_eintmask);
+}
index e2ae12da16e731db8265e86a2d9574c275f75833..062a29339a9189447795bf32e0385a6da881a170 100644 (file)
@@ -34,9 +34,6 @@
 #include <linux/serial_core.h>
 #include <linux/io.h>
 
-#include <asm/cacheflush.h>
-#include <mach/hardware.h>
-
 #include <plat/regs-serial.h>
 #include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
@@ -47,7 +44,6 @@
 
 #include <plat/pm.h>
 
-
 #define PFX "s3c24xx-pm: "
 
 static struct sleep_save core_save[] = {
@@ -115,66 +111,6 @@ static struct sleep_save misc_save[] = {
        SAVE_ITEM(S3C2410_DCLKCON),
 };
 
-#ifdef CONFIG_S3C2410_PM_DEBUG
-
-#define SAVE_UART(va) \
-       SAVE_ITEM((va) + S3C2410_ULCON), \
-       SAVE_ITEM((va) + S3C2410_UCON), \
-       SAVE_ITEM((va) + S3C2410_UFCON), \
-       SAVE_ITEM((va) + S3C2410_UMCON), \
-       SAVE_ITEM((va) + S3C2410_UBRDIV)
-
-static struct sleep_save uart_save[] = {
-       SAVE_UART(S3C24XX_VA_UART0),
-       SAVE_UART(S3C24XX_VA_UART1),
-#ifndef CONFIG_CPU_S3C2400
-       SAVE_UART(S3C24XX_VA_UART2),
-#endif
-};
-
-/* debug
- *
- * we send the debug to printascii() to allow it to be seen if the
- * system never wakes up from the sleep
-*/
-
-static void s3c2410_pm_debug_init(void)
-{
-       unsigned long tmp = __raw_readl(S3C2410_CLKCON);
-
-       /* re-start uart clocks */
-       tmp |= S3C2410_CLKCON_UART0;
-       tmp |= S3C2410_CLKCON_UART1;
-       tmp |= S3C2410_CLKCON_UART2;
-
-       __raw_writel(tmp, S3C2410_CLKCON);
-       udelay(10);
-}
-
-#else
-#define s3c2410_pm_debug_init() do { } while(0)
-
-static struct sleep_save uart_save[] = {};
-#endif
-
-/* s3c2410_pm_show_resume_irqs
- *
- * print any IRQs asserted at resume time (ie, we woke from)
-*/
-
-static void s3c2410_pm_show_resume_irqs(int start, unsigned long which,
-                                       unsigned long mask)
-{
-       int i;
-
-       which &= ~mask;
-
-       for (i = 0; i <= 31; i++) {
-               if ((which) & (1L<<i)) {
-                       S3C_PMDBG("IRQ %d asserted at resume\n", start+i);
-               }
-       }
-}
 
 /* s3c_pm_check_resume_pin
  *
@@ -206,12 +142,12 @@ static void s3c_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
        }
 }
 
-/* s3c2410_pm_configure_extint
+/* s3c_pm_configure_extint
  *
  * configure all external interrupt pins
 */
 
-static void s3c2410_pm_configure_extint(void)
+void s3c_pm_configure_extint(void)
 {
        int pin;
 
@@ -235,12 +171,12 @@ static void s3c2410_pm_configure_extint(void)
 #define OFFS_DAT       (S3C2410_GPADAT - S3C2410_GPACON)
 #define OFFS_UP                (S3C2410_GPBUP  - S3C2410_GPBCON)
 
-/* s3c2410_pm_save_gpios()
+/* s3c_pm_save_gpios()
  *
  * Save the state of the GPIOs
  */
 
-static void s3c2410_pm_save_gpios(void)
+void s3c_pm_save_gpios(void)
 {
        struct gpio_sleep *gps = gpio_save;
        unsigned int gpio;
@@ -279,7 +215,10 @@ static inline int is_out(unsigned long con)
        return con == 1;
 }
 
-/* s3c2410_pm_restore_gpio()
+/**
+ * s3c2410_pm_restore_gpio() - restore the given GPIO bank
+ * @index: The number of the GPIO bank being resumed.
+ * @gps: The sleep confgiuration for the bank.
  *
  * Restore one of the GPIO banks that was saved during suspend. This is
  * not as simple as once thought, due to the possibility of glitches
@@ -397,7 +336,7 @@ static void s3c2410_pm_restore_gpio(int index, struct gpio_sleep *gps)
  * Restore the state of the GPIOs
  */
 
-static void s3c2410_pm_restore_gpios(void)
+void s3c_pm_restore_gpios(void)
 {
        struct gpio_sleep *gps = gpio_save;
        int gpio;
@@ -407,150 +346,15 @@ static void s3c2410_pm_restore_gpios(void)
        }
 }
 
-void (*pm_cpu_prep)(void);
-void (*pm_cpu_sleep)(void);
-
-#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
-
-/* s3c2410_pm_enter
- *
- * central control for sleep/resume process
-*/
-
-static int s3c2410_pm_enter(suspend_state_t state)
+void s3c_pm_restore_core(void)
 {
-       unsigned long regs_save[16];
-
-       /* ensure the debug is initialised (if enabled) */
-
-       s3c2410_pm_debug_init();
-
-       S3C_PMDBG("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;
-       }
-
-       /* check if we have anything to wake-up with... bad things seem
-        * to happen if you suspend with no wakeup (system will often
-        * require a full power-cycle)
-       */
-
-       if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
-           !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
-               printk(KERN_ERR PFX "No sources enabled for wake-up!\n");
-               printk(KERN_ERR PFX "Aborting sleep\n");
-               return -EINVAL;
-       }
-
-       /* prepare check area if configured */
-
-       s3c_pm_check_prepare();
-
-       /* store the physical address of the register recovery block */
-
-       s3c_sleep_save_phys = virt_to_phys(regs_save);
-
-       S3C_PMDBG("s3c_sleep_save_phys=0x%08lx\n", s3c_sleep_save_phys);
-
-       /* save all necessary core registers not covered by the drivers */
-
-       s3c2410_pm_save_gpios();
-       s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save));
-       s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
-       s3c_pm_do_save(uart_save, ARRAY_SIZE(uart_save));
-
-       /* set the irq configuration for wake */
-
-       s3c2410_pm_configure_extint();
-
-       S3C_PMDBG("sleep: irq wakeup masks: %08lx,%08lx\n",
-           s3c_irqwake_intmask, s3c_irqwake_eintmask);
-
-       __raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
-       __raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
-
-       /* 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 preparation */
-
-       pm_cpu_prep();
-
-       /* flush cache back to ram */
-
-       flush_cache_all();
-
-       s3c_pm_check_store();
-
-       /* send the cpu to sleep... */
-
-       __raw_writel(0x00, S3C2410_CLKCON);  /* turn off clocks over sleep */
-
-       /* 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();
-       }
-
-       /* restore the cpu state */
-
-       cpu_init();
-
-       /* restore the system state */
-
        s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
        s3c_pm_do_restore(misc_save, ARRAY_SIZE(misc_save));
-       s3c_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));
-       s3c2410_pm_restore_gpios();
-
-       s3c2410_pm_debug_init();
-
-       /* check what irq (if any) restored the system */
-
-       S3C_PMDBG("post sleep: IRQs 0x%08x, 0x%08x\n",
-           __raw_readl(S3C2410_SRCPND),
-           __raw_readl(S3C2410_EINTPEND));
-
-       s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
-                                   s3c_irqwake_intmask);
-
-       s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
-                                   s3c_irqwake_eintmask);
-
-       S3C_PMDBG("post sleep, preparing to return\n");
-
-       s3c_pm_check_restore();
-
-       /* ok, let's return from sleep */
-
-       S3C_PMDBG("S3C2410 PM Resume (post-restore)\n");
-       return 0;
 }
 
-static struct platform_suspend_ops s3c2410_pm_ops = {
-       .enter          = s3c2410_pm_enter,
-       .valid          = suspend_valid_only_mem,
-};
-
-/* s3c2410_pm_init
- *
- * Attach the power management functions. This should be called
- * from the board specific initialisation if the board supports
- * it.
-*/
-
-int __init s3c2410_pm_init(void)
+void s3c_pm_save_core(void)
 {
-       printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n");
-
-       suspend_set_ops(&s3c2410_pm_ops);
-       return 0;
+       s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save));
+       s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
 }
+