aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-s3c2410/pm.c11
-rw-r--r--arch/arm/mach-s3c2440/mach-gta02.c3
-rw-r--r--arch/arm/mach-s3c6400/include/mach/map.h3
-rw-r--r--arch/arm/mach-s3c6410/mach-smdk6410.c17
-rw-r--r--arch/arm/plat-s3c/include/plat/pm.h3
-rw-r--r--arch/arm/plat-s3c/pm-check.c34
-rw-r--r--arch/arm/plat-s3c/pm-gpio.c4
-rw-r--r--arch/arm/plat-s3c/pm.c25
-rw-r--r--arch/arm/plat-s3c24xx/irq-pm.c3
-rw-r--r--arch/arm/plat-s3c24xx/pm.c1
-rw-r--r--arch/arm/plat-s3c64xx/cpu.c5
-rw-r--r--arch/arm/plat-s3c64xx/include/plat/pm-core.h40
-rw-r--r--arch/arm/plat-s3c64xx/include/plat/regs-gpio-memport.h25
-rw-r--r--arch/arm/plat-s3c64xx/include/plat/regs-gpio.h85
-rw-r--r--arch/arm/plat-s3c64xx/include/plat/regs-modem.h31
-rw-r--r--arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h3
-rw-r--r--arch/arm/plat-s3c64xx/irq-eint.c1
-rw-r--r--arch/arm/plat-s3c64xx/irq-pm.c23
-rw-r--r--arch/arm/plat-s3c64xx/pm.c22
-rw-r--r--arch/arm/plat-s3c64xx/sleep.S12
-rw-r--r--drivers/mmc/host/sdhci-s3c.c27
-rw-r--r--drivers/video/s3c-fb.c1
22 files changed, 317 insertions, 62 deletions
diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
index 24fb0a19001..87fc481d92d 100644
--- a/arch/arm/mach-s3c2410/pm.c
+++ b/arch/arm/mach-s3c2410/pm.c
@@ -37,21 +37,14 @@
#include <plat/cpu.h>
#include <plat/pm.h>
-#ifdef CONFIG_S3C2410_PM_DEBUG
-extern void pm_dbg(const char *fmt, ...);
-#define DBG(fmt...) pm_dbg(fmt)
-#else
-#define DBG(fmt...) printk(KERN_DEBUG fmt)
-#endif
-
static void s3c2410_pm_prepare(void)
{
/* ensure at least GSTATUS3 has the resume address */
__raw_writel(virt_to_phys(s3c_cpu_resume), S3C2410_GSTATUS3);
- DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
- DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
+ S3C_PMDBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
+ S3C_PMDBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
if (machine_is_h1940()) {
void *base = phys_to_virt(H1940_SUSPEND_CHECK);
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index e90f82bdfc3..c9c5391f3d0 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -743,9 +743,6 @@ struct pcf50633_platform_data gta02_pcf_pdata = {
.min_uV = 0,
.max_uV = 3300000,
.valid_modes_mask = REGULATOR_MODE_NORMAL,
- .state_mem = {
- .enabled = 1,
- },
},
.num_consumer_supplies = 0,
},
diff --git a/arch/arm/mach-s3c6400/include/mach/map.h b/arch/arm/mach-s3c6400/include/mach/map.h
index cff27d813fc..baf1c0f1ea5 100644
--- a/arch/arm/mach-s3c6400/include/mach/map.h
+++ b/arch/arm/mach-s3c6400/include/mach/map.h
@@ -52,6 +52,9 @@
#define S3C64XX_PA_VIC0 (0x71200000)
#define S3C64XX_PA_VIC1 (0x71300000)
+#define S3C64XX_PA_MODEM (0x74108000)
+#define S3C64XX_VA_MODEM S3C_ADDR(0x00600000)
+
/* place VICs close together */
#define S3C_VA_VIC0 (S3C_VA_IRQ + 0x00)
#define S3C_VA_VIC1 (S3C_VA_IRQ + 0x10000)
diff --git a/arch/arm/mach-s3c6410/mach-smdk6410.c b/arch/arm/mach-s3c6410/mach-smdk6410.c
index a3d3b3187de..cf4167e88ec 100644
--- a/arch/arm/mach-s3c6410/mach-smdk6410.c
+++ b/arch/arm/mach-s3c6410/mach-smdk6410.c
@@ -39,7 +39,9 @@
#include <asm/mach-types.h>
#include <plat/regs-serial.h>
+#include <plat/regs-modem.h>
#include <plat/regs-gpio.h>
+#include <plat/regs-sys.h>
#include <plat/iic.h>
#include <plat/fb.h>
#include <plat/pm.h>
@@ -157,12 +159,23 @@ static struct i2c_board_info i2c_devs1[] __initdata = {
static void __init smdk6410_map_io(void)
{
+ u32 tmp;
+
s3c64xx_init_io(smdk6410_iodesc, ARRAY_SIZE(smdk6410_iodesc));
s3c24xx_init_clocks(12000000);
s3c24xx_init_uarts(smdk6410_uartcfgs, ARRAY_SIZE(smdk6410_uartcfgs));
- /* do not change gpio settings over sleep to xxxSLPCON */
- __raw_writel(S3C64XX_SLPEN_CFG_BYSLPEN, S3C64XX_SLPEN);
+ /* set the LCD type */
+
+ tmp = __raw_readl(S3C64XX_SPCON);
+ tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
+ tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
+ __raw_writel(tmp, S3C64XX_SPCON);
+
+ /* remove the lcd bypass */
+ tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
+ tmp &= ~MIFPCON_LCD_BYPASS;
+ __raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
}
static void __init smdk6410_machine_init(void)
diff --git a/arch/arm/plat-s3c/include/plat/pm.h b/arch/arm/plat-s3c/include/plat/pm.h
index 9b9a88592ee..6694107db90 100644
--- a/arch/arm/plat-s3c/include/plat/pm.h
+++ b/arch/arm/plat-s3c/include/plat/pm.h
@@ -146,10 +146,12 @@ static inline void s3c_pm_debug_smdkled(u32 set, u32 clear) { }
#ifdef CONFIG_S3C2410_PM_CHECK
extern void s3c_pm_check_prepare(void);
extern void s3c_pm_check_restore(void);
+extern void s3c_pm_check_cleanup(void);
extern void s3c_pm_check_store(void);
#else
#define s3c_pm_check_prepare() do { } while(0)
#define s3c_pm_check_restore() do { } while(0)
+#define s3c_pm_check_cleanup() do { } while(0)
#define s3c_pm_check_store() do { } while(0)
#endif
@@ -179,3 +181,4 @@ extern void s3c_pm_save_gpios(void);
extern void s3c_pm_save_core(void);
extern void s3c_pm_restore_core(void);
+
diff --git a/arch/arm/plat-s3c/pm-check.c b/arch/arm/plat-s3c/pm-check.c
index 7f21bef09c3..39f2555564d 100644
--- a/arch/arm/plat-s3c/pm-check.c
+++ b/arch/arm/plat-s3c/pm-check.c
@@ -43,7 +43,7 @@ typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
/* s3c_pm_run_res
*
- * go thorugh the given resource list, and look for system ram
+ * go through the given resource list, and look for system ram
*/
static void s3c_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
@@ -136,7 +136,7 @@ void s3c_pm_check_store(void)
/* in_region
*
- * return TRUE if the area defined by ptr..ptr+size contatins the
+ * return TRUE if the area defined by ptr..ptr+size contains the
* what..what+whatsz
*/
@@ -152,7 +152,7 @@ static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
}
/**
- * s3c_pm_runcheck*() - helper to check a resource on restore.
+ * s3c_pm_runcheck() - helper to check a resource on restore.
* @res: The resource to check
* @vak: Pointer to list of CRC32 values to check.
*
@@ -166,9 +166,12 @@ static u32 *s3c_pm_runcheck(struct resource *res, u32 *val)
void *save_at = phys_to_virt(s3c_sleep_save_phys);
unsigned long addr;
unsigned long left;
+ void *stkpage;
void *ptr;
u32 calc;
+ stkpage = (void *)((u32)&calc & ~PAGE_MASK);
+
for (addr = res->start; addr < res->end;
addr += CHECK_CHUNKSIZE) {
left = res->end - addr;
@@ -178,6 +181,11 @@ static u32 *s3c_pm_runcheck(struct resource *res, u32 *val)
ptr = phys_to_virt(addr);
+ if (in_region(ptr, left, stkpage, 4096)) {
+ S3C_PMDBG("skipping %08lx, has stack in\n", addr);
+ goto skip_check;
+ }
+
if (in_region(ptr, left, crcs, crc_size)) {
S3C_PMDBG("skipping %08lx, has crc block in\n", addr);
goto skip_check;
@@ -214,9 +222,21 @@ static u32 *s3c_pm_runcheck(struct resource *res, u32 *val)
*/
void s3c_pm_check_restore(void)
{
- if (crcs != NULL) {
+ if (crcs != NULL)
s3c_pm_run_sysram(s3c_pm_runcheck, crcs);
- kfree(crcs);
- crcs = NULL;
- }
}
+
+/**
+ * s3c_pm_check_cleanup() - free memory resources
+ *
+ * Free the resources that where allocated by the suspend
+ * memory check code. We do this separately from the
+ * s3c_pm_check_restore() function as we cannot call any
+ * functions that might sleep during that resume.
+ */
+void s3c_pm_check_cleanup(void)
+{
+ kfree(crcs);
+ crcs = NULL;
+}
+
diff --git a/arch/arm/plat-s3c/pm-gpio.c b/arch/arm/plat-s3c/pm-gpio.c
index 6b5d6ec1dd7..b58d000d8b3 100644
--- a/arch/arm/plat-s3c/pm-gpio.c
+++ b/arch/arm/plat-s3c/pm-gpio.c
@@ -260,7 +260,7 @@ static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
void __iomem *base = chip->base;
u32 old_gpcon[2];
u32 old_gpdat = __raw_readl(base + OFFS_DAT);
- u32 gps_gpdat = chip->pm_save[1];
+ u32 gps_gpdat = chip->pm_save[2];
/* First, modify the CON settings */
@@ -284,7 +284,7 @@ static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
__raw_writel(chip->pm_save[3], base + OFFS_UP);
if (chip->chip.ngpio > 8) {
- S3C_PMDBG("%s: CON4 %08x => %08x, DAT %08x => %08x\n",
+ S3C_PMDBG("%s: CON4 %08x,%08x => %08x,%08x, DAT %08x => %08x\n",
chip->chip.label, old_gpcon[0], old_gpcon[1],
__raw_readl(base - 4),
__raw_readl(base + OFFS_CON),
diff --git a/arch/arm/plat-s3c/pm.c b/arch/arm/plat-s3c/pm.c
index 3091837d177..422dea207b0 100644
--- a/arch/arm/plat-s3c/pm.c
+++ b/arch/arm/plat-s3c/pm.c
@@ -197,7 +197,7 @@ void s3c_pm_do_restore(struct sleep_save *ptr, int count)
/**
* s3c_pm_do_restore_core() - early restore register values from save list.
*
- * This is simialr to s3c_pm_do_restore() except we try and minimise the
+ * This is similar to s3c_pm_do_restore() except we try and minimise the
* side effects of the function in case registers that hardware might need
* to work has been restored.
*
@@ -267,10 +267,6 @@ static int s3c_pm_enter(suspend_state_t state)
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);
@@ -333,17 +329,30 @@ static int s3c_pm_enter(suspend_state_t state)
S3C_PMDBG("%s: post sleep, preparing to return\n", __func__);
+ s3c_pm_check_restore();
+
/* LEDs should now be 1110 */
s3c_pm_debug_smdkled(1 << 1, 0);
- s3c_pm_check_restore();
-
/* ok, let's return from sleep */
S3C_PMDBG("S3C PM Resume (post-restore)\n");
return 0;
}
+static int s3c_pm_prepare(void)
+{
+ /* prepare check area if configured */
+
+ s3c_pm_check_prepare();
+ return 0;
+}
+
+static void s3c_pm_finish(void)
+{
+ s3c_pm_check_cleanup();
+}
+
static int s3c_pm_begin(suspend_state_t state)
{
int ret = 0;
@@ -356,6 +365,8 @@ static int s3c_pm_begin(suspend_state_t state)
static struct platform_suspend_ops s3c_pm_ops = {
.enter = s3c_pm_enter,
+ .prepare = s3c_pm_prepare,
+ .finish = s3c_pm_finish,
.valid = suspend_valid_only_mem,
.begin = s3c_pm_begin,
};
diff --git a/arch/arm/plat-s3c24xx/irq-pm.c b/arch/arm/plat-s3c24xx/irq-pm.c
index 04352bf397c..925514e60e7 100644
--- a/arch/arm/plat-s3c24xx/irq-pm.c
+++ b/arch/arm/plat-s3c24xx/irq-pm.c
@@ -35,9 +35,6 @@ int s3c_irq_wake(unsigned int irqno, unsigned int state)
{
unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
- if (irqno >= IRQ_EINT4)
- return s3c_irqext_wake(irqno, state);
-
if (!(s3c_irqwake_intallow & irqbit))
return -ENOENT;
diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c
index e28d9bc22ae..74c7006e51c 100644
--- a/arch/arm/plat-s3c24xx/pm.c
+++ b/arch/arm/plat-s3c24xx/pm.c
@@ -133,6 +133,7 @@ void s3c_pm_configure_extint(void)
}
}
+
void s3c_pm_restore_core(void)
{
s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
diff --git a/arch/arm/plat-s3c64xx/cpu.c b/arch/arm/plat-s3c64xx/cpu.c
index 278a04d5c57..58b39fccd15 100644
--- a/arch/arm/plat-s3c64xx/cpu.c
+++ b/arch/arm/plat-s3c64xx/cpu.c
@@ -98,6 +98,11 @@ static struct map_desc s3c_iodesc[] __initdata = {
.pfn = __phys_to_pfn(S3C64XX_PA_GPIO),
.length = SZ_4K,
.type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S3C64XX_VA_MODEM,
+ .pfn = __phys_to_pfn(S3C64XX_PA_MODEM),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
},
};
diff --git a/arch/arm/plat-s3c64xx/include/plat/pm-core.h b/arch/arm/plat-s3c64xx/include/plat/pm-core.h
index 8906c9fd443..10d89baa4a0 100644
--- a/arch/arm/plat-s3c64xx/include/plat/pm-core.h
+++ b/arch/arm/plat-s3c64xx/include/plat/pm-core.h
@@ -19,7 +19,7 @@ static inline void s3c_pm_debug_init_uart(void)
u32 tmp = __raw_readl(S3C_PCLK_GATE);
/* As a note, since the S3C64XX UARTs generally have multiple
- * clock sources, we simply enable PCLK at the momemnt and hope
+ * clock sources, we simply enable PCLK at the moment and hope
* that the resume settings for the UART are suitable for the
* use with PCLK.
*/
@@ -70,6 +70,7 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
u32 ucon_clk = ucon & S3C6400_UCON_CLKMASK;
u32 save_clk = save->ucon & S3C6400_UCON_CLKMASK;
u32 new_ucon;
+ u32 delta;
/* S3C64XX UART blocks only support level interrupts, so ensure that
* when we restore unused UART blocks we force the level interrupt
@@ -83,26 +84,23 @@ static inline void s3c_pm_arch_update_uart(void __iomem *regs,
*/
if (ucon_clk != save_clk) {
new_ucon = save->ucon;
- new_ucon &= ~S3C6400_UCON_CLKMASK;
-
- /* check for illegal change of UCLK, and fixup */
-
- if (ucon_clk == S3C6400_UCON_UCLK0 &&
- save_clk == S3C6400_UCON_PCLK2)
- new_ucon |= S3C6400_UCON_PCLK;
-
- if (ucon_clk == S3C6400_UCON_UCLK1 &&
- save_clk == S3C6400_UCON_PCLK)
- new_ucon |= S3C6400_UCON_PCLK2;
-
- if (ucon_clk == S3C6400_UCON_PCLK &&
- save_clk == S3C6400_UCON_PCLK2)
- new_ucon |= S3C6400_UCON_PCLK;
-
- if (ucon_clk == S3C6400_UCON_PCLK2 &&
- save_clk == S3C6400_UCON_PCLK)
- new_ucon |= S3C6400_UCON_PCLK2;
-
+ delta = ucon_clk ^ save_clk;
+
+ /* change from UCLKx => wrong PCLK,
+ * either UCLK can be tested for by a bit-test
+ * with UCLK0 */
+ if (ucon_clk & S3C6400_UCON_UCLK0 &&
+ !(save_clk & S3C6400_UCON_UCLK0) &&
+ delta & S3C6400_UCON_PCLK2) {
+ new_ucon &= ~S3C6400_UCON_UCLK0;
+ } else if (delta == S3C6400_UCON_PCLK2) {
+ /* as an precaution, don't change from
+ * PCLK2 => PCLK or vice-versa */
+ new_ucon ^= S3C6400_UCON_PCLK2;
+ }
+
+ S3C_PMDBG("ucon change %04x => %04x (save=%04x)\n",
+ ucon, new_ucon, save->ucon);
save->ucon = new_ucon;
}
}
diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-gpio-memport.h b/arch/arm/plat-s3c64xx/include/plat/regs-gpio-memport.h
new file mode 100644
index 00000000000..82342f6fd27
--- /dev/null
+++ b/arch/arm/plat-s3c64xx/include/plat/regs-gpio-memport.h
@@ -0,0 +1,25 @@
+/* linux/arch/arm/plat-s3c64xx/include/mach/regs-gpio-memport.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ * http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX - GPIO memory port register definitions
+ */
+
+#ifndef __ASM_PLAT_S3C64XX_REGS_GPIO_MEMPORT_H
+#define __ASM_PLAT_S3C64XX_REGS_GPIO_MEMPORT_H __FILE__
+
+#define S3C64XX_MEM0CONSTOP S3C64XX_GPIOREG(0x1B0)
+#define S3C64XX_MEM1CONSTOP S3C64XX_GPIOREG(0x1B4)
+
+#define S3C64XX_MEM0CONSLP0 S3C64XX_GPIOREG(0x1C0)
+#define S3C64XX_MEM0CONSLP1 S3C64XX_GPIOREG(0x1C4)
+#define S3C64XX_MEM1CONSLP S3C64XX_GPIOREG(0x1C8)
+
+#define S3C64XX_MEM0DRVCON S3C64XX_GPIOREG(0x1D0)
+#define S3C64XX_MEM1DRVCON S3C64XX_GPIOREG(0x1D4)
+
+#endif /* __ASM_PLAT_S3C64XX_REGS_GPIO_MEMPORT_H */
+
diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h b/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h
index 17944803a32..81f7f6e6832 100644
--- a/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h
+++ b/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h
@@ -33,6 +33,91 @@
#define S3C64XX_GPP_BASE S3C64XX_GPIOREG(0x0160)
#define S3C64XX_GPQ_BASE S3C64XX_GPIOREG(0x0180)
+/* SPCON */
+
+#define S3C64XX_SPCON S3C64XX_GPIOREG(0x1A0)
+
+#define S3C64XX_SPCON_DRVCON_CAM_MASK (0x3 << 30)
+#define S3C64XX_SPCON_DRVCON_CAM_SHIFT (30)
+#define S3C64XX_SPCON_DRVCON_CAM_2mA (0x0 << 30)
+#define S3C64XX_SPCON_DRVCON_CAM_4mA (0x1 << 30)
+#define S3C64XX_SPCON_DRVCON_CAM_7mA (0x2 << 30)
+#define S3C64XX_SPCON_DRVCON_CAM_9mA (0x3 << 30)
+
+#define S3C64XX_SPCON_DRVCON_HSSPI_MASK (0x3 << 28)
+#define S3C64XX_SPCON_DRVCON_HSSPI_SHIFT (28)
+#define S3C64XX_SPCON_DRVCON_HSSPI_2mA (0x0 << 28)
+#define S3C64XX_SPCON_DRVCON_HSSPI_4mA (0x1 << 28)
+#define S3C64XX_SPCON_DRVCON_HSSPI_7mA (0x2 << 28)
+#define S3C64XX_SPCON_DRVCON_HSSPI_9mA (0x3 << 28)
+
+#define S3C64XX_SPCON_DRVCON_HSMMC_MASK (0x3 << 26)
+#define S3C64XX_SPCON_DRVCON_HSMMC_SHIFT (26)
+#define S3C64XX_SPCON_DRVCON_HSMMC_2mA (0x0 << 26)
+#define S3C64XX_SPCON_DRVCON_HSMMC_4mA (0x1 << 26)
+#define S3C64XX_SPCON_DRVCON_HSMMC_7mA (0x2 << 26)
+#define S3C64XX_SPCON_DRVCON_HSMMC_9mA (0x3 << 26)
+
+#define S3C64XX_SPCON_DRVCON_LCD_MASK (0x3 << 24)
+#define S3C64XX_SPCON_DRVCON_LCD_SHIFT (24)
+#define S3C64XX_SPCON_DRVCON_LCD_2mA (0x0 << 24)
+#define S3C64XX_SPCON_DRVCON_LCD_4mA (0x1 << 24)
+#define S3C64XX_SPCON_DRVCON_LCD_7mA (0x2 << 24)
+#define S3C64XX_SPCON_DRVCON_LCD_9mA (0x3 << 24)
+
+#define S3C64XX_SPCON_DRVCON_MODEM_MASK (0x3 << 22)
+#define S3C64XX_SPCON_DRVCON_MODEM_SHIFT (22)
+#define S3C64XX_SPCON_DRVCON_MODEM_2mA (0x0 << 22)
+#define S3C64XX_SPCON_DRVCON_MODEM_4mA (0x1 << 22)
+#define S3C64XX_SPCON_DRVCON_MODEM_7mA (0x2 << 22)
+#define S3C64XX_SPCON_DRVCON_MODEM_9mA (0x3 << 22)
+
+#define S3C64XX_SPCON_nRSTOUT_OEN (1 << 21)
+
+#define S3C64XX_SPCON_DRVCON_SPICLK1_MASK (0x3 << 18)
+#define S3C64XX_SPCON_DRVCON_SPICLK1_SHIFT (18)
+#define S3C64XX_SPCON_DRVCON_SPICLK1_2mA (0x0 << 18)
+#define S3C64XX_SPCON_DRVCON_SPICLK1_4mA (0x1 << 18)
+#define S3C64XX_SPCON_DRVCON_SPICLK1_7mA (0x2 << 18)
+#define S3C64XX_SPCON_DRVCON_SPICLK1_9mA (0x3 << 18)
+
+#define S3C64XX_SPCON_MEM1_DQS_PUD_MASK (0x3 << 16)
+#define S3C64XX_SPCON_MEM1_DQS_PUD_SHIFT (16)
+#define S3C64XX_SPCON_MEM1_DQS_PUD_DISABLED (0x0 << 16)
+#define S3C64XX_SPCON_MEM1_DQS_PUD_DOWN (0x1 << 16)
+#define S3C64XX_SPCON_MEM1_DQS_PUD_UP (0x2 << 16)
+
+#define S3C64XX_SPCON_MEM1_D_PUD1_MASK (0x3 << 14)
+#define S3C64XX_SPCON_MEM1_D_PUD1_SHIFT (14)
+#define S3C64XX_SPCON_MEM1_D_PUD1_DISABLED (0x0 << 14)
+#define S3C64XX_SPCON_MEM1_D_PUD1_DOWN (0x1 << 14)
+#define S3C64XX_SPCON_MEM1_D_PUD1_UP (0x2 << 14)
+
+#define S3C64XX_SPCON_MEM1_D_PUD0_MASK (0x3 << 12)
+#define S3C64XX_SPCON_MEM1_D_PUD0_SHIFT (12)
+#define S3C64XX_SPCON_MEM1_D_PUD0_DISABLED (0x0 << 12)
+#define S3C64XX_SPCON_MEM1_D_PUD0_DOWN (0x1 << 12)
+#define S3C64XX_SPCON_MEM1_D_PUD0_UP (0x2 << 12)
+
+#define S3C64XX_SPCON_MEM0_D_PUD_MASK (0x3 << 8)
+#define S3C64XX_SPCON_MEM0_D_PUD_SHIFT (8)
+#define S3C64XX_SPCON_MEM0_D_PUD_DISABLED (0x0 << 8)
+#define S3C64XX_SPCON_MEM0_D_PUD_DOWN (0x1 << 8)
+#define S3C64XX_SPCON_MEM0_D_PUD_UP (0x2 << 8)
+
+#define S3C64XX_SPCON_USBH_DMPD (1 << 7)
+#define S3C64XX_SPCON_USBH_DPPD (1 << 6)
+#define S3C64XX_SPCON_USBH_PUSW2 (1 << 5)
+#define S3C64XX_SPCON_USBH_PUSW1 (1 << 4)
+#define S3C64XX_SPCON_USBH_SUSPND (1 << 3)
+
+#define S3C64XX_SPCON_LCD_SEL_MASK (0x3 << 0)
+#define S3C64XX_SPCON_LCD_SEL_SHIFT (0)
+#define S3C64XX_SPCON_LCD_SEL_HOST (0x0 << 0)
+#define S3C64XX_SPCON_LCD_SEL_RGB (0x1 << 0)
+#define S3C64XX_SPCON_LCD_SEL_606_656 (0x2 << 0)
+
+
/* External interrupt registers */
#define S3C64XX_EINT12CON S3C64XX_GPIOREG(0x200)
diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-modem.h b/arch/arm/plat-s3c64xx/include/plat/regs-modem.h
new file mode 100644
index 00000000000..49f7759dedf
--- /dev/null
+++ b/arch/arm/plat-s3c64xx/include/plat/regs-modem.h
@@ -0,0 +1,31 @@
+/* arch/arm/plat-s3c64xx/include/plat/regs-modem.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C64XX - modem block registers
+ *
+ * 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.
+*/
+
+#ifndef __PLAT_S3C64XX_REGS_MODEM_H
+#define __PLAT_S3C64XX_REGS_MODEM_H __FILE__
+
+#define S3C64XX_MODEMREG(x) (S3C64XX_VA_MODEM + (x))
+
+#define S3C64XX_MODEM_INT2AP S3C64XX_MODEMREG(0x0)
+#define S3C64XX_MODEM_INT2MODEM S3C64XX_MODEMREG(0x4)
+#define S3C64XX_MODEM_MIFCON S3C64XX_MODEMREG(0x8)
+#define S3C64XX_MODEM_MIFPCON S3C64XX_MODEMREG(0xC)
+#define S3C64XX_MODEM_INTCLR S3C64XX_MODEMREG(0x10)
+#define S3C64XX_MODEM_DMA_TXADDR S3C64XX_MODEMREG(0x14)
+#define S3C64XX_MODEM_DMA_RXADDR S3C64XX_MODEMREG(0x18)
+
+#define MIFPCON_INT2M_LEVEL (1 << 4)
+#define MIFPCON_LCD_BYPASS (1 << 3)
+
+#endif /* __PLAT_S3C64XX_REGS_MODEM_H */
diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h b/arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h
index 1b155fcb03b..270d96ac970 100644
--- a/arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h
+++ b/arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h
@@ -80,6 +80,9 @@
#define S3C64XX_STOPMEMCFG_IRDA_RETAIN (1 << 1)
#define S3C64XX_STOPMEMCFG_NFCON_RETAIN (1 << 0)
+#define S3C64XX_OSC_STABLE S3C_SYSREG(0x824)
+#define S3C64XX_PWR_STABLE S3C_SYSREG(0x828)
+
#define S3C64XX_WAKEUP_STAT S3C_SYSREG(0x908)
#define S3C64XX_WAKEUPSTAT_MMC2 (1 << 11)
diff --git a/arch/arm/plat-s3c64xx/irq-eint.c b/arch/arm/plat-s3c64xx/irq-eint.c
index 7f853473df7..f9439fa0be2 100644
--- a/arch/arm/plat-s3c64xx/irq-eint.c
+++ b/arch/arm/plat-s3c64xx/irq-eint.c
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/interrupt.h>
+#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/gpio.h>
diff --git a/arch/arm/plat-s3c64xx/irq-pm.c b/arch/arm/plat-s3c64xx/irq-pm.c
index fd705faf335..72e3b398751 100644
--- a/arch/arm/plat-s3c64xx/irq-pm.c
+++ b/arch/arm/plat-s3c64xx/irq-pm.c
@@ -5,7 +5,7 @@
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
- * S3C64XX - Interrupt handling Power Managment
+ * S3C64XX - Interrupt handling Power Management
*
* 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
@@ -30,10 +30,10 @@
#include <plat/pm.h>
/* We handled all the IRQ types in this code, to save having to make several
- * small files to handle each different type seperately. Having the EINT_GRP
+ * small files to handle each different type separately. Having the EINT_GRP
* code here shouldn't be as much bloat as the IRQ table space needed when
* they are enabled. The added benefit is we ensure that these registers are
- * in the same state as we suspsended.
+ * in the same state as we suspended.
*/
static struct sleep_save irq_save[] = {
@@ -57,6 +57,7 @@ static struct irq_grp_save {
struct irq_vic_save {
u32 int_select;
u32 int_enable;
+ u32 soft_int;
u32 protect;
u32 vect_addr[32];
u32 vect_cntl[32];
@@ -73,8 +74,12 @@ static void s3c64xx_vic_save(void __iomem *base, struct irq_vic_save *save)
save->int_select = readl(base + VIC_INT_SELECT);
save->int_enable = readl(base + VIC_INT_ENABLE);
+ save->soft_int = readl(base + VIC_INT_SOFT);
save->protect = readl(base + VIC_PROTECT);
+ S3C_PMDBG("%s: select=%08x, enable=%08x, protect=%08x\n", __func__,
+ save->int_select, save->int_enable, save->protect);
+
for (v = 0; v < ARRAY_SIZE(save->vect_addr); v++) {
save->vect_addr[v] = readl(base + VIC_VECT_ADDR0 + (v * 4));
save->vect_cntl[v] = readl(base + VIC_VECT_CNTL0 + (v * 4));
@@ -92,6 +97,13 @@ static void s3c64xx_vic_restore(void __iomem *base, struct irq_vic_save *save)
writel(save->int_enable, base + VIC_INT_ENABLE);
writel(~save->int_enable, base + VIC_INT_ENABLE_CLEAR);
+ /* and the same for the soft-int register */
+
+ writel(save->soft_int, base + VIC_INT_SOFT);
+ writel(~save->soft_int, base + VIC_INT_SOFT_CLEAR);
+
+ S3C_PMDBG("%s: vic int_enable=%08x\n", __func__, readl(base + VIC_INT_ENABLE));
+
for (v = 0; v < ARRAY_SIZE(save->vect_addr); v++) {
writel(save->vect_addr[v], base + VIC_VECT_ADDR0 + (v * 4));
writel(save->vect_cntl[v], base + VIC_VECT_CNTL0 + (v * 4));
@@ -103,7 +115,7 @@ static int s3c64xx_irq_pm_suspend(struct sys_device *dev, pm_message_t state)
struct irq_grp_save *grp = eint_grp_save;
int i;
- S3C_PMDBG("%s: suspending IRQs\n");
+ S3C_PMDBG("%s: suspending IRQs\n", __func__);
s3c64xx_vic_save(S3C_VA_VIC0, &irq_pm_vic0_save);
s3c64xx_vic_save(S3C_VA_VIC1, &irq_pm_vic1_save);
@@ -127,7 +139,7 @@ static int s3c64xx_irq_pm_resume(struct sys_device *dev)
struct irq_grp_save *grp = eint_grp_save;
int i;
- S3C_PMDBG("%s: resuming IRQs\n");
+ S3C_PMDBG("%s: resuming IRQs\n", __func__);
s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
@@ -143,6 +155,7 @@ static int s3c64xx_irq_pm_resume(struct sys_device *dev)
__raw_writel(grp->fltcon, S3C64XX_EINT12FLTCON + (i * 4));
}
+ S3C_PMDBG("%s: IRQ configuration restored\n", __func__);
return 0;
}
diff --git a/arch/arm/plat-s3c64xx/pm.c b/arch/arm/plat-s3c64xx/pm.c
index 539a93b1b88..8c28e4c93ce 100644
--- a/arch/arm/plat-s3c64xx/pm.c
+++ b/arch/arm/plat-s3c64xx/pm.c
@@ -23,7 +23,9 @@
#include <plat/regs-sys.h>
#include <plat/regs-gpio.h>
#include <plat/regs-clock.h>
+#include <plat/regs-modem.h>
#include <plat/regs-syscon-power.h>
+#include <plat/regs-gpio-memport.h>
#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
#include <plat/gpio-bank-n.h>
@@ -67,6 +69,9 @@ static struct sleep_save core_save[] = {
SAVE_ITEM(S3C_EPLL_CON1),
SAVE_ITEM(S3C_EPLL_CON0),
+ SAVE_ITEM(S3C64XX_MEM0DRVCON),
+ SAVE_ITEM(S3C64XX_MEM1DRVCON),
+
#ifndef CONFIG_CPU_FREQ
SAVE_ITEM(S3C_APLL_CON),
SAVE_ITEM(S3C_MPLL_CON),
@@ -77,12 +82,20 @@ static struct sleep_save misc_save[] = {
SAVE_ITEM(S3C64XX_AHB_CON0),
SAVE_ITEM(S3C64XX_AHB_CON1),
SAVE_ITEM(S3C64XX_AHB_CON2),
+
+ SAVE_ITEM(S3C64XX_MODEM_MIFPCON),
+ SAVE_ITEM(S3C64XX_SPCON),
+
+ SAVE_ITEM(S3C64XX_MEM0CONSTOP),
+ SAVE_ITEM(S3C64XX_MEM1CONSTOP),
+ SAVE_ITEM(S3C64XX_MEM0CONSLP0),
+ SAVE_ITEM(S3C64XX_MEM0CONSLP1),
+ SAVE_ITEM(S3C64XX_MEM1CONSLP),
};
void s3c_pm_configure_extint(void)
{
__raw_writel(s3c_irqwake_eintmask, S3C64XX_EINT_MASK);
- __raw_writel(s3c_irqwake_eintmask, S3C64XX_EINT_MASK);
}
void s3c_pm_restore_core(void)
@@ -106,6 +119,8 @@ void s3c_pm_save_core(void)
* this.
*/
+#include <plat/regs-gpio.h>
+
static void s3c64xx_cpu_suspend(void)
{
unsigned long tmp;
@@ -117,6 +132,11 @@ static void s3c64xx_cpu_suspend(void)
tmp |= S3C64XX_PWRCFG_CFG_WFI_SLEEP;
__raw_writel(tmp, S3C64XX_PWR_CFG);
+ /* clear any old wakeup */
+
+ __raw_writel(__raw_readl(S3C64XX_WAKEUP_STAT),
+ S3C64XX_WAKEUP_STAT);
+
/* set the LED state to 0110 over sleep */
s3c_pm_debug_smdkled(3 << 1, 0xf);
diff --git a/arch/arm/plat-s3c64xx/sleep.S b/arch/arm/plat-s3c64xx/sleep.S
index 8b96f2f0e06..7b55ced2f22 100644
--- a/arch/arm/plat-s3c64xx/sleep.S
+++ b/arch/arm/plat-s3c64xx/sleep.S
@@ -47,6 +47,8 @@ ENTRY(s3c_cpu_save)
mrc p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
mrc p15, 0, r8, c2, c0, 2 @ Translation Table Control
mrc p15, 0, r9, c1, c0, 0 @ Control register
+ mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register
+ mrc p15, 0, r11, c1, c0, 2 @ Co-processor access controls
stmia r0, { r4 - r13 } @ Save CP registers and SP
mov r0, #0
@@ -109,14 +111,15 @@ ENTRY(s3c_cpu_resume)
#endif
/* __v6_setup from arch/arm/mm/proc-v6.S, ensure that the caches
- * are thorougly cleaned just in case the bootloader didn't do it
+ * are thoroughly cleaned just in case the bootloader didn't do it
* for us. */
mov r0, #0
mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
mcr p15, 0, r0, c7, c15, 0 @ clean+invalidate cache
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
- mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs
+ @@mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs
+ @@mcr p15, 0, r0, c7, c7, 0 @ Invalidate I + D caches
ldr r0, s3c_sleep_save_phys
ldmia r0, { r4 - r13 }
@@ -126,6 +129,11 @@ ENTRY(s3c_cpu_resume)
mcr p15, 0, r6, c2, c0, 0 @ Translation Table BASE0
mcr p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
mcr p15, 0, r8, c2, c0, 2 @ Translation Table Control
+ mcr p15, 0, r10, c1, c0, 1 @ Auxiliary control register
+
+ mov r0, #0 @ restore copro access controls
+ mcr p15, 0, r11, c1, c0, 2 @ Co-processor access controls
+ mcr p15, 0, r0, c7, c5, 4
ldr r2, =resume_with_mmu
mcr p15, 0, r9, c1, c0, 0 /* turn mmu back on */
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index b9c9fd73d6a..38b841bcd1b 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -252,6 +252,8 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
sc->pdev = pdev;
sc->pdata = pdata;
+ platform_set_drvdata(pdev, host);
+
sc->clk_io = clk_get(dev, "hsmmc");
if (IS_ERR(sc->clk_io)) {
dev_err(dev, "failed to get io clock\n");
@@ -364,9 +366,34 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
+
+static int sdhci_s3c_suspend(struct platform_device *dev, pm_message_t pm)
+{
+ struct sdhci_host *host = platform_get_drvdata(dev);
+
+ sdhci_suspend_host(host, pm);
+ return 0;
+}
+
+static int sdhci_s3c_resume(struct platform_device *dev)
+{
+ struct sdhci_host *host = platform_get_drvdata(dev);
+
+ sdhci_resume_host(host);
+ return 0;
+}
+
+#else
+#define sdhci_s3c_suspend NULL
+#define sdhci_s3c_resume NULL
+#endif
+
static struct platform_driver sdhci_s3c_driver = {
.probe = sdhci_s3c_probe,
.remove = __devexit_p(sdhci_s3c_remove),
+ .suspend = sdhci_s3c_suspend,
+ .resume = sdhci_s3c_resume,
.driver = {
.owner = THIS_MODULE,
.name = "s3c-sdhci",
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 09ebbc69b0c..5e9c6302433 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -995,6 +995,7 @@ static int s3c_fb_resume(struct platform_device *pdev)
if (!win)
continue;
+ dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
s3c_fb_set_par(win->fbinfo);
}