Hi Abhilash, Please see my comments inline. On Monday 16 of December 2013 17:31:10 Abhilash Kesavan wrote: > Add PMU configuration table for various low power modes - AFTR/LPA/SLEEP. > Also, add core s2r support for Exynos5420. > > Signed-off-by: Abhilash Kesavan <a.kesavan@xxxxxxxxxxx> > --- > This patch depends on "ARM: EXYNOS5: Add PMU settings for exynos5420" > http://www.spinics.net/lists/linux-samsung-soc/msg24902.html > > arch/arm/mach-exynos/include/mach/regs-clock.h | 15 +++ > arch/arm/mach-exynos/include/mach/regs-pmu.h | 84 ++++++++++++ > arch/arm/mach-exynos/pm.c | 151 +++++++++++++++++++--- > arch/arm/mach-exynos/pmu.c | 165 ++++++++++++++++++++++++ > 4 files changed, 396 insertions(+), 19 deletions(-) > > diff --git a/arch/arm/mach-exynos/include/mach/regs-clock.h b/arch/arm/mach-exynos/include/mach/regs-clock.h > index d36ad76..20008f6 100644 > --- a/arch/arm/mach-exynos/include/mach/regs-clock.h > +++ b/arch/arm/mach-exynos/include/mach/regs-clock.h > @@ -363,6 +363,21 @@ > #define PWR_CTRL2_CORE2_UP_RATIO (1 << 4) > #define PWR_CTRL2_CORE1_UP_RATIO (1 << 0) > > +/* For EXYNOS5420 */ > +#define EXYNOS5420_CLKSRC_MASK_CPERI EXYNOS_CLKREG(0x04300) > +#define EXYNOS5420_CLKSRC_MASK_TOP0 EXYNOS_CLKREG(0x10300) > +#define EXYNOS5420_CLKSRC_MASK_TOP1 EXYNOS_CLKREG(0x10304) > +#define EXYNOS5420_CLKSRC_MASK_TOP2 EXYNOS_CLKREG(0x10308) > +#define EXYNOS5420_CLKSRC_MASK_TOP7 EXYNOS_CLKREG(0x1031C) > +#define EXYNOS5420_CLKSRC_MASK_DISP10 EXYNOS_CLKREG(0x1032C) > +#define EXYNOS5420_CLKSRC_MASK_MAU EXYNOS_CLKREG(0x10334) > +#define EXYNOS5420_CLKSRC_MASK_FSYS EXYNOS_CLKREG(0x10340) > +#define EXYNOS5420_CLKSRC_MASK_PERIC0 EXYNOS_CLKREG(0x10350) > +#define EXYNOS5420_CLKSRC_MASK_PERIC1 EXYNOS_CLKREG(0x10354) > +#define EXYNOS5420_CLKSRC_MASK_ISP EXYNOS_CLKREG(0x10370) > +#define EXYNOS5420_CLKGATE_BUS_DISP1 EXYNOS_CLKREG(0x10728) > +#define EXYNOS5420_CLKGATE_IP_PERIC EXYNOS_CLKREG(0x10950) This looks suspicious. Let me see below if this is really needed for what I think it is. > + > /* Compatibility defines and inclusion */ > > #include <mach/regs-pmu.h> > diff --git a/arch/arm/mach-exynos/include/mach/regs-pmu.h b/arch/arm/mach-exynos/include/mach/regs-pmu.h > index d5d5386..ad316f3 100644 > --- a/arch/arm/mach-exynos/include/mach/regs-pmu.h > +++ b/arch/arm/mach-exynos/include/mach/regs-pmu.h > @@ -229,6 +229,7 @@ > > /* For EXYNOS5 */ > > +#define EXYNOS5_SYS_DISP1_BLK_CFG S5P_SYSREG(0x0214) Is it really a definition common for all Exynos5 SoCs? > #define EXYNOS5_SYS_I2C_CFG S5P_SYSREG(0x0234) > > #define EXYNOS5_AUTO_WDTRESET_DISABLE S5P_PMUREG(0x0408) > @@ -360,6 +361,7 @@ > #define EXYNOS5_USE_SC_COUNTER (1 << 0) > > #define EXYNOS5_MANUAL_L2RSTDISABLE_CONTROL (1 << 2) > +#define EXYNOS5_L2RSTDISABLE_VALUE (1 << 3) Ditto. > #define EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN (1 << 7) > > #define EXYNOS5_OPTION_USE_STANDBYWFE (1 << 24) [snip] > diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c > index 7fb0f13..3ad103f 100644 > --- a/arch/arm/mach-exynos/pm.c > +++ b/arch/arm/mach-exynos/pm.c > @@ -52,6 +52,22 @@ static const struct sleep_save exynos4210_set_clksrc[] = { > { .reg = EXYNOS4210_CLKSRC_MASK_LCD1 , .val = 0x00001111, }, > }; > > +static struct sleep_save exynos5420_set_clksrc[] = { > + { .reg = EXYNOS5420_CLKSRC_MASK_CPERI, .val = 0xffffffff, }, > + { .reg = EXYNOS5420_CLKSRC_MASK_TOP0, .val = 0x11111111, }, > + { .reg = EXYNOS5420_CLKSRC_MASK_TOP1, .val = 0x11101111, }, > + { .reg = EXYNOS5420_CLKSRC_MASK_TOP2, .val = 0x11111110, }, > + { .reg = EXYNOS5420_CLKSRC_MASK_TOP7, .val = 0x00111100, }, > + { .reg = EXYNOS5420_CLKSRC_MASK_DISP10, .val = 0x11111110, }, > + { .reg = EXYNOS5420_CLKSRC_MASK_MAU, .val = 0x10000000, }, > + { .reg = EXYNOS5420_CLKSRC_MASK_FSYS, .val = 0x11111110, }, > + { .reg = EXYNOS5420_CLKSRC_MASK_PERIC0, .val = 0x11111110, }, > + { .reg = EXYNOS5420_CLKSRC_MASK_PERIC1, .val = 0x11111100, }, > + { .reg = EXYNOS5420_CLKSRC_MASK_ISP, .val = 0x11111000, }, > + { .reg = EXYNOS5420_CLKGATE_BUS_DISP1, .val = 0xffffffff, }, > + { .reg = EXYNOS5420_CLKGATE_IP_PERIC, .val = 0xffffffff, }, > +}; > + OK, just as I thought... NAK. Clock registers should be accessed only inside clock driver. Please see my patch implementing similar thing for Exynos 4: http://thread.gmane.org/gmane.linux.kernel.samsung-soc/24078/focus=24087 > static struct sleep_save exynos4_epll_save[] = { > SAVE_ITEM(EXYNOS4_EPLL_CON0), > SAVE_ITEM(EXYNOS4_EPLL_CON1), > @@ -66,6 +82,14 @@ static struct sleep_save exynos5_sys_save[] = { > SAVE_ITEM(EXYNOS5_SYS_I2C_CFG), > }; > > +static struct sleep_save exynos5420_sys_save[] = { > + SAVE_ITEM(EXYNOS5_SYS_DISP1_BLK_CFG), > +}; > + > +static struct sleep_save exynos5420_cpustate_save[] = { > + SAVE_ITEM(S5P_VA_SYSRAM + 0x28), > +}; > + > static struct sleep_save exynos_core_save[] = { > /* SROM side */ > SAVE_ITEM(S5P_SROM_BW), > @@ -84,8 +108,15 @@ static int exynos_cpu_suspend(unsigned long arg) > #ifdef CONFIG_CACHE_L2X0 > outer_flush_all(); > #endif > + /* > + * Clear the IRAM register that holds a low power flag. The presence > + * of this flag decides if the primary cpu starts executing the low > + * power function at wake-up or not. > + */ > + if (soc_is_exynos5420()) > + __raw_writel(0x0, S5P_VA_SYSRAM + 0x28); > > - if (soc_is_exynos5250()) > + if (soc_is_exynos5250() || soc_is_exynos5420()) > flush_cache_all(); > > /* issue the standby signal into the pm unit. */ > @@ -101,9 +132,14 @@ static void exynos_pm_prepare(void) > > s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save)); > > - if (!soc_is_exynos5250()) { > + if (!(soc_is_exynos5250() || soc_is_exynos5420())) { > s3c_pm_do_save(exynos4_epll_save, ARRAY_SIZE(exynos4_epll_save)); > s3c_pm_do_save(exynos4_vpll_save, ARRAY_SIZE(exynos4_vpll_save)); > + } else if (soc_is_exynos5420()) { > + s3c_pm_do_save(exynos5420_sys_save, > + ARRAY_SIZE(exynos5420_sys_save)); > + s3c_pm_do_save(exynos5420_cpustate_save, > + ARRAY_SIZE(exynos5420_cpustate_save)); > } else { > s3c_pm_do_save(exynos5_sys_save, ARRAY_SIZE(exynos5_sys_save)); > /* Disable USE_RETENTION of JPEG_MEM_OPTION */ What about rewriting this code as follows: if (soc_is_exynos5420()) { // exynos5420 specific code } else if (soc_is_exynos5250()) { // exynos5250 specific code } else { // exynos4 specific code } Still, I'd prefer this to be based on top of my series I mentioned above which removes any clock handling from this file and so makes the exynos4 branch above disappear. > @@ -123,12 +159,32 @@ static void exynos_pm_prepare(void) > > /* Before enter central sequence mode, clock src register have to set */ > > - if (!soc_is_exynos5250()) > + if (!(soc_is_exynos5250() || soc_is_exynos5420())) > s3c_pm_do_restore_core(exynos4_set_clksrc, ARRAY_SIZE(exynos4_set_clksrc)); > > if (soc_is_exynos4210()) > s3c_pm_do_restore_core(exynos4210_set_clksrc, ARRAY_SIZE(exynos4210_set_clksrc)); > > + if (soc_is_exynos5420()) { > + s3c_pm_do_restore_core(exynos5420_set_clksrc, > + ARRAY_SIZE(exynos5420_set_clksrc)); > + > + tmp = __raw_readl(EXYNOS5420_SFR_AXI_CGDIS1); > + tmp |= EXYNOS5420_UFS; > + __raw_writel(tmp, EXYNOS5420_SFR_AXI_CGDIS1); > + > + tmp = __raw_readl(EXYNOS5420_ARM_COMMON_OPTION); > + tmp &= ~EXYNOS5_L2RSTDISABLE_VALUE; > + __raw_writel(tmp, EXYNOS5420_ARM_COMMON_OPTION); > + > + tmp = __raw_readl(EXYNOS5420_FSYS2_OPTION); > + tmp |= EXYNOS5420_EMULATION; > + __raw_writel(tmp, EXYNOS5420_FSYS2_OPTION); > + > + tmp = __raw_readl(EXYNOS5420_PSGEN_OPTION); > + tmp |= EXYNOS5420_EMULATION; > + __raw_writel(tmp, EXYNOS5420_PSGEN_OPTION); > + } > } > > static int exynos_pm_add(struct device *dev, struct subsys_interface *sif) > @@ -224,11 +280,17 @@ static __init int exynos_pm_drvinit(void) > > /* All wakeup disable */ > > - tmp = __raw_readl(S5P_WAKEUP_MASK); > - tmp |= ((0xFF << 8) | (0x1F << 1)); > - __raw_writel(tmp, S5P_WAKEUP_MASK); > + if (soc_is_exynos5420()) { > + tmp = __raw_readl(S5P_WAKEUP_MASK); > + tmp |= ((0x7F << 7) | (0x1F << 1)); > + __raw_writel(tmp, S5P_WAKEUP_MASK); > + } else { > + tmp = __raw_readl(S5P_WAKEUP_MASK); > + tmp |= ((0xFF << 8) | (0x1F << 1)); > + __raw_writel(tmp, S5P_WAKEUP_MASK); > + } > > - if (!soc_is_exynos5250()) { > + if (!(soc_is_exynos5250() || soc_is_exynos5420())) { > pll_base = clk_get(NULL, "xtal"); This code is also removed by my series. > > if (!IS_ERR(pll_base)) { > @@ -244,6 +306,7 @@ arch_initcall(exynos_pm_drvinit); > static int exynos_pm_suspend(void) > { > unsigned long tmp; > + unsigned int cluster_id; > > /* Setting Central Sequence Register for power down mode */ > > @@ -253,10 +316,20 @@ static int exynos_pm_suspend(void) > > /* Setting SEQ_OPTION register */ > > - tmp = (S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0); > - __raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION); > + if (soc_is_exynos5420()) { > + cluster_id = (read_cpuid(CPUID_MPIDR) >> 8) & 0xf; > + if (!cluster_id) > + __raw_writel(EXYNOS5420_ARM_USE_STANDBY_WFI0, > + S5P_CENTRAL_SEQ_OPTION); > + else > + __raw_writel(EXYNOS5420_KFC_USE_STANDBY_WFI0, > + S5P_CENTRAL_SEQ_OPTION); > + } else if (soc_is_exynos5250()) { This code should be also called on other Exynos SoCs, not just 5250. > + tmp = (S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0); > + __raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION); > + } > > - if (!soc_is_exynos5250()) { > + if (!(soc_is_exynos5250() || soc_is_exynos5420())) { > /* Save Power control register */ > asm ("mrc p15, 0, %0, c15, c0, 0" > : "=r" (tmp) : : "cc"); > @@ -275,6 +348,15 @@ static void exynos_pm_resume(void) > { > unsigned long tmp; > > + if (soc_is_exynos5420()) { > + /* Restore the low power flag */ > + s3c_pm_do_restore(exynos5420_cpustate_save, > + ARRAY_SIZE(exynos5420_cpustate_save)); > + > + __raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL, > + S5P_CENTRAL_SEQ_OPTION); > + } > + > /* > * If PMU failed while entering sleep mode, WFI will be > * ignored by PMU and then exiting cpu_do_idle(). > @@ -290,7 +372,7 @@ static void exynos_pm_resume(void) > /* No need to perform below restore code */ > goto early_wakeup; > } > - if (!soc_is_exynos5250()) { > + if (!(soc_is_exynos5250() || soc_is_exynos5420())) { > /* Restore Power control register */ > tmp = save_arm_register[0]; > asm volatile ("mcr p15, 0, %0, c15, c0, 0" > @@ -306,21 +388,40 @@ static void exynos_pm_resume(void) > > /* For release retention */ > > - __raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION); > - __raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION); > - __raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION); > - __raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION); > - __raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION); > - __raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION); > - __raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION); > + if (soc_is_exynos5420()) { Indentation issue. > + __raw_writel((1 << 28), EXYNOS5420_PAD_RET_DRAM_OPTION); > + __raw_writel((1 << 28), EXYNOS5420_PAD_RET_MAUDIO_OPTION); > + __raw_writel((1 << 28), EXYNOS5420_PAD_RET_JTAG_OPTION); > + __raw_writel((1 << 28), EXYNOS5420_PAD_RET_GPIO_OPTION); > + __raw_writel((1 << 28), EXYNOS5420_PAD_RET_UART_OPTION); > + __raw_writel((1 << 28), EXYNOS5420_PAD_RET_MMCA_OPTION); > + __raw_writel((1 << 28), EXYNOS5420_PAD_RET_MMCB_OPTION); > + __raw_writel((1 << 28), EXYNOS5420_PAD_RET_MMCC_OPTION); > + __raw_writel((1 << 28), EXYNOS5420_PAD_RET_HSI_OPTION); > + __raw_writel((1 << 28), EXYNOS5420_PAD_RET_EBIA_OPTION); > + __raw_writel((1 << 28), EXYNOS5420_PAD_RET_EBIB_OPTION); > + __raw_writel((1 << 28), EXYNOS5420_PAD_RET_SPI_OPTION); > + __raw_writel((1 << 28), EXYNOS5420_PAD_RET_DRAM_COREBLK_OPTION); > + } else { > + __raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION); > + __raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION); > + __raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION); > + __raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION); > + __raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION); > + __raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION); > + __raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION); > + } > > if (soc_is_exynos5250()) > s3c_pm_do_restore(exynos5_sys_save, > ARRAY_SIZE(exynos5_sys_save)); > + else if (soc_is_exynos5420()) > + s3c_pm_do_restore(exynos5420_sys_save, > + ARRAY_SIZE(exynos5420_sys_save)); > > s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save)); > > - if (!soc_is_exynos5250()) { > + if (!(soc_is_exynos5250() || soc_is_exynos5420())) { > exynos4_restore_pll(); > > #ifdef CONFIG_SMP > @@ -330,6 +431,18 @@ static void exynos_pm_resume(void) > > early_wakeup: > > + if (soc_is_exynos5420()) { > + tmp = __raw_readl(EXYNOS5420_SFR_AXI_CGDIS1); > + tmp &= ~EXYNOS5420_UFS; > + __raw_writel(tmp, EXYNOS5420_SFR_AXI_CGDIS1); > + tmp = __raw_readl(EXYNOS5420_FSYS2_OPTION); > + tmp &= ~EXYNOS5420_EMULATION; > + __raw_writel(tmp, EXYNOS5420_FSYS2_OPTION); > + tmp = __raw_readl(EXYNOS5420_PSGEN_OPTION); > + tmp &= ~EXYNOS5420_EMULATION; > + __raw_writel(tmp, EXYNOS5420_PSGEN_OPTION); > + } > + > /* Clear SLEEP mode set in INFORM1 */ > __raw_writel(0x0, S5P_INFORM1); > > diff --git a/arch/arm/mach-exynos/pmu.c b/arch/arm/mach-exynos/pmu.c > index e39cc75..1449404 100644 > --- a/arch/arm/mach-exynos/pmu.c > +++ b/arch/arm/mach-exynos/pmu.c > @@ -16,6 +16,8 @@ > #include <mach/regs-clock.h> > #include <mach/regs-pmu.h> > > +#include <asm/cputype.h> > + > #include "common.h" > > static const struct exynos_pmu_conf *exynos_pmu_config; > @@ -318,6 +320,151 @@ static const struct exynos_pmu_conf exynos5250_pmu_config[] = { > { PMU_TABLE_END,}, > }; > > +static struct exynos_pmu_conf exynos5420_pmu_config[] = { static const? Best regards, Tomasz -- 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