ARM: EXYNOS: Add ARM down clock support
authorAbhilash Kesavan <a.kesavan@samsung.com>
Tue, 20 Nov 2012 11:34:58 +0000 (20:34 +0900)
committerKukjin Kim <kgene.kim@samsung.com>
Tue, 20 Nov 2012 11:34:58 +0000 (20:34 +0900)
In idle state down clocking the arm cores can result in power
savings. Program the power control registers to achieve this and
save these registers across a suspend/resume cycle.

Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
arch/arm/mach-exynos/clock-exynos5.c
arch/arm/mach-exynos/cpuidle.c
arch/arm/mach-exynos/include/mach/regs-clock.h

index de9ae13..31f4509 100644 (file)
@@ -80,6 +80,8 @@ static struct sleep_save exynos5_clock_save[] = {
        SAVE_ITEM(EXYNOS5_VPLL_CON0),
        SAVE_ITEM(EXYNOS5_VPLL_CON1),
        SAVE_ITEM(EXYNOS5_VPLL_CON2),
+       SAVE_ITEM(EXYNOS5_PWR_CTRL1),
+       SAVE_ITEM(EXYNOS5_PWR_CTRL2),
 };
 #endif
 
index cff0595..4ddda91 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/suspend.h>
 #include <asm/unified.h>
 #include <asm/cpuidle.h>
+#include <mach/regs-clock.h>
 #include <mach/regs-pmu.h>
 #include <mach/pmu.h>
 
@@ -156,12 +157,47 @@ static int exynos4_enter_lowpower(struct cpuidle_device *dev,
                return exynos4_enter_core0_aftr(dev, drv, new_index);
 }
 
+static void __init exynos5_core_down_clk(void)
+{
+       unsigned int tmp;
+
+       /*
+        * Enable arm clock down (in idle) and set arm divider
+        * ratios in WFI/WFE state.
+        */
+       tmp = PWR_CTRL1_CORE2_DOWN_RATIO | \
+             PWR_CTRL1_CORE1_DOWN_RATIO | \
+             PWR_CTRL1_DIV2_DOWN_EN     | \
+             PWR_CTRL1_DIV1_DOWN_EN     | \
+             PWR_CTRL1_USE_CORE1_WFE    | \
+             PWR_CTRL1_USE_CORE0_WFE    | \
+             PWR_CTRL1_USE_CORE1_WFI    | \
+             PWR_CTRL1_USE_CORE0_WFI;
+       __raw_writel(tmp, EXYNOS5_PWR_CTRL1);
+
+       /*
+        * Enable arm clock up (on exiting idle). Set arm divider
+        * ratios when not in idle along with the standby duration
+        * ratios.
+        */
+       tmp = PWR_CTRL2_DIV2_UP_EN       | \
+             PWR_CTRL2_DIV1_UP_EN       | \
+             PWR_CTRL2_DUR_STANDBY2_VAL | \
+             PWR_CTRL2_DUR_STANDBY1_VAL | \
+             PWR_CTRL2_CORE2_UP_RATIO   | \
+             PWR_CTRL2_CORE1_UP_RATIO;
+       __raw_writel(tmp, EXYNOS5_PWR_CTRL2);
+}
+
 static int __init exynos4_init_cpuidle(void)
 {
        int i, max_cpuidle_state, cpu_id;
        struct cpuidle_device *device;
        struct cpuidle_driver *drv = &exynos4_idle_driver;
 
+       if (soc_is_exynos5250())
+               exynos5_core_down_clk();
+
        /* Setup cpuidle driver */
        drv->state_count = (sizeof(exynos4_cpuidle_set) /
                                       sizeof(struct cpuidle_state));
index 8c9b38c..d36ad76 100644 (file)
 #define EXYNOS5_CLKDIV_STATCPU0                        EXYNOS_CLKREG(0x00600)
 #define EXYNOS5_CLKDIV_STATCPU1                        EXYNOS_CLKREG(0x00604)
 
+#define EXYNOS5_PWR_CTRL1                      EXYNOS_CLKREG(0x01020)
+#define EXYNOS5_PWR_CTRL2                      EXYNOS_CLKREG(0x01024)
+
 #define EXYNOS5_MPLL_CON0                      EXYNOS_CLKREG(0x04100)
 #define EXYNOS5_CLKSRC_CORE1                   EXYNOS_CLKREG(0x04204)
 
 
 #define EXYNOS5_EPLLCON0_LOCKED_SHIFT          (29)
 
+#define PWR_CTRL1_CORE2_DOWN_RATIO             (7 << 28)
+#define PWR_CTRL1_CORE1_DOWN_RATIO             (7 << 16)
+#define PWR_CTRL1_DIV2_DOWN_EN                 (1 << 9)
+#define PWR_CTRL1_DIV1_DOWN_EN                 (1 << 8)
+#define PWR_CTRL1_USE_CORE1_WFE                        (1 << 5)
+#define PWR_CTRL1_USE_CORE0_WFE                        (1 << 4)
+#define PWR_CTRL1_USE_CORE1_WFI                        (1 << 1)
+#define PWR_CTRL1_USE_CORE0_WFI                        (1 << 0)
+
+#define PWR_CTRL2_DIV2_UP_EN                   (1 << 25)
+#define PWR_CTRL2_DIV1_UP_EN                   (1 << 24)
+#define PWR_CTRL2_DUR_STANDBY2_VAL             (1 << 16)
+#define PWR_CTRL2_DUR_STANDBY1_VAL             (1 << 8)
+#define PWR_CTRL2_CORE2_UP_RATIO               (1 << 4)
+#define PWR_CTRL2_CORE1_UP_RATIO               (1 << 0)
+
 /* Compatibility defines and inclusion */
 
 #include <mach/regs-pmu.h>