aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
authorKrzysztof Kozlowski <k.kozlowski@samsung.com>2014-07-18 10:36:32 -0400
committerTomasz Figa <t.figa@samsung.com>2014-07-25 20:49:31 -0400
commit42773b28e71d06daeceba106ea12c8be2e48011f (patch)
tree5db6bd3049dc07b02edb60e5442aa5949022d4c2 /drivers/clk
parentd19bb397e19e271aead5c3e089f48475fb14b647 (diff)
clk: samsung: exynos4: Enable ARMCLK down feature
Enable ARMCLK down feature on all Exynos4 SoCs. The frequency of ARMCLK will be reduced upon entering idle mode (WFI or WFE). The feature behaves like very fast cpufreq ondemand governor. In idle mode this reduces energy consumption on full frequency chosen by cpufreq governor by approximately: - Trats2: 6.5% (153 mA -> 143 mA) - Trats: 33.0% (180 mA -> 120 mA) - Gear1: 27.0% (180 mA -> 130 mA) The patch uses simillar settings as Exynos5250 (clk-exynos5250.c), except it disables clock up feature and on Exynos4412 ARMCLK down is enabled for all 4 cores. Tested on Trats board (Exynos4210), Trats2 board (Exynos4412) and Samsung Gear 1 (Exynos4212). Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Tested-by: Daniel Drake <drake@endlessm.com> Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/samsung/clk-exynos4.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 3effe7abb2e2..1563ea83f5e8 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -119,11 +119,27 @@
119#define GATE_SCLK_CPU 0x14800 119#define GATE_SCLK_CPU 0x14800
120#define GATE_IP_CPU 0x14900 120#define GATE_IP_CPU 0x14900
121#define CLKOUT_CMU_CPU 0x14a00 121#define CLKOUT_CMU_CPU 0x14a00
122#define PWR_CTRL1 0x15020
123#define E4X12_PWR_CTRL2 0x15024
122#define E4X12_DIV_ISP0 0x18300 124#define E4X12_DIV_ISP0 0x18300
123#define E4X12_DIV_ISP1 0x18304 125#define E4X12_DIV_ISP1 0x18304
124#define E4X12_GATE_ISP0 0x18800 126#define E4X12_GATE_ISP0 0x18800
125#define E4X12_GATE_ISP1 0x18804 127#define E4X12_GATE_ISP1 0x18804
126 128
129/* Below definitions are used for PWR_CTRL settings */
130#define PWR_CTRL1_CORE2_DOWN_RATIO(x) (((x) & 0x7) << 28)
131#define PWR_CTRL1_CORE1_DOWN_RATIO(x) (((x) & 0x7) << 16)
132#define PWR_CTRL1_DIV2_DOWN_EN (1 << 9)
133#define PWR_CTRL1_DIV1_DOWN_EN (1 << 8)
134#define PWR_CTRL1_USE_CORE3_WFE (1 << 7)
135#define PWR_CTRL1_USE_CORE2_WFE (1 << 6)
136#define PWR_CTRL1_USE_CORE1_WFE (1 << 5)
137#define PWR_CTRL1_USE_CORE0_WFE (1 << 4)
138#define PWR_CTRL1_USE_CORE3_WFI (1 << 3)
139#define PWR_CTRL1_USE_CORE2_WFI (1 << 2)
140#define PWR_CTRL1_USE_CORE1_WFI (1 << 1)
141#define PWR_CTRL1_USE_CORE0_WFI (1 << 0)
142
127/* the exynos4 soc type */ 143/* the exynos4 soc type */
128enum exynos4_soc { 144enum exynos4_soc {
129 EXYNOS4210, 145 EXYNOS4210,
@@ -160,6 +176,7 @@ static unsigned long exynos4210_clk_save[] __initdata = {
160 E4210_GATE_IP_LCD1, 176 E4210_GATE_IP_LCD1,
161 E4210_GATE_IP_PERIR, 177 E4210_GATE_IP_PERIR,
162 E4210_MPLL_CON0, 178 E4210_MPLL_CON0,
179 PWR_CTRL1,
163}; 180};
164 181
165static unsigned long exynos4x12_clk_save[] __initdata = { 182static unsigned long exynos4x12_clk_save[] __initdata = {
@@ -169,6 +186,8 @@ static unsigned long exynos4x12_clk_save[] __initdata = {
169 E4X12_DIV_ISP, 186 E4X12_DIV_ISP,
170 E4X12_DIV_CAM1, 187 E4X12_DIV_CAM1,
171 E4X12_MPLL_CON0, 188 E4X12_MPLL_CON0,
189 PWR_CTRL1,
190 E4X12_PWR_CTRL2,
172}; 191};
173 192
174static unsigned long exynos4_clk_pll_regs[] __initdata = { 193static unsigned long exynos4_clk_pll_regs[] __initdata = {
@@ -1337,6 +1356,32 @@ static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = {
1337 VPLL_LOCK, VPLL_CON0, NULL), 1356 VPLL_LOCK, VPLL_CON0, NULL),
1338}; 1357};
1339 1358
1359static void __init exynos4_core_down_clock(enum exynos4_soc soc)
1360{
1361 unsigned int tmp;
1362
1363 /*
1364 * Enable arm clock down (in idle) and set arm divider
1365 * ratios in WFI/WFE state.
1366 */
1367 tmp = (PWR_CTRL1_CORE2_DOWN_RATIO(7) | PWR_CTRL1_CORE1_DOWN_RATIO(7) |
1368 PWR_CTRL1_DIV2_DOWN_EN | PWR_CTRL1_DIV1_DOWN_EN |
1369 PWR_CTRL1_USE_CORE1_WFE | PWR_CTRL1_USE_CORE0_WFE |
1370 PWR_CTRL1_USE_CORE1_WFI | PWR_CTRL1_USE_CORE0_WFI);
1371 /* On Exynos4412 enable it also on core 2 and 3 */
1372 if (num_possible_cpus() == 4)
1373 tmp |= PWR_CTRL1_USE_CORE3_WFE | PWR_CTRL1_USE_CORE2_WFE |
1374 PWR_CTRL1_USE_CORE3_WFI | PWR_CTRL1_USE_CORE2_WFI;
1375 __raw_writel(tmp, reg_base + PWR_CTRL1);
1376
1377 /*
1378 * Disable the clock up feature on Exynos4x12, in case it was
1379 * enabled by bootloader.
1380 */
1381 if (exynos4_soc == EXYNOS4X12)
1382 __raw_writel(0x0, reg_base + E4X12_PWR_CTRL2);
1383}
1384
1340/* register exynos4 clocks */ 1385/* register exynos4 clocks */
1341static void __init exynos4_clk_init(struct device_node *np, 1386static void __init exynos4_clk_init(struct device_node *np,
1342 enum exynos4_soc soc) 1387 enum exynos4_soc soc)
@@ -1431,6 +1476,7 @@ static void __init exynos4_clk_init(struct device_node *np,
1431 samsung_clk_register_alias(ctx, exynos4_aliases, 1476 samsung_clk_register_alias(ctx, exynos4_aliases,
1432 ARRAY_SIZE(exynos4_aliases)); 1477 ARRAY_SIZE(exynos4_aliases));
1433 1478
1479 exynos4_core_down_clock(soc);
1434 exynos4_clk_sleep_init(); 1480 exynos4_clk_sleep_init();
1435 1481
1436 samsung_clk_of_add_provider(np, ctx); 1482 samsung_clk_of_add_provider(np, ctx);