aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/plat-s3c/include/plat/pm.h19
-rw-r--r--arch/arm/plat-s3c/pm.c61
-rw-r--r--arch/arm/plat-s3c24xx/include/plat/map.h2
3 files changed, 60 insertions, 22 deletions
diff --git a/arch/arm/plat-s3c/include/plat/pm.h b/arch/arm/plat-s3c/include/plat/pm.h
index f121a5ac7420..c27b8cf5d891 100644
--- a/arch/arm/plat-s3c/include/plat/pm.h
+++ b/arch/arm/plat-s3c/include/plat/pm.h
@@ -71,6 +71,25 @@ struct sleep_save {
71#define SAVE_ITEM(x) \ 71#define SAVE_ITEM(x) \
72 { .reg = (x) } 72 { .reg = (x) }
73 73
74/**
75 * struct pm_uart_save - save block for core UART
76 * @ulcon: Save value for S3C2410_ULCON
77 * @ucon: Save value for S3C2410_UCON
78 * @ufcon: Save value for S3C2410_UFCON
79 * @umcon: Save value for S3C2410_UMCON
80 * @ubrdiv: Save value for S3C2410_UBRDIV
81 *
82 * Save block for UART registers to be held over sleep and restored if they
83 * are needed (say by debug).
84*/
85struct pm_uart_save {
86 u32 ulcon;
87 u32 ucon;
88 u32 ufcon;
89 u32 umcon;
90 u32 ubrdiv;
91};
92
74/* helper functions to save/restore lists of registers. */ 93/* helper functions to save/restore lists of registers. */
75 94
76extern void s3c_pm_do_save(struct sleep_save *ptr, int count); 95extern void s3c_pm_do_save(struct sleep_save *ptr, int count);
diff --git a/arch/arm/plat-s3c/pm.c b/arch/arm/plat-s3c/pm.c
index e320b0ff3852..78bf50a14027 100644
--- a/arch/arm/plat-s3c/pm.c
+++ b/arch/arm/plat-s3c/pm.c
@@ -72,33 +72,50 @@ static inline void s3c_pm_debug_init(void)
72 72
73#ifdef CONFIG_S3C2410_PM_DEBUG 73#ifdef CONFIG_S3C2410_PM_DEBUG
74 74
75#define SAVE_UART(va) \ 75struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
76 SAVE_ITEM((va) + S3C2410_ULCON), \ 76
77 SAVE_ITEM((va) + S3C2410_UCON), \ 77static void s3c_pm_save_uart(unsigned int uart, struct pm_uart_save *save)
78 SAVE_ITEM((va) + S3C2410_UFCON), \ 78{
79 SAVE_ITEM((va) + S3C2410_UMCON), \ 79 void __iomem *regs = S3C_VA_UARTx(uart);
80 SAVE_ITEM((va) + S3C2410_UBRDIV) 80
81 81 save->ulcon = __raw_readl(regs + S3C2410_ULCON);
82static struct sleep_save uart_save[] = { 82 save->ucon = __raw_readl(regs + S3C2410_UCON);
83 SAVE_UART(S3C_VA_UART0), 83 save->ufcon = __raw_readl(regs + S3C2410_UFCON);
84 SAVE_UART(S3C_VA_UART1), 84 save->umcon = __raw_readl(regs + S3C2410_UMCON);
85#ifndef CONFIG_CPU_S3C2400 85 save->ubrdiv = __raw_readl(regs + S3C2410_UBRDIV);
86 SAVE_UART(S3C_VA_UART2), 86}
87#endif
88};
89 87
90static void s3c_pm_save_uart(void) 88static void s3c_pm_save_uarts(void)
91{ 89{
92 s3c_pm_do_save(uart_save, ARRAY_SIZE(uart_save)); 90 struct pm_uart_save *save = uart_save;
91 unsigned int uart;
92
93 for (uart = 0; uart < CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++)
94 s3c_pm_save_uart(uart, save);
95}
96
97static void s3c_pm_restore_uart(unsigned int uart, struct pm_uart_save *save)
98{
99 void __iomem *regs = S3C_VA_UARTx(uart);
100
101 __raw_writel(save->ulcon, regs + S3C2410_ULCON);
102 __raw_writel(save->ucon, regs + S3C2410_UCON);
103 __raw_writel(save->ufcon, regs + S3C2410_UFCON);
104 __raw_writel(save->umcon, regs + S3C2410_UMCON);
105 __raw_writel(save->ubrdiv, regs + S3C2410_UBRDIV);
93} 106}
94 107
95static void s3c_pm_restore_uart(void) 108static void s3c_pm_restore_uarts(void)
96{ 109{
97 s3c_pm_do_restore(uart_save, ARRAY_SIZE(uart_save)); 110 struct pm_uart_save *save = uart_save;
111 unsigned int uart;
112
113 for (uart = 0; uart < CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++)
114 s3c_pm_restore_uart(uart, save);
98} 115}
99#else 116#else
100static void s3c_pm_save_uart(void) { } 117static void s3c_pm_save_uarts(void) { }
101static void s3c_pm_restore_uart(void) { } 118static void s3c_pm_restore_uarts(void) { }
102#endif 119#endif
103 120
104/* The IRQ ext-int code goes here, it is too small to currently bother 121/* The IRQ ext-int code goes here, it is too small to currently bother
@@ -250,7 +267,7 @@ static int s3c_pm_enter(suspend_state_t state)
250 /* save all necessary core registers not covered by the drivers */ 267 /* save all necessary core registers not covered by the drivers */
251 268
252 s3c_pm_save_gpios(); 269 s3c_pm_save_gpios();
253 s3c_pm_save_uart(); 270 s3c_pm_save_uarts();
254 s3c_pm_save_core(); 271 s3c_pm_save_core();
255 272
256 /* set the irq configuration for wake */ 273 /* set the irq configuration for wake */
@@ -293,7 +310,7 @@ static int s3c_pm_enter(suspend_state_t state)
293 /* restore the system state */ 310 /* restore the system state */
294 311
295 s3c_pm_restore_core(); 312 s3c_pm_restore_core();
296 s3c_pm_restore_uart(); 313 s3c_pm_restore_uarts();
297 s3c_pm_restore_gpios(); 314 s3c_pm_restore_gpios();
298 315
299 s3c_pm_debug_init(); 316 s3c_pm_debug_init();
diff --git a/arch/arm/plat-s3c24xx/include/plat/map.h b/arch/arm/plat-s3c24xx/include/plat/map.h
index fef8ea8b8e1e..eed8f78e7593 100644
--- a/arch/arm/plat-s3c24xx/include/plat/map.h
+++ b/arch/arm/plat-s3c24xx/include/plat/map.h
@@ -31,6 +31,8 @@
31#define S3C24XX_SZ_UART SZ_1M 31#define S3C24XX_SZ_UART SZ_1M
32#define S3C_UART_OFFSET (0x4000) 32#define S3C_UART_OFFSET (0x4000)
33 33
34#define S3C_VA_UARTx(uart) (S3C_VA_UART + ((uart * S3C_UART_OFFSET)))
35
34/* Timers */ 36/* Timers */
35#define S3C24XX_VA_TIMER S3C_VA_TIMER 37#define S3C24XX_VA_TIMER S3C_VA_TIMER
36#define S3C2410_PA_TIMER (0x51000000) 38#define S3C2410_PA_TIMER (0x51000000)