diff options
author | Tomasz Figa <t.figa@samsung.com> | 2014-02-13 18:16:01 -0500 |
---|---|---|
committer | Kukjin Kim <kgene.kim@samsung.com> | 2014-02-13 18:16:01 -0500 |
commit | 4fcf47e2db145f72b31b344fda64a8a6dacd8d1d (patch) | |
tree | bd49b51004f7027683725c09b2f4562d12a51a63 /drivers/clk | |
parent | 3efb25116774f69f0649fd6774fd46306cabdb56 (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.c | 76 |
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 |
141 | static struct samsung_clk_reg_dump *exynos4_save_common; | 141 | static struct samsung_clk_reg_dump *exynos4_save_common; |
142 | static struct samsung_clk_reg_dump *exynos4_save_soc; | 142 | static struct samsung_clk_reg_dump *exynos4_save_soc; |
143 | static 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 | ||
169 | static 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 | |||
168 | static unsigned long exynos4_clk_regs[] __initdata = { | 180 | static 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 | ||
247 | static 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 | |||
259 | static 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 | |||
266 | static 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 | |||
241 | static int exynos4_clk_suspend(void) | 280 | static 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 | ||
256 | static void exynos4_clk_resume(void) | 303 | static 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 | ||
353 | err_soc: | ||
354 | kfree(exynos4_save_soc); | ||
295 | err_common: | 355 | err_common: |
296 | kfree(exynos4_save_common); | 356 | kfree(exynos4_save_common); |
297 | err_warn: | 357 | err_warn: |