aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
authorTomasz Figa <t.figa@samsung.com>2014-02-13 18:16:01 -0500
committerKukjin Kim <kgene.kim@samsung.com>2014-02-13 18:16:01 -0500
commit4fcf47e2db145f72b31b344fda64a8a6dacd8d1d (patch)
treebd49b51004f7027683725c09b2f4562d12a51a63 /drivers/clk
parent3efb25116774f69f0649fd6774fd46306cabdb56 (diff)
clk: samsung: exynos4: Add remaining suspend/resume handling
As of now, part of Exynos4 clock suspend/resume handling is located in mach-exynos/pm.c, which is not where code accessing CMU registers should reside. This patch implements all the necessary suspend/resume handling code in Exynos4 clock driver to allow dropping that old code. Signed-off-by: Tomasz Figa <t.figa@samsung.com> Acked-by: Kyungmin Park <kyungmin.park@samsung.com> Reviewed-by: Thomas Abraham <thomas.ab@samsung.com> Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/samsung/clk-exynos4.c76
1 files changed, 68 insertions, 8 deletions
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index b620a8375b7f..b4f967210175 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -140,6 +140,7 @@ static enum exynos4_soc exynos4_soc;
140#ifdef CONFIG_PM_SLEEP 140#ifdef CONFIG_PM_SLEEP
141static struct samsung_clk_reg_dump *exynos4_save_common; 141static struct samsung_clk_reg_dump *exynos4_save_common;
142static struct samsung_clk_reg_dump *exynos4_save_soc; 142static struct samsung_clk_reg_dump *exynos4_save_soc;
143static struct samsung_clk_reg_dump *exynos4_save_pll;
143 144
144/* 145/*
145 * list of controller registers to be saved and restored during a 146 * list of controller registers to be saved and restored during a
@@ -165,6 +166,17 @@ static unsigned long exynos4x12_clk_save[] __initdata = {
165 E4X12_MPLL_CON0, 166 E4X12_MPLL_CON0,
166}; 167};
167 168
169static unsigned long exynos4_clk_pll_regs[] __initdata = {
170 EPLL_LOCK,
171 VPLL_LOCK,
172 EPLL_CON0,
173 EPLL_CON1,
174 EPLL_CON2,
175 VPLL_CON0,
176 VPLL_CON1,
177 VPLL_CON2,
178};
179
168static unsigned long exynos4_clk_regs[] __initdata = { 180static unsigned long exynos4_clk_regs[] __initdata = {
169 SRC_LEFTBUS, 181 SRC_LEFTBUS,
170 DIV_LEFTBUS, 182 DIV_LEFTBUS,
@@ -172,12 +184,6 @@ static unsigned long exynos4_clk_regs[] __initdata = {
172 SRC_RIGHTBUS, 184 SRC_RIGHTBUS,
173 DIV_RIGHTBUS, 185 DIV_RIGHTBUS,
174 GATE_IP_RIGHTBUS, 186 GATE_IP_RIGHTBUS,
175 EPLL_CON0,
176 EPLL_CON1,
177 EPLL_CON2,
178 VPLL_CON0,
179 VPLL_CON1,
180 VPLL_CON2,
181 SRC_TOP0, 187 SRC_TOP0,
182 SRC_TOP1, 188 SRC_TOP1,
183 SRC_CAM, 189 SRC_CAM,
@@ -238,23 +244,70 @@ static unsigned long exynos4_clk_regs[] __initdata = {
238 GATE_IP_CPU, 244 GATE_IP_CPU,
239}; 245};
240 246
247static const struct samsung_clk_reg_dump src_mask_suspend[] = {
248 { .offset = SRC_MASK_TOP, .value = 0x00000001, },
249 { .offset = SRC_MASK_CAM, .value = 0x11111111, },
250 { .offset = SRC_MASK_TV, .value = 0x00000111, },
251 { .offset = SRC_MASK_LCD0, .value = 0x00001111, },
252 { .offset = SRC_MASK_MAUDIO, .value = 0x00000001, },
253 { .offset = SRC_MASK_FSYS, .value = 0x01011111, },
254 { .offset = SRC_MASK_PERIL0, .value = 0x01111111, },
255 { .offset = SRC_MASK_PERIL1, .value = 0x01110111, },
256 { .offset = SRC_MASK_DMC, .value = 0x00010000, },
257};
258
259static const struct samsung_clk_reg_dump src_mask_suspend_e4210[] = {
260 { .offset = E4210_SRC_MASK_LCD1, .value = 0x00001111, },
261};
262
263#define PLL_ENABLED (1 << 31)
264#define PLL_LOCKED (1 << 29)
265
266static void exynos4_clk_wait_for_pll(u32 reg)
267{
268 u32 pll_con;
269
270 pll_con = readl(reg_base + reg);
271 if (!(pll_con & PLL_ENABLED))
272 return;
273
274 while (!(pll_con & PLL_LOCKED)) {
275 cpu_relax();
276 pll_con = readl(reg_base + reg);
277 }
278}
279
241static int exynos4_clk_suspend(void) 280static int exynos4_clk_suspend(void)
242{ 281{
243 samsung_clk_save(reg_base, exynos4_save_common, 282 samsung_clk_save(reg_base, exynos4_save_common,
244 ARRAY_SIZE(exynos4_clk_regs)); 283 ARRAY_SIZE(exynos4_clk_regs));
284 samsung_clk_save(reg_base, exynos4_save_pll,
285 ARRAY_SIZE(exynos4_clk_pll_regs));
245 286
246 if (exynos4_soc == EXYNOS4210) 287 if (exynos4_soc == EXYNOS4210) {
247 samsung_clk_save(reg_base, exynos4_save_soc, 288 samsung_clk_save(reg_base, exynos4_save_soc,
248 ARRAY_SIZE(exynos4210_clk_save)); 289 ARRAY_SIZE(exynos4210_clk_save));
249 else 290 samsung_clk_restore(reg_base, src_mask_suspend_e4210,
291 ARRAY_SIZE(src_mask_suspend_e4210));
292 } else {
250 samsung_clk_save(reg_base, exynos4_save_soc, 293 samsung_clk_save(reg_base, exynos4_save_soc,
251 ARRAY_SIZE(exynos4x12_clk_save)); 294 ARRAY_SIZE(exynos4x12_clk_save));
295 }
296
297 samsung_clk_restore(reg_base, src_mask_suspend,
298 ARRAY_SIZE(src_mask_suspend));
252 299
253 return 0; 300 return 0;
254} 301}
255 302
256static void exynos4_clk_resume(void) 303static void exynos4_clk_resume(void)
257{ 304{
305 samsung_clk_restore(reg_base, exynos4_save_pll,
306 ARRAY_SIZE(exynos4_clk_pll_regs));
307
308 exynos4_clk_wait_for_pll(EPLL_CON0);
309 exynos4_clk_wait_for_pll(VPLL_CON0);
310
258 samsung_clk_restore(reg_base, exynos4_save_common, 311 samsung_clk_restore(reg_base, exynos4_save_common,
259 ARRAY_SIZE(exynos4_clk_regs)); 312 ARRAY_SIZE(exynos4_clk_regs));
260 313
@@ -289,9 +342,16 @@ static void exynos4_clk_sleep_init(void)
289 if (!exynos4_save_soc) 342 if (!exynos4_save_soc)
290 goto err_common; 343 goto err_common;
291 344
345 exynos4_save_pll = samsung_clk_alloc_reg_dump(exynos4_clk_pll_regs,
346 ARRAY_SIZE(exynos4_clk_pll_regs));
347 if (!exynos4_save_pll)
348 goto err_soc;
349
292 register_syscore_ops(&exynos4_clk_syscore_ops); 350 register_syscore_ops(&exynos4_clk_syscore_ops);
293 return; 351 return;
294 352
353err_soc:
354 kfree(exynos4_save_soc);
295err_common: 355err_common:
296 kfree(exynos4_save_common); 356 kfree(exynos4_save_common);
297err_warn: 357err_warn: