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 | |
| 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>
| -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: |
