Re: [PATCH V3 1/6] ARM: exynos: Add AFTR mode cpuidle state on EXYNOS4210

2011-11-24 Thread amit kachhap
On Thu, Nov 24, 2011 at 9:37 AM, Inderpal Singh
 wrote:
> Hi Amit,
>
> On 22 November 2011 15:05, Amit Daniel Kachhap  
> wrote:
>>
>> This patch adds support AFTR(ARM OFF TOP RUNNING) mode in
>> cpuidle driver. L2 cache keeps their data in this mode.
>> This patch ports the code to the latest interfaces to
>> save/restore CPU state inclusive of CPU PM notifiers, l2
>> resume and cpu_suspend/resume.
>>
>> Signed-off-by: Jaecheol Lee 
>> Signed-off-by: Lorenzo Pieralisi 
>> Signed-off-by: Amit Daniel Kachhap 
>> ---
>>  arch/arm/mach-exynos/cpuidle.c          |  152 
>> ++-
>>  arch/arm/mach-exynos/include/mach/pmu.h |    2 +
>>  2 files changed, 151 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c
>> index 21403c8..89afa93 100644
>> --- a/arch/arm/mach-exynos/cpuidle.c
>> +++ b/arch/arm/mach-exynos/cpuidle.c
>> @@ -12,15 +12,37 @@
>>  #include 
>>  #include 
>>  #include 
>> +#include 
>>  #include 
>>  #include 
>>  #include 
>>
>>  #include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +
>> +#include 
>> +#include 
>> +
>> +#define REG_DIRECTGO_ADDR      (samsung_rev() == EXYNOS4210_REV_1_1 ? \
>> +                       S5P_INFORM7 : (samsung_rev() == EXYNOS4210_REV_1_0 ? 
>> \
>> +                       (S5P_VA_SYSRAM + 0x24) : S5P_INFORM0))
>> +#define REG_DIRECTGO_FLAG      (samsung_rev() == EXYNOS4210_REV_1_1 ? \
>> +                       S5P_INFORM6 : (samsung_rev() == EXYNOS4210_REV_1_0 ? 
>> \
>> +                       (S5P_VA_SYSRAM + 0x20) : S5P_INFORM1))
>> +
>> +#define S5P_CHECK_AFTR         (samsung_rev() == EXYNOS4210_REV_1_0 ? \
>> +                               0xBAD0 : 0xFCBA0D10)
>>
>>  static int exynos4_enter_idle(struct cpuidle_device *dev,
>>                        struct cpuidle_driver *drv,
>>                              int index);
>> +static int exynos4_enter_lowpower(struct cpuidle_device *dev,
>> +                               struct cpuidle_driver *drv,
>> +                               int index);
>>
>>  static struct cpuidle_state exynos4_cpuidle_set[] = {
>>        [0] = {
>> @@ -28,9 +50,17 @@ static struct cpuidle_state exynos4_cpuidle_set[] = {
>>                .exit_latency           = 1,
>>                .target_residency       = 10,
>>                .flags                  = CPUIDLE_FLAG_TIME_VALID,
>> -               .name                   = "IDLE",
>> +               .name                   = "C0",
>>                .desc                   = "ARM clock gating(WFI)",
>>        },
>> +       [1] = {
>> +               .enter                  = exynos4_enter_lowpower,
>> +               .exit_latency           = 300,
>> +               .target_residency       = 10,
>> +               .flags                  = CPUIDLE_FLAG_TIME_VALID,
>> +               .name                   = "C1",
>> +               .desc                   = "ARM power down",
>> +       },
>>  };
>>
>>  static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
>> @@ -40,9 +70,101 @@ static struct cpuidle_driver exynos4_idle_driver = {
>>        .owner          = THIS_MODULE,
>>  };
>>
>> +/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
>> +static void exynos4_set_wakeupmask(void)
>> +{
>> +       __raw_writel(0xff3e, S5P_WAKEUP_MASK);
>> +}
>> +
>> +static unsigned int g_pwr_ctrl, g_diag_reg;
>> +
>> +static void save_cpu_arch_register(void)
>> +{
>> +       /*read power control register*/
>> +       asm("mrc p15, 0, %0, c15, c0, 0" : "=r"(g_pwr_ctrl) : : "cc");
>> +       /*read diagnostic register*/
>> +       asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc");
>> +       return;
>> +}
>> +
>> +static void restore_cpu_arch_register(void)
>> +{
>> +       /*write power control register*/
>> +       asm("mcr p15, 0, %0, c15, c0, 0" : : "r"(g_pwr_ctrl) : "cc");
>> +       /*write diagnostic register*/
>> +       asm("mcr p15, 0, %0, c15, c0, 1" : : "r"(g_diag_reg) : "cc");
>> +       return;
>> +}
>> +
>> +static int idle_finisher(unsigned long flags)
>> +{
>> +       cpu_do_idle();
>> +       return 1;
>> +}
>> +
>> +static int exynos4_enter_core0_aftr(struct cpuidle_device *dev,
>> +                               struct cpuidle_driver *drv,
>> +                               int index)
>> +{
>> +       struct timeval before, after;
>> +       int idle_time;
>> +       unsigned long tmp;
>> +
>> +       local_irq_disable();
>> +       do_gettimeofday(&before);
>> +
>> +       exynos4_set_wakeupmask();
>> +
>> +       /* Set value of power down register for aftr mode */
>> +       exynos4_sys_powerdown_conf(SYS_AFTR);
>> +
>> +       __raw_writel(BSYM(virt_to_phys(s3c_cpu_resume)),
>> +                                                REG_DIRECTGO_ADDR);
>> +       __raw_writel(S5P_CHECK_AFTR, REG_DIRECTGO_FLAG);
>> +
>> +       save_cpu_arch_register();
>> +
>> +       /* Setting Central Sequence Register for power down mod

Re: [PATCH V3 1/6] ARM: exynos: Add AFTR mode cpuidle state on EXYNOS4210

2011-11-23 Thread Inderpal Singh
Hi Amit,

On 22 November 2011 15:05, Amit Daniel Kachhap  wrote:
>
> This patch adds support AFTR(ARM OFF TOP RUNNING) mode in
> cpuidle driver. L2 cache keeps their data in this mode.
> This patch ports the code to the latest interfaces to
> save/restore CPU state inclusive of CPU PM notifiers, l2
> resume and cpu_suspend/resume.
>
> Signed-off-by: Jaecheol Lee 
> Signed-off-by: Lorenzo Pieralisi 
> Signed-off-by: Amit Daniel Kachhap 
> ---
>  arch/arm/mach-exynos/cpuidle.c          |  152 
> ++-
>  arch/arm/mach-exynos/include/mach/pmu.h |    2 +
>  2 files changed, 151 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c
> index 21403c8..89afa93 100644
> --- a/arch/arm/mach-exynos/cpuidle.c
> +++ b/arch/arm/mach-exynos/cpuidle.c
> @@ -12,15 +12,37 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
>
>  #include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +#include 
> +
> +#define REG_DIRECTGO_ADDR      (samsung_rev() == EXYNOS4210_REV_1_1 ? \
> +                       S5P_INFORM7 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \
> +                       (S5P_VA_SYSRAM + 0x24) : S5P_INFORM0))
> +#define REG_DIRECTGO_FLAG      (samsung_rev() == EXYNOS4210_REV_1_1 ? \
> +                       S5P_INFORM6 : (samsung_rev() == EXYNOS4210_REV_1_0 ? \
> +                       (S5P_VA_SYSRAM + 0x20) : S5P_INFORM1))
> +
> +#define S5P_CHECK_AFTR         (samsung_rev() == EXYNOS4210_REV_1_0 ? \
> +                               0xBAD0 : 0xFCBA0D10)
>
>  static int exynos4_enter_idle(struct cpuidle_device *dev,
>                        struct cpuidle_driver *drv,
>                              int index);
> +static int exynos4_enter_lowpower(struct cpuidle_device *dev,
> +                               struct cpuidle_driver *drv,
> +                               int index);
>
>  static struct cpuidle_state exynos4_cpuidle_set[] = {
>        [0] = {
> @@ -28,9 +50,17 @@ static struct cpuidle_state exynos4_cpuidle_set[] = {
>                .exit_latency           = 1,
>                .target_residency       = 10,
>                .flags                  = CPUIDLE_FLAG_TIME_VALID,
> -               .name                   = "IDLE",
> +               .name                   = "C0",
>                .desc                   = "ARM clock gating(WFI)",
>        },
> +       [1] = {
> +               .enter                  = exynos4_enter_lowpower,
> +               .exit_latency           = 300,
> +               .target_residency       = 10,
> +               .flags                  = CPUIDLE_FLAG_TIME_VALID,
> +               .name                   = "C1",
> +               .desc                   = "ARM power down",
> +       },
>  };
>
>  static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
> @@ -40,9 +70,101 @@ static struct cpuidle_driver exynos4_idle_driver = {
>        .owner          = THIS_MODULE,
>  };
>
> +/* Ext-GIC nIRQ/nFIQ is the only wakeup source in AFTR */
> +static void exynos4_set_wakeupmask(void)
> +{
> +       __raw_writel(0xff3e, S5P_WAKEUP_MASK);
> +}
> +
> +static unsigned int g_pwr_ctrl, g_diag_reg;
> +
> +static void save_cpu_arch_register(void)
> +{
> +       /*read power control register*/
> +       asm("mrc p15, 0, %0, c15, c0, 0" : "=r"(g_pwr_ctrl) : : "cc");
> +       /*read diagnostic register*/
> +       asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc");
> +       return;
> +}
> +
> +static void restore_cpu_arch_register(void)
> +{
> +       /*write power control register*/
> +       asm("mcr p15, 0, %0, c15, c0, 0" : : "r"(g_pwr_ctrl) : "cc");
> +       /*write diagnostic register*/
> +       asm("mcr p15, 0, %0, c15, c0, 1" : : "r"(g_diag_reg) : "cc");
> +       return;
> +}
> +
> +static int idle_finisher(unsigned long flags)
> +{
> +       cpu_do_idle();
> +       return 1;
> +}
> +
> +static int exynos4_enter_core0_aftr(struct cpuidle_device *dev,
> +                               struct cpuidle_driver *drv,
> +                               int index)
> +{
> +       struct timeval before, after;
> +       int idle_time;
> +       unsigned long tmp;
> +
> +       local_irq_disable();
> +       do_gettimeofday(&before);
> +
> +       exynos4_set_wakeupmask();
> +
> +       /* Set value of power down register for aftr mode */
> +       exynos4_sys_powerdown_conf(SYS_AFTR);
> +
> +       __raw_writel(BSYM(virt_to_phys(s3c_cpu_resume)),
> +                                                REG_DIRECTGO_ADDR);
> +       __raw_writel(S5P_CHECK_AFTR, REG_DIRECTGO_FLAG);
> +
> +       save_cpu_arch_register();
> +
> +       /* Setting Central Sequence Register for power down mode */
> +       tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
> +       tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
> +       __raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
> +
> +       cpu_pm_enter();
> +       c