Hi Mr Kim, On Wed, Sep 7, 2011 at 11:31 AM, Kukjin Kim <kgene.kim@xxxxxxxxxxx> wrote: > Abhilash Kesavan wrote: >> >> Add suspend-to-ram support for SMDK6440/50 >> >> Signed-off-by: Abhilash Kesavan <a.kesavan@xxxxxxxxxxx> >> --- >> arch/arm/Kconfig | 2 +- >> arch/arm/mach-s5p64x0/Kconfig | 4 + >> arch/arm/mach-s5p64x0/Makefile | 1 + >> arch/arm/mach-s5p64x0/include/mach/map.h | 1 + >> arch/arm/mach-s5p64x0/include/mach/pm-core.h | 117 +++++++++++++ >> arch/arm/mach-s5p64x0/include/mach/regs-clock.h | 33 ++++ >> arch/arm/mach-s5p64x0/include/mach/regs-gpio.h | 19 ++ >> arch/arm/mach-s5p64x0/irq-eint.c | 2 + >> arch/arm/mach-s5p64x0/irq-pm.c | 92 ++++++++++ >> arch/arm/mach-s5p64x0/pm.c | 204 >> +++++++++++++++++++++++ >> 10 files changed, 474 insertions(+), 1 deletions(-) >> create mode 100644 arch/arm/mach-s5p64x0/include/mach/pm-core.h >> create mode 100644 arch/arm/mach-s5p64x0/irq-pm.c >> create mode 100644 arch/arm/mach-s5p64x0/pm.c >> >> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig >> index 2c71a8f..47aed0d 100644 >> --- a/arch/arm/Kconfig >> +++ b/arch/arm/Kconfig >> @@ -2071,7 +2071,7 @@ menu "Power management options" >> source "kernel/power/Kconfig" >> >> config ARCH_SUSPEND_POSSIBLE >> - depends on !ARCH_S5P64X0 && !ARCH_S5PC100 >> + depends on !ARCH_S5PC100 >> depends on CPU_ARM920T || CPU_ARM926T || CPU_SA1100 || \ >> CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE >> def_bool y >> diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig >> index 65c7518..d7f034a 100644 >> --- a/arch/arm/mach-s5p64x0/Kconfig >> +++ b/arch/arm/mach-s5p64x0/Kconfig >> @@ -11,6 +11,8 @@ config CPU_S5P6440 >> bool >> select S3C_PL330_DMA >> select S5P_HRT >> + select SAMSUNG_SLEEP if PM >> + select SAMSUNG_WAKEMASK if PM >> help >> Enable S5P6440 CPU support >> >> @@ -18,6 +20,8 @@ config CPU_S5P6450 >> bool >> select S3C_PL330_DMA >> select S5P_HRT >> + select SAMSUNG_SLEEP if PM >> + select SAMSUNG_WAKEMASK if PM >> help >> Enable S5P6450 CPU support >> >> diff --git a/arch/arm/mach-s5p64x0/Makefile > b/arch/arm/mach-s5p64x0/Makefile >> index 5f6afdf..acfebb7 100644 >> --- a/arch/arm/mach-s5p64x0/Makefile >> +++ b/arch/arm/mach-s5p64x0/Makefile >> @@ -16,6 +16,7 @@ obj-$(CONFIG_ARCH_S5P64X0) += cpu.o init.o >> clock.o dma.o gpiolib.o >> obj-$(CONFIG_ARCH_S5P64X0) += setup-i2c0.o irq-eint.o >> obj-$(CONFIG_CPU_S5P6440) += clock-s5p6440.o >> obj-$(CONFIG_CPU_S5P6450) += clock-s5p6450.o >> +obj-$(CONFIG_PM) += pm.o irq-pm.o >> >> # machine support >> >> diff --git a/arch/arm/mach-s5p64x0/include/mach/map.h b/arch/arm/mach- >> s5p64x0/include/mach/map.h >> index 95c9125..6138f7c 100644 >> --- a/arch/arm/mach-s5p64x0/include/mach/map.h >> +++ b/arch/arm/mach-s5p64x0/include/mach/map.h >> @@ -85,5 +85,6 @@ >> #define S5P_PA_UART5 S5P6450_PA_UART(5) >> >> #define S5P_SZ_UART SZ_256 >> +#define S3C_VA_UARTx(x) (S3C_VA_UART + ((x) * >> S3C_UART_OFFSET)) >> >> #endif /* __ASM_ARCH_MAP_H */ >> diff --git a/arch/arm/mach-s5p64x0/include/mach/pm-core.h b/arch/arm/mach- >> s5p64x0/include/mach/pm-core.h >> new file mode 100644 >> index 0000000..aee9d85 >> --- /dev/null >> +++ b/arch/arm/mach-s5p64x0/include/mach/pm-core.h >> @@ -0,0 +1,117 @@ >> +/* linux/arch/arm/mach-s5p64x0/include/mach/pm-core.h >> + * >> + * Copyright (c) 2011 Samsung Electronics Co., Ltd. >> + * http://www.samsung.com >> + * >> + * S5P64X0 - PM core support for arch/arm/plat-samsung/pm.c >> + * >> + * Based on PM core support for S3C64XX by Ben Dooks >> + * >> + * 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. >> + */ >> + >> +#include <mach/regs-gpio.h> >> + >> +static inline void s3c_pm_debug_init_uart(void) >> +{ >> + u32 tmp = __raw_readl(S5P64X0_CLK_GATE_PCLK); >> + >> + /* >> + * As a note, since the S5P64X0 UARTs generally have multiple >> + * 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. >> + */ >> + tmp |= S5P64X0_CLKCON_PCLK_UART0; >> + tmp |= S5P64X0_CLKCON_PCLK_UART1; >> + tmp |= S5P64X0_CLKCON_PCLK_UART2; >> + tmp |= S5P64X0_CLKCON_PCLK_UART3; >> + >> + __raw_writel(tmp, S5P64X0_CLK_GATE_PCLK); >> + udelay(10); >> +} >> + >> +static inline void s3c_pm_arch_prepare_irqs(void) >> +{ >> + /* VIC should have already been taken care of */ >> + >> + /* clear any pending EINT0 interrupts */ >> + __raw_writel(__raw_readl(S5P64X0_EINT0PEND), S5P64X0_EINT0PEND); >> +} >> + >> +static inline void s3c_pm_arch_stop_clocks(void) { } >> +static inline void s3c_pm_arch_show_resume_irqs(void) { } >> + >> +/* >> + * make these defines, we currently do not have any need to change >> + * the IRQ wake controls depending on the CPU we are running on >> + */ >> +#define s3c_irqwake_eintallow ((1 << 16) - 1) >> +#define s3c_irqwake_intallow (~0) >> + >> +static inline void s3c_pm_arch_update_uart(void __iomem *regs, >> + struct pm_uart_save *save) >> +{ >> + u32 ucon = __raw_readl(regs + S3C2410_UCON); >> + u32 ucon_clk = ucon & S3C6400_UCON_CLKMASK; >> + u32 save_clk = save->ucon & S3C6400_UCON_CLKMASK; >> + u32 new_ucon; >> + u32 delta; >> + >> + /* >> + * S5P64X0 UART blocks only support level interrupts, so ensure that >> + * when we restore unused UART blocks we force the level interrupt >> + * settings. >> + */ >> + save->ucon |= S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL; >> + >> + /* >> + * We have a constraint on changing the clock type of the UART >> + * between UCLKx and PCLK, so ensure that when we restore UCON >> + * that the CLK field is correctly modified if the bootloader >> + * has changed anything. >> + */ >> + if (ucon_clk != save_clk) { >> + new_ucon = save->ucon; >> + 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 a 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; >> + } >> +} >> + >> +static inline void s3c_pm_restored_gpios(void) >> +{ >> + /* ensure sleep mode has been cleared from the system */ >> + __raw_writel(0, S5P64X0_SLPEN); >> +} >> + >> +static inline void s3c_pm_saved_gpios(void) >> +{ >> + /* >> + * turn on the sleep mode and keep it there, as it seems that during >> + * suspend the xCON registers get re-set and thus you can end up > with >> + * problems between going to sleep and resuming. >> + */ >> + __raw_writel(S5P64X0_SLPEN_USE_xSLP, S5P64X0_SLPEN); >> +} >> diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-clock.h > b/arch/arm/mach- >> s5p64x0/include/mach/regs-clock.h >> index a133f22..75f66a9 100644 >> --- a/arch/arm/mach-s5p64x0/include/mach/regs-clock.h >> +++ b/arch/arm/mach-s5p64x0/include/mach/regs-clock.h >> @@ -41,17 +41,50 @@ >> #define S5P6450_DPLL_CON S5P_CLKREG(0x50) >> #define S5P6450_DPLL_CON_K S5P_CLKREG(0x54) >> >> +#define S5P64X0_AHB_CON0 S5P_CLKREG(0x100) >> #define S5P64X0_CLK_SRC1 S5P_CLKREG(0x10C) >> >> #define S5P64X0_SYS_ID S5P_CLKREG(0x118) >> #define S5P64X0_SYS_OTHERS S5P_CLKREG(0x11C) >> >> #define S5P64X0_PWR_CFG S5P_CLKREG(0x804) >> +#define S5P64X0_EINT_WAKEUP_MASK S5P_CLKREG(0x808) >> +#define S5P64X0_SLEEP_CFG S5P_CLKREG(0x818) >> +#define S5P64X0_PWR_STABLE S5P_CLKREG(0x828) >> + >> #define S5P64X0_OTHERS S5P_CLKREG(0x900) >> +#define S5P64X0_WAKEUP_STAT S5P_CLKREG(0x908) >> + >> +#define S5P64X0_INFORM0 S5P_CLKREG(0xA00) >> >> #define S5P64X0_CLKDIV0_HCLK_SHIFT (8) >> #define S5P64X0_CLKDIV0_HCLK_MASK (0xF << >> S5P64X0_CLKDIV0_HCLK_SHIFT) >> >> +/* HCLK GATE Registers */ >> +#define S5P64X0_CLKCON_HCLK1_FIMGVG (1<<2) > > Should be added blank around "<<" like (1 << 2). > And if possible, the name should be same with datasheet like > ...CLK_GATE_HCLK1_FIMGVG. > > Please don't make new name. OK..will change > >> +#define S5P64X0_CLKCON_SCLK1_FIMGVG (1<<2) > > Same as above. OK..will change > ...CLK_GATE_SCLK1_FIMGVG > >> + >> +/* PCLK GATE Registers */ >> +#define S5P64X0_CLKCON_PCLK_UART3 (1<<4) >> +#define S5P64X0_CLKCON_PCLK_UART2 (1<<3) >> +#define S5P64X0_CLKCON_PCLK_UART1 (1<<2) >> +#define S5P64X0_CLKCON_PCLK_UART0 (1<<1) > > Same as above. OK..will change > >> + >> +#define S5P64X0_PWRCFG_MMC1_DISABLE (1 << 15) >> +#define S5P64X0_PWRCFG_MMC0_DISABLE (1 << 14) >> +#define S5P64X0_PWRCFG_RTC_TICK_DISABLE (1 << 11) >> +#define S5P64X0_PWRCFG_RTC_ALRM_DISABLE (1 << 10) >> +#define S5P64X0_PWRCFG_CFG_WFI_MASK (3 << 5) >> +#define S5P64X0_PWRCFG_CFG_WFI_SLEEP (3 << 5) >> + >> +#define S5P64X0_SLEEP_CFG_OSC_EN (1 << 0) >> + >> +#define S5P64X0_PWR_STABLE_CNT_VAL_4 (4 << 0) > > Same...please use same name with datasheet. would you like it to be PWR_STABLE_PWR_CNT_VAL_4 ? > >> + >> +#define S5P6450_OTHERS_DISABLE_INT (1 << 31) >> +#define S5P64X0_OTHERS_RET_UART (1 << 26) >> +#define S5P64X0_OTHERS_RET_MMC1 (1 << 25) >> +#define S5P64X0_OTHERS_RET_MMC0 (1 << 24) >> #define S5P64X0_OTHERS_USB_SIG_MASK (1 << 16) >> >> /* Compatibility defines */ >> diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h > b/arch/arm/mach- >> s5p64x0/include/mach/regs-gpio.h >> index 6ce2547..27a2230 100644 >> --- a/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h >> +++ b/arch/arm/mach-s5p64x0/include/mach/regs-gpio.h >> @@ -34,14 +34,33 @@ >> #define S5P6450_GPQ_BASE (S5P_VA_GPIO + 0x0180) >> #define S5P6450_GPS_BASE (S5P_VA_GPIO + 0x0300) >> >> +#define S5P64X0_SPCON0 (S5P_VA_GPIO + 0x1A0) >> +#define S5P64X0_SPCON1 (S5P_VA_GPIO + 0x2B0) >> + >> +#define S5P64X0_MEM0CONSLP0 (S5P_VA_GPIO + 0x1C0) >> +#define S5P64X0_MEM0CONSLP1 (S5P_VA_GPIO + 0x1C4) >> +#define S5P64X0_MEM0DRVCON (S5P_VA_GPIO + 0x1D0) >> +#define S5P64X0_MEM1DRVCON (S5P_VA_GPIO + 0x1D4) >> + >> +#define S5P64X0_EINT12CON (S5P_VA_GPIO + 0x200) >> +#define S5P64X0_EINT12FLTCON (S5P_VA_GPIO + 0x220) >> +#define S5P64X0_EINT12MASK (S5P_VA_GPIO + 0x240) >> + >> /* External interrupt control registers for group0 */ >> >> #define EINT0CON0_OFFSET (0x900) >> +#define EINT0FLTCON0_OFFSET (0x910) >> +#define EINT0FLTCON1_OFFSET (0x914) >> #define EINT0MASK_OFFSET (0x920) >> #define EINT0PEND_OFFSET (0x924) >> >> #define S5P64X0_EINT0CON0 (S5P_VA_GPIO + >> EINT0CON0_OFFSET) >> +#define S5P64X0_EINT0FLTCON0 (S5P_VA_GPIO + >> EINT0FLTCON0_OFFSET) >> +#define S5P64X0_EINT0FLTCON1 (S5P_VA_GPIO + >> EINT0FLTCON1_OFFSET) >> #define S5P64X0_EINT0MASK (S5P_VA_GPIO + >> EINT0MASK_OFFSET) >> #define S5P64X0_EINT0PEND (S5P_VA_GPIO + >> EINT0PEND_OFFSET) >> >> +#define S5P64X0_SLPEN (S5P_VA_GPIO + 0x930) >> +#define S5P64X0_SLPEN_USE_xSLP (1 << 0) >> + >> #endif /* __ASM_ARCH_REGS_GPIO_H */ >> diff --git a/arch/arm/mach-s5p64x0/irq-eint.c > b/arch/arm/mach-s5p64x0/irq-eint.c >> index fe7380f..3b94c6c 100644 >> --- a/arch/arm/mach-s5p64x0/irq-eint.c >> +++ b/arch/arm/mach-s5p64x0/irq-eint.c >> @@ -19,6 +19,7 @@ >> >> #include <plat/regs-irqtype.h> >> #include <plat/gpio-cfg.h> >> +#include <plat/pm.h> >> >> #include <mach/regs-gpio.h> >> #include <mach/regs-clock.h> >> @@ -133,6 +134,7 @@ static int s5p64x0_alloc_gc(void) >> ct->chip.irq_mask = irq_gc_mask_set_bit; >> ct->chip.irq_unmask = irq_gc_mask_clr_bit; >> ct->chip.irq_set_type = s5p64x0_irq_eint_set_type; >> + ct->chip.irq_set_wake = s3c_irqext_wake; >> ct->regs.ack = EINT0PEND_OFFSET; >> ct->regs.mask = EINT0MASK_OFFSET; >> irq_setup_generic_chip(gc, IRQ_MSK(16), IRQ_GC_INIT_MASK_CACHE, >> diff --git a/arch/arm/mach-s5p64x0/irq-pm.c > b/arch/arm/mach-s5p64x0/irq-pm.c >> new file mode 100644 >> index 0000000..3e6f245 >> --- /dev/null >> +++ b/arch/arm/mach-s5p64x0/irq-pm.c >> @@ -0,0 +1,92 @@ >> +/* linux/arch/arm/mach-s5p64x0/irq-pm.c >> + * >> + * Copyright (c) 2011 Samsung Electronics Co., Ltd. >> + * http://www.samsung.com >> + * >> + * S5P64X0 - Interrupt handling Power Management >> + * >> + * Based on arch/arm/mach-s3c64xx/irq-pm.c by Ben Dooks >> + * >> + * 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. >> + */ >> + >> +#include <linux/syscore_ops.h> >> +#include <linux/serial_core.h> >> +#include <linux/io.h> >> + >> +#include <plat/regs-serial.h> >> +#include <plat/pm.h> >> + >> +#include <mach/regs-gpio.h> >> + >> +static struct sleep_save irq_save[] = { >> + SAVE_ITEM(S5P64X0_EINT0CON0), >> + SAVE_ITEM(S5P64X0_EINT0FLTCON0), >> + SAVE_ITEM(S5P64X0_EINT0FLTCON1), >> + SAVE_ITEM(S5P64X0_EINT0MASK), >> +}; >> + >> +static struct irq_grp_save { >> + u32 con; >> + u32 fltcon; >> + u32 mask; >> +} eint_grp_save[4]; >> + >> +static u32 irq_uart_mask[CONFIG_SERIAL_SAMSUNG_UARTS]; >> + >> +static int s5p64x0_irq_pm_suspend(void) >> +{ >> + struct irq_grp_save *grp = eint_grp_save; >> + int i; >> + >> + S3C_PMDBG("%s: suspending IRQs\n", __func__); >> + >> + s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save)); >> + >> + for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++) >> + irq_uart_mask[i] = __raw_readl(S3C_VA_UARTx(i) + >> S3C64XX_UINTM); >> + >> + for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) { >> + grp->con = __raw_readl(S5P64X0_EINT12CON + (i * 4)); >> + grp->mask = __raw_readl(S5P64X0_EINT12MASK + (i * 4)); >> + grp->fltcon = __raw_readl(S5P64X0_EINT12FLTCON + (i * 4)); >> + } >> + >> + return 0; >> +} >> + >> +static void s5p64x0_irq_pm_resume(void) >> +{ >> + struct irq_grp_save *grp = eint_grp_save; >> + int i; >> + >> + S3C_PMDBG("%s: resuming IRQs\n", __func__); >> + >> + s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save)); >> + >> + for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++) >> + __raw_writel(irq_uart_mask[i], S3C_VA_UARTx(i) + >> S3C64XX_UINTM); >> + >> + for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) { >> + __raw_writel(grp->con, S5P64X0_EINT12CON + (i * 4)); >> + __raw_writel(grp->mask, S5P64X0_EINT12MASK + (i * 4)); >> + __raw_writel(grp->fltcon, S5P64X0_EINT12FLTCON + (i * 4)); >> + } >> + >> + S3C_PMDBG("%s: IRQ configuration restored\n", __func__); >> +} >> + >> +static struct syscore_ops s5p64x0_irq_syscore_ops = { >> + .suspend = s5p64x0_irq_pm_suspend, >> + .resume = s5p64x0_irq_pm_resume, >> +}; >> + >> +static int __init s5p64x0_syscore_init(void) >> +{ >> + register_syscore_ops(&s5p64x0_irq_syscore_ops); >> + >> + return 0; >> +} >> +core_initcall(s5p64x0_syscore_init); >> diff --git a/arch/arm/mach-s5p64x0/pm.c b/arch/arm/mach-s5p64x0/pm.c >> new file mode 100644 >> index 0000000..cced4fb >> --- /dev/null >> +++ b/arch/arm/mach-s5p64x0/pm.c >> @@ -0,0 +1,204 @@ >> +/* linux/arch/arm/mach-s5p64x0/pm.c >> + * >> + * Copyright (c) 2011 Samsung Electronics Co., Ltd. >> + * http://www.samsung.com >> + * >> + * S5P64X0 Power Management Support >> + * >> + * Based on arch/arm/mach-s3c64xx/pm.c by Ben Dooks >> + * >> + * 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. >> +*/ >> + >> +#include <linux/suspend.h> >> +#include <linux/syscore_ops.h> >> +#include <linux/io.h> >> + >> +#include <plat/cpu.h> >> +#include <plat/pm.h> >> +#include <plat/regs-timer.h> >> +#include <plat/wakeup-mask.h> >> + >> +#include <mach/regs-clock.h> >> +#include <mach/regs-gpio.h> >> + >> +static struct sleep_save s5p64x0_core_save[] = { >> + SAVE_ITEM(S5P64X0_APLL_CON), >> + SAVE_ITEM(S5P64X0_MPLL_CON), >> + SAVE_ITEM(S5P64X0_EPLL_CON), >> + SAVE_ITEM(S5P64X0_EPLL_CON_K), >> + SAVE_ITEM(S5P64X0_CLK_SRC0), >> + SAVE_ITEM(S5P64X0_CLK_SRC1), >> + SAVE_ITEM(S5P64X0_CLK_DIV0), >> + SAVE_ITEM(S5P64X0_CLK_DIV1), >> + SAVE_ITEM(S5P64X0_CLK_DIV2), >> + SAVE_ITEM(S5P64X0_CLK_DIV3), >> + SAVE_ITEM(S5P64X0_CLK_GATE_MEM0), >> + SAVE_ITEM(S5P64X0_CLK_GATE_HCLK1), >> + SAVE_ITEM(S5P64X0_CLK_GATE_SCLK1), >> +}; >> + >> +static struct sleep_save s5p64x0_misc_save[] = { >> + SAVE_ITEM(S5P64X0_AHB_CON0), >> + SAVE_ITEM(S5P64X0_SPCON0), >> + SAVE_ITEM(S5P64X0_SPCON1), >> + SAVE_ITEM(S5P64X0_MEM0CONSLP0), >> + SAVE_ITEM(S5P64X0_MEM0CONSLP1), >> + SAVE_ITEM(S5P64X0_MEM0DRVCON), >> + SAVE_ITEM(S5P64X0_MEM1DRVCON), >> + >> + SAVE_ITEM(S3C64XX_TINT_CSTAT), >> +}; >> + >> +/* DPLL is present only in S5P6450 */ >> +static struct sleep_save s5p6450_core_save[] = { >> + SAVE_ITEM(S5P6450_DPLL_CON), >> + SAVE_ITEM(S5P6450_DPLL_CON_K), >> +}; >> + >> +void s3c_pm_configure_extint(void) >> +{ >> + __raw_writel(s3c_irqwake_eintmask, S5P64X0_EINT_WAKEUP_MASK); >> +} >> + >> +void s3c_pm_restore_core(void) >> +{ >> + __raw_writel(0, S5P64X0_EINT_WAKEUP_MASK); >> + >> + s3c_pm_do_restore_core(s5p64x0_core_save, >> + ARRAY_SIZE(s5p64x0_core_save)); >> + >> + if ((__raw_readl(S5P64X0_SYS_ID) & 0xFF000) == 0x50000) >> + s3c_pm_do_restore_core(s5p6450_core_save, >> + ARRAY_SIZE(s5p6450_core_save)); > > You can use soc_is_xxx() here. Yep, wasn't there when I posted the series. Will change. > >> + >> + s3c_pm_do_restore(s5p64x0_misc_save, >> ARRAY_SIZE(s5p64x0_misc_save)); >> +} >> + >> +void s3c_pm_save_core(void) >> +{ >> + s3c_pm_do_save(s5p64x0_misc_save, >> ARRAY_SIZE(s5p64x0_misc_save)); >> + >> + if ((__raw_readl(S5P64X0_SYS_ID) & 0xFF000) == 0x50000) >> + s3c_pm_do_save(s5p6450_core_save, >> + ARRAY_SIZE(s5p6450_core_save)); > > Same. > >> + >> + s3c_pm_do_save(s5p64x0_core_save, >> ARRAY_SIZE(s5p64x0_core_save)); >> +} >> + >> +static int s5p64x0_cpu_suspend(unsigned long arg) >> +{ >> + unsigned long tmp = 0; >> + >> + /* >> + * Issue the standby signal into the pm unit. Note, we >> + * issue a write-buffer drain just in case. >> + */ >> + asm("b 1f\n\t" >> + ".align 5\n\t" >> + "1:\n\t" >> + "mcr p15, 0, %0, c7, c10, 5\n\t" >> + "mcr p15, 0, %0, c7, c10, 4\n\t" >> + "mcr p15, 0, %0, c7, c0, 4" : : "r" (tmp)); >> + >> + /* we should never get past here */ >> + panic("sleep resumed to originator?"); >> +} >> + >> +/* mapping of interrupts to parts of the wakeup mask */ >> +static struct samsung_wakeup_mask s5p64x0_wake_irqs[] = { >> + { .irq = IRQ_RTC_ALARM, .bit = >> S5P64X0_PWRCFG_RTC_ALRM_DISABLE, }, >> + { .irq = IRQ_RTC_TIC, .bit = >> S5P64X0_PWRCFG_RTC_TICK_DISABLE, }, >> + { .irq = IRQ_HSMMC0, .bit = S5P64X0_PWRCFG_MMC0_DISABLE, }, >> + { .irq = IRQ_HSMMC1, .bit = S5P64X0_PWRCFG_MMC1_DISABLE, }, >> +}; >> + >> +static void s5p64x0_pm_prepare(void) >> +{ >> + u32 tmp; >> + >> + samsung_sync_wakemask(S5P64X0_PWR_CFG, >> + s5p64x0_wake_irqs, ARRAY_SIZE(s5p64x0_wake_irqs)); >> + >> + /* store the resume address in INFORM0 register */ >> + __raw_writel(virt_to_phys(s3c_cpu_resume), S5P64X0_INFORM0); >> + >> + /* setup clock gating for FIMGVG block */ >> + __raw_writel((__raw_readl(S5P64X0_CLK_GATE_HCLK1) | \ >> + (S5P64X0_CLKCON_HCLK1_FIMGVG)), >> S5P64X0_CLK_GATE_HCLK1); >> + __raw_writel((__raw_readl(S5P64X0_CLK_GATE_SCLK1) | \ >> + (S5P64X0_CLKCON_SCLK1_FIMGVG)), >> S5P64X0_CLK_GATE_SCLK1); >> + >> + /* Configure the stabilization counter with wait time required */ >> + __raw_writel(S5P64X0_PWR_STABLE_CNT_VAL_4, >> S5P64X0_PWR_STABLE); >> + >> + /* set WFI to SLEEP mode configuration */ >> + tmp = __raw_readl(S5P64X0_SLEEP_CFG); >> + tmp &= ~(S5P64X0_SLEEP_CFG_OSC_EN); >> + __raw_writel(tmp, S5P64X0_SLEEP_CFG); >> + >> + tmp = __raw_readl(S5P64X0_PWR_CFG); >> + tmp &= ~(S5P64X0_PWRCFG_CFG_WFI_MASK); >> + tmp |= S5P64X0_PWRCFG_CFG_WFI_SLEEP; >> + __raw_writel(tmp, S5P64X0_PWR_CFG); >> + >> + /* >> + * set OTHERS register to disable interrupt before going to >> + * sleep. This bit is present only in S5P6450, it is reserved >> + * in S5P6440. >> + */ >> + if ((__raw_readl(S5P64X0_SYS_ID) & 0xFF000) == 0x50000) { >> + tmp = __raw_readl(S5P64X0_OTHERS); >> + tmp |= S5P6450_OTHERS_DISABLE_INT; >> + __raw_writel(tmp, S5P64X0_OTHERS); >> + } >> + >> + /* ensure previous wakeup state is cleared before sleeping */ >> + __raw_writel(__raw_readl(S5P64X0_WAKEUP_STAT), >> S5P64X0_WAKEUP_STAT); >> + >> +} >> + >> +static int s5p64x0_pm_add(struct sys_device *sysdev) >> +{ >> + pm_cpu_prep = s5p64x0_pm_prepare; >> + pm_cpu_sleep = s5p64x0_cpu_suspend; >> + pm_uart_udivslot = 1; > > If pm_uart_udivslot has value, the UDIVSLOT3 is used...is this right on > S5P64X0? UDIVSLOT at an offset of 2C seems fine for 64X0. > >> + >> + return 0; >> +} >> + >> +static struct sysdev_driver s5p64x0_pm_driver = { >> + .add = s5p64x0_pm_add, >> +}; >> + >> +static __init int s5p64x0_pm_drvinit(void) >> +{ >> + s3c_pm_init(); >> + >> + return sysdev_driver_register(&s5p64x0_sysclass, > &s5p64x0_pm_driver); >> +} >> +arch_initcall(s5p64x0_pm_drvinit); >> + >> +static void s5p64x0_pm_resume(void) >> +{ >> + u32 tmp; >> + >> + tmp = __raw_readl(S5P64X0_OTHERS); >> + tmp |= (S5P64X0_OTHERS_RET_MMC0 | >> S5P64X0_OTHERS_RET_MMC1 | \ >> + S5P64X0_OTHERS_RET_UART); >> + __raw_writel(tmp , S5P64X0_OTHERS); >> +} >> + >> +static struct syscore_ops s5p64x0_pm_syscore_ops = { >> + .resume = s5p64x0_pm_resume, >> +}; >> + >> +static __init int s5p64x0_pm_syscore_init(void) >> +{ >> + register_syscore_ops(&s5p64x0_pm_syscore_ops); >> + >> + return 0; >> +} >> +arch_initcall(s5p64x0_pm_syscore_init); >> -- >> 1.7.4.1 > > Basically, this codes need small fixing. I mean if this codes have been > tested on board and it works fine, it's ok to me. > > But as you said, s5p64x0 pm is almost same with s3c64xx, so we need to clean > them up next time :) Has been tested for 6440 and 6450. Thanks for the review. > > Thanks. > > Best regards, > Kgene. Abhilash > -- > Kukjin Kim <kgene.kim@xxxxxxxxxxx>, Senior Engineer, > SW Solution Development Team, Samsung Electronics Co., Ltd. > > > _______________________________________________ > linux-arm-kernel mailing list > linux-arm-kernel@xxxxxxxxxxxxxxxxxxx > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel > -- To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html