diff options
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); } |