Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Tomasz Figa and committed by
Kukjin Kim
4fcf47e2 3efb2511

+68 -8
+68 -8
drivers/clk/samsung/clk-exynos4.c
··· 140 140 #ifdef CONFIG_PM_SLEEP 141 141 static struct samsung_clk_reg_dump *exynos4_save_common; 142 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 146 * list of controller registers to be saved and restored during a ··· 166 165 E4X12_MPLL_CON0, 167 166 }; 168 167 168 + static unsigned long exynos4_clk_pll_regs[] __initdata = { 169 + EPLL_LOCK, 170 + VPLL_LOCK, 171 + EPLL_CON0, 172 + EPLL_CON1, 173 + EPLL_CON2, 174 + VPLL_CON0, 175 + VPLL_CON1, 176 + VPLL_CON2, 177 + }; 178 + 169 179 static unsigned long exynos4_clk_regs[] __initdata = { 170 180 SRC_LEFTBUS, 171 181 DIV_LEFTBUS, ··· 184 172 SRC_RIGHTBUS, 185 173 DIV_RIGHTBUS, 186 174 GATE_IP_RIGHTBUS, 187 - EPLL_CON0, 188 - EPLL_CON1, 189 - EPLL_CON2, 190 - VPLL_CON0, 191 - VPLL_CON1, 192 - VPLL_CON2, 193 175 SRC_TOP0, 194 176 SRC_TOP1, 195 177 SRC_CAM, ··· 244 238 GATE_IP_CPU, 245 239 }; 246 240 241 + static const struct samsung_clk_reg_dump src_mask_suspend[] = { 242 + { .offset = SRC_MASK_TOP, .value = 0x00000001, }, 243 + { .offset = SRC_MASK_CAM, .value = 0x11111111, }, 244 + { .offset = SRC_MASK_TV, .value = 0x00000111, }, 245 + { .offset = SRC_MASK_LCD0, .value = 0x00001111, }, 246 + { .offset = SRC_MASK_MAUDIO, .value = 0x00000001, }, 247 + { .offset = SRC_MASK_FSYS, .value = 0x01011111, }, 248 + { .offset = SRC_MASK_PERIL0, .value = 0x01111111, }, 249 + { .offset = SRC_MASK_PERIL1, .value = 0x01110111, }, 250 + { .offset = SRC_MASK_DMC, .value = 0x00010000, }, 251 + }; 252 + 253 + static const struct samsung_clk_reg_dump src_mask_suspend_e4210[] = { 254 + { .offset = E4210_SRC_MASK_LCD1, .value = 0x00001111, }, 255 + }; 256 + 257 + #define PLL_ENABLED (1 << 31) 258 + #define PLL_LOCKED (1 << 29) 259 + 260 + static void exynos4_clk_wait_for_pll(u32 reg) 261 + { 262 + u32 pll_con; 263 + 264 + pll_con = readl(reg_base + reg); 265 + if (!(pll_con & PLL_ENABLED)) 266 + return; 267 + 268 + while (!(pll_con & PLL_LOCKED)) { 269 + cpu_relax(); 270 + pll_con = readl(reg_base + reg); 271 + } 272 + } 273 + 247 274 static int exynos4_clk_suspend(void) 248 275 { 249 276 samsung_clk_save(reg_base, exynos4_save_common, 250 277 ARRAY_SIZE(exynos4_clk_regs)); 278 + samsung_clk_save(reg_base, exynos4_save_pll, 279 + ARRAY_SIZE(exynos4_clk_pll_regs)); 251 280 252 - if (exynos4_soc == EXYNOS4210) 281 + if (exynos4_soc == EXYNOS4210) { 253 282 samsung_clk_save(reg_base, exynos4_save_soc, 254 283 ARRAY_SIZE(exynos4210_clk_save)); 255 - else 284 + samsung_clk_restore(reg_base, src_mask_suspend_e4210, 285 + ARRAY_SIZE(src_mask_suspend_e4210)); 286 + } else { 256 287 samsung_clk_save(reg_base, exynos4_save_soc, 257 288 ARRAY_SIZE(exynos4x12_clk_save)); 289 + } 290 + 291 + samsung_clk_restore(reg_base, src_mask_suspend, 292 + ARRAY_SIZE(src_mask_suspend)); 258 293 259 294 return 0; 260 295 } 261 296 262 297 static void exynos4_clk_resume(void) 263 298 { 299 + samsung_clk_restore(reg_base, exynos4_save_pll, 300 + ARRAY_SIZE(exynos4_clk_pll_regs)); 301 + 302 + exynos4_clk_wait_for_pll(EPLL_CON0); 303 + exynos4_clk_wait_for_pll(VPLL_CON0); 304 + 264 305 samsung_clk_restore(reg_base, exynos4_save_common, 265 306 ARRAY_SIZE(exynos4_clk_regs)); 266 307 ··· 342 289 if (!exynos4_save_soc) 343 290 goto err_common; 344 291 292 + exynos4_save_pll = samsung_clk_alloc_reg_dump(exynos4_clk_pll_regs, 293 + ARRAY_SIZE(exynos4_clk_pll_regs)); 294 + if (!exynos4_save_pll) 295 + goto err_soc; 296 + 345 297 register_syscore_ops(&exynos4_clk_syscore_ops); 346 298 return; 347 299 300 + err_soc: 301 + kfree(exynos4_save_soc); 348 302 err_common: 349 303 kfree(exynos4_save_common); 350 304 err_warn: