From 3581e56fd33b87ef485140c246d0db6c43fe4c58 Mon Sep 17 00:00:00 2001 From: Pankaj Dubey Date: Fri, 14 Feb 2014 07:25:05 +0900 Subject: clocksource: exynos_mct: remove unwanted header file inclusion remove unwanted header file inclusion "asm/mach/time.h" from exynos_mct.c Signed-off-by: Pankaj Dubey Signed-off-by: Kukjin Kim --- drivers/clocksource/exynos_mct.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index 48f76bc05da0..ed49b25fa552 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c @@ -25,8 +25,6 @@ #include #include -#include - #define EXYNOS4_MCTREG(x) (x) #define EXYNOS4_MCT_G_CNT_L EXYNOS4_MCTREG(0x100) #define EXYNOS4_MCT_G_CNT_U EXYNOS4_MCTREG(0x104) -- cgit v1.2.3 From a83784859ccde07ebdc3a7acfbb2f74cb6c75a80 Mon Sep 17 00:00:00 2001 From: Pankaj Dubey Date: Fri, 14 Feb 2014 07:27:40 +0900 Subject: irqchip: exynos-combiner: call handle_bad_irq directly This patch is inspired from following commit aec00956 (irqchip: gic: Call handle_bad_irq() directly) Also this will help in removing unwanted inclusion of header file "asm/mach/irq.h" Signed-off-by: Pankaj Dubey Reviewed-by: Tomasz Figa Signed-off-by: Kukjin Kim --- drivers/irqchip/exynos-combiner.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/irqchip/exynos-combiner.c b/drivers/irqchip/exynos-combiner.c index 40e6440348ff..f8636a650cf6 100644 --- a/drivers/irqchip/exynos-combiner.c +++ b/drivers/irqchip/exynos-combiner.c @@ -17,7 +17,6 @@ #include #include #include -#include #include "irqchip.h" @@ -81,7 +80,7 @@ static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) cascade_irq = irq_find_mapping(combiner_irq_domain, combiner_irq); if (unlikely(!cascade_irq)) - do_bad_IRQ(irq, desc); + handle_bad_irq(irq, desc); else generic_handle_irq(cascade_irq); -- cgit v1.2.3 From 442f4948e5b0b2bc6e77811a5e46fcd13f0870a6 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Fri, 14 Feb 2014 08:16:00 +0900 Subject: clk: exynos4: Remove remnants of non-DT support This patch simplifies a bit clock initialization code by removing remnants of non-DT clock initialization, such as reg_base and xom values passed in function parameters. Signed-off-by: Tomasz Figa Acked-by: Kyungmin Park Reviewed-by: Thomas Abraham Reviewed-by: Sylwester Nawrocki Signed-off-by: Kukjin Kim --- drivers/clk/samsung/clk-exynos4.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 010f071af883..12a9f28f9f17 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -908,12 +908,13 @@ static unsigned long exynos4_get_xom(void) return xom; } -static void __init exynos4_clk_register_finpll(unsigned long xom) +static void __init exynos4_clk_register_finpll(void) { struct samsung_fixed_rate_clock fclk; struct clk *clk; unsigned long finpll_f = 24000000; char *parent_name; + unsigned int xom = exynos4_get_xom(); parent_name = xom & 1 ? "xusbxti" : "xxti"; clk = clk_get(NULL, parent_name); @@ -1038,9 +1039,10 @@ static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = { /* register exynos4 clocks */ static void __init exynos4_clk_init(struct device_node *np, - enum exynos4_soc exynos4_soc, - void __iomem *reg_base, unsigned long xom) + enum exynos4_soc exynos4_soc) { + void __iomem *reg_base; + reg_base = of_iomap(np, 0); if (!reg_base) panic("%s: failed to map registers\n", __func__); @@ -1058,7 +1060,7 @@ static void __init exynos4_clk_init(struct device_node *np, ARRAY_SIZE(exynos4_fixed_rate_ext_clks), ext_clk_match); - exynos4_clk_register_finpll(xom); + exynos4_clk_register_finpll(); if (exynos4_soc == EXYNOS4210) { samsung_clk_register_mux(exynos4210_mux_early, @@ -1136,12 +1138,12 @@ static void __init exynos4_clk_init(struct device_node *np, static void __init exynos4210_clk_init(struct device_node *np) { - exynos4_clk_init(np, EXYNOS4210, NULL, exynos4_get_xom()); + exynos4_clk_init(np, EXYNOS4210); } CLK_OF_DECLARE(exynos4210_clk, "samsung,exynos4210-clock", exynos4210_clk_init); static void __init exynos4412_clk_init(struct device_node *np) { - exynos4_clk_init(np, EXYNOS4X12, NULL, exynos4_get_xom()); + exynos4_clk_init(np, EXYNOS4X12); } CLK_OF_DECLARE(exynos4412_clk, "samsung,exynos4412-clock", exynos4412_clk_init); -- cgit v1.2.3 From 3ccefbd2291d6ee59f242c05266e241c5e33667e Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Fri, 14 Feb 2014 08:16:00 +0900 Subject: clk: samsung: Provide common helpers for register save/restore As suspend/resume handlers are being moved to SoC specific code, due to differencies in suspend/resume handling of particular SoCs, to minimize code duplication this patch provides common register save/restore helpers that save/restore given list of registers of clock controller. Signed-off-by: Tomasz Figa Acked-by: Kyungmin Park Acked-by: Heiko Stuebner Reviewed-by: Thomas Abraham Reviewed-by: Sylwester Nawrocki Signed-off-by: Kukjin Kim --- drivers/clk/samsung/clk.c | 32 ++++++++++++++++++++++++++++++++ drivers/clk/samsung/clk.h | 10 ++++++++++ 2 files changed, 42 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index f503f32e2f80..c0a716b94a66 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -22,6 +22,38 @@ static struct clk_onecell_data clk_data; #endif #ifdef CONFIG_PM_SLEEP +void samsung_clk_save(void __iomem *base, + struct samsung_clk_reg_dump *rd, + unsigned int num_regs) +{ + for (; num_regs > 0; --num_regs, ++rd) + rd->value = readl(base + rd->offset); +} + +void samsung_clk_restore(void __iomem *base, + const struct samsung_clk_reg_dump *rd, + unsigned int num_regs) +{ + for (; num_regs > 0; --num_regs, ++rd) + writel(rd->value, base + rd->offset); +} + +struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(unsigned long *rdump, + unsigned long nr_rdump) +{ + struct samsung_clk_reg_dump *rd; + unsigned int i; + + rd = kcalloc(nr_rdump, sizeof(*rd), GFP_KERNEL); + if (!rd) + return NULL; + + for (i = 0; i < nr_rdump; ++i) + rd[i].offset = rdump[i]; + + return rd; +} + static struct samsung_clk_reg_dump *reg_dump; static unsigned long nr_reg_dump; diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index 31b4174e7a5b..ec8d46ba8178 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -340,4 +340,14 @@ extern void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list, extern unsigned long _get_rate(const char *clk_name); +extern void samsung_clk_save(void __iomem *base, + struct samsung_clk_reg_dump *rd, + unsigned int num_regs); +extern void samsung_clk_restore(void __iomem *base, + const struct samsung_clk_reg_dump *rd, + unsigned int num_regs); +extern struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump( + unsigned long *rdump, + unsigned long nr_rdump); + #endif /* __SAMSUNG_CLK_H */ -- cgit v1.2.3 From b7b647be157c9503aec9ce3c7d7e86205a6c39dc Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Fri, 14 Feb 2014 08:16:00 +0900 Subject: clk: samsung: exynos4: Move suspend/resume handling to SoC driver Since there are multiple differences in how suspend/resume of particular Exynos SoCs must be handled, SoC driver is better place for suspend/resume handlers and so this patch moves them. Signed-off-by: Tomasz Figa Acked-by: Kyungmin Park Reviewed-by: Thomas Abraham Reviewed-by: Sylwester Nawrocki Signed-off-by: Kukjin Kim --- drivers/clk/samsung/clk-exynos4.c | 90 ++++++++++++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 12a9f28f9f17..325f29248af5 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "clk.h" @@ -130,6 +131,16 @@ enum exynos4_plls { nr_plls /* number of PLLs */ }; +static void __iomem *reg_base; +static enum exynos4_soc exynos4_soc; + +/* + * Support for CMU save/restore across system suspends + */ +#ifdef CONFIG_PM_SLEEP +static struct samsung_clk_reg_dump *exynos4_save_common; +static struct samsung_clk_reg_dump *exynos4_save_soc; + /* * list of controller registers to be saved and restored during a * suspend/resume cycle. @@ -227,6 +238,70 @@ static unsigned long exynos4_clk_regs[] __initdata = { GATE_IP_CPU, }; +static int exynos4_clk_suspend(void) +{ + samsung_clk_save(reg_base, exynos4_save_common, + ARRAY_SIZE(exynos4_clk_regs)); + + if (exynos4_soc == EXYNOS4210) + samsung_clk_save(reg_base, exynos4_save_soc, + ARRAY_SIZE(exynos4210_clk_save)); + else + samsung_clk_save(reg_base, exynos4_save_soc, + ARRAY_SIZE(exynos4x12_clk_save)); + + return 0; +} + +static void exynos4_clk_resume(void) +{ + samsung_clk_restore(reg_base, exynos4_save_common, + ARRAY_SIZE(exynos4_clk_regs)); + + if (exynos4_soc == EXYNOS4210) + samsung_clk_restore(reg_base, exynos4_save_soc, + ARRAY_SIZE(exynos4210_clk_save)); + else + samsung_clk_restore(reg_base, exynos4_save_soc, + ARRAY_SIZE(exynos4x12_clk_save)); +} + +static struct syscore_ops exynos4_clk_syscore_ops = { + .suspend = exynos4_clk_suspend, + .resume = exynos4_clk_resume, +}; + +static void exynos4_clk_sleep_init(void) +{ + exynos4_save_common = samsung_clk_alloc_reg_dump(exynos4_clk_regs, + ARRAY_SIZE(exynos4_clk_regs)); + if (!exynos4_save_common) + goto err_warn; + + if (exynos4_soc == EXYNOS4210) + exynos4_save_soc = samsung_clk_alloc_reg_dump( + exynos4210_clk_save, + ARRAY_SIZE(exynos4210_clk_save)); + else + exynos4_save_soc = samsung_clk_alloc_reg_dump( + exynos4x12_clk_save, + ARRAY_SIZE(exynos4x12_clk_save)); + if (!exynos4_save_soc) + goto err_common; + + register_syscore_ops(&exynos4_clk_syscore_ops); + return; + +err_common: + kfree(exynos4_save_common); +err_warn: + pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", + __func__); +} +#else +static void exynos4_clk_sleep_init(void) {} +#endif + /* list of all parent clock list */ PNAME(mout_apll_p) = { "fin_pll", "fout_apll", }; PNAME(mout_mpll_p) = { "fin_pll", "fout_mpll", }; @@ -1039,22 +1114,15 @@ static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = { /* register exynos4 clocks */ static void __init exynos4_clk_init(struct device_node *np, - enum exynos4_soc exynos4_soc) + enum exynos4_soc soc) { - void __iomem *reg_base; + exynos4_soc = soc; reg_base = of_iomap(np, 0); if (!reg_base) panic("%s: failed to map registers\n", __func__); - if (exynos4_soc == EXYNOS4210) - samsung_clk_init(np, reg_base, CLK_NR_CLKS, - exynos4_clk_regs, ARRAY_SIZE(exynos4_clk_regs), - exynos4210_clk_save, ARRAY_SIZE(exynos4210_clk_save)); - else - samsung_clk_init(np, reg_base, CLK_NR_CLKS, - exynos4_clk_regs, ARRAY_SIZE(exynos4_clk_regs), - exynos4x12_clk_save, ARRAY_SIZE(exynos4x12_clk_save)); + samsung_clk_init(np, reg_base, CLK_NR_CLKS, NULL, 0, NULL, 0); samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks, ARRAY_SIZE(exynos4_fixed_rate_ext_clks), @@ -1127,6 +1195,8 @@ static void __init exynos4_clk_init(struct device_node *np, samsung_clk_register_alias(exynos4_aliases, ARRAY_SIZE(exynos4_aliases)); + exynos4_clk_sleep_init(); + pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n" "\tsclk_epll = %ld, sclk_vpll = %ld, arm_clk = %ld\n", exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12", -- cgit v1.2.3 From c3b6c1d7015a5a19d87725fe22b58aeea9a88f3c Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Fri, 14 Feb 2014 08:16:00 +0900 Subject: clk: samsung: exynos5250: Move suspend/resume handling to SoC driver Since there are multiple differences in how suspend/resume of particular Exynos SoCs must be handled, SoC driver is better place for suspend/resume handlers and so this patch moves them. Signed-off-by: Tomasz Figa Acked-by: Kyungmin Park Reviewed-by: Thomas Abraham Reviewed-by: Sylwester Nawrocki Signed-off-by: Kukjin Kim --- drivers/clk/samsung/clk-exynos5250.c | 49 ++++++++++++++++++++++++++++++++---- drivers/clk/samsung/clk.c | 5 ++-- drivers/clk/samsung/clk.h | 4 +-- 3 files changed, 49 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index ff4beebe1f0b..b3cccf044607 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "clk.h" @@ -85,6 +86,11 @@ enum exynos5250_plls { nr_plls /* number of PLLs */ }; +static void __iomem *reg_base; + +#ifdef CONFIG_PM_SLEEP +static struct samsung_clk_reg_dump *exynos5250_save; + /* * list of controller registers to be saved and restored during a * suspend/resume cycle. @@ -137,6 +143,41 @@ static unsigned long exynos5250_clk_regs[] __initdata = { GATE_IP_ACP, }; +static int exynos5250_clk_suspend(void) +{ + samsung_clk_save(reg_base, exynos5250_save, + ARRAY_SIZE(exynos5250_clk_regs)); + + return 0; +} + +static void exynos5250_clk_resume(void) +{ + samsung_clk_restore(reg_base, exynos5250_save, + ARRAY_SIZE(exynos5250_clk_regs)); +} + +static struct syscore_ops exynos5250_clk_syscore_ops = { + .suspend = exynos5250_clk_suspend, + .resume = exynos5250_clk_resume, +}; + +static void exynos5250_clk_sleep_init(void) +{ + exynos5250_save = samsung_clk_alloc_reg_dump(exynos5250_clk_regs, + ARRAY_SIZE(exynos5250_clk_regs)); + if (!exynos5250_save) { + pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", + __func__); + return; + } + + register_syscore_ops(&exynos5250_clk_syscore_ops); +} +#else +static void exynos5250_clk_sleep_init(void) {} +#endif + /* list of all parent clock list */ PNAME(mout_apll_p) = { "fin_pll", "fout_apll", }; PNAME(mout_cpu_p) = { "mout_apll", "mout_mpll", }; @@ -645,8 +686,6 @@ static struct of_device_id ext_clk_match[] __initdata = { /* register exynox5250 clocks */ static void __init exynos5250_clk_init(struct device_node *np) { - void __iomem *reg_base; - if (np) { reg_base = of_iomap(np, 0); if (!reg_base) @@ -655,9 +694,7 @@ static void __init exynos5250_clk_init(struct device_node *np) panic("%s: unable to determine soc\n", __func__); } - samsung_clk_init(np, reg_base, CLK_NR_CLKS, - exynos5250_clk_regs, ARRAY_SIZE(exynos5250_clk_regs), - NULL, 0); + samsung_clk_init(np, reg_base, CLK_NR_CLKS, NULL, 0, NULL, 0); samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks, ARRAY_SIZE(exynos5250_fixed_rate_ext_clks), ext_clk_match); @@ -685,6 +722,8 @@ static void __init exynos5250_clk_init(struct device_node *np) samsung_clk_register_gate(exynos5250_gate_clks, ARRAY_SIZE(exynos5250_gate_clks)); + exynos5250_clk_sleep_init(); + pr_info("Exynos5250: clock setup completed, armclk=%ld\n", _get_rate("div_arm2")); } diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index c0a716b94a66..ec761e344fd0 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -38,8 +38,9 @@ void samsung_clk_restore(void __iomem *base, writel(rd->value, base + rd->offset); } -struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(unsigned long *rdump, - unsigned long nr_rdump) +struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump( + const unsigned long *rdump, + unsigned long nr_rdump) { struct samsung_clk_reg_dump *rd; unsigned int i; diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index ec8d46ba8178..93cb8a0deb7b 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -347,7 +347,7 @@ extern void samsung_clk_restore(void __iomem *base, const struct samsung_clk_reg_dump *rd, unsigned int num_regs); extern struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump( - unsigned long *rdump, - unsigned long nr_rdump); + const unsigned long *rdump, + unsigned long nr_rdump); #endif /* __SAMSUNG_CLK_H */ -- cgit v1.2.3 From 388c78851ee3c1fa6e80e9e06dc3bb9d77fb5f55 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Fri, 14 Feb 2014 08:16:00 +0900 Subject: clk: samsung: exynos5420: Move suspend/resume handling to SoC driver Since there are multiple differences in how suspend/resume of particular Exynos SoCs must be handled, SoC driver is better place for suspend/resume handlers and so this patch moves them. Signed-off-by: Tomasz Figa Acked-by: Kyungmin Park Reviewed-by: Thomas Abraham Reviewed-by: Sylwester Nawrocki Signed-off-by: Kukjin Kim --- drivers/clk/samsung/clk-exynos5420.c | 49 ++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index ab4f2f7d88ef..8ce078049fb4 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "clk.h" @@ -108,6 +109,11 @@ enum exynos5420_plls { nr_plls /* number of PLLs */ }; +static void __iomem *reg_base; + +#ifdef CONFIG_PM_SLEEP +static struct samsung_clk_reg_dump *exynos5420_save; + /* * list of controller registers to be saved and restored during a * suspend/resume cycle. @@ -174,6 +180,41 @@ static unsigned long exynos5420_clk_regs[] __initdata = { DIV_KFC0, }; +static int exynos5420_clk_suspend(void) +{ + samsung_clk_save(reg_base, exynos5420_save, + ARRAY_SIZE(exynos5420_clk_regs)); + + return 0; +} + +static void exynos5420_clk_resume(void) +{ + samsung_clk_restore(reg_base, exynos5420_save, + ARRAY_SIZE(exynos5420_clk_regs)); +} + +static struct syscore_ops exynos5420_clk_syscore_ops = { + .suspend = exynos5420_clk_suspend, + .resume = exynos5420_clk_resume, +}; + +static void exynos5420_clk_sleep_init(void) +{ + exynos5420_save = samsung_clk_alloc_reg_dump(exynos5420_clk_regs, + ARRAY_SIZE(exynos5420_clk_regs)); + if (!exynos5420_save) { + pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", + __func__); + return; + } + + register_syscore_ops(&exynos5420_clk_syscore_ops); +} +#else +static void exynos5420_clk_sleep_init(void) {} +#endif + /* list of all parent clocks */ PNAME(mspll_cpu_p) = { "sclk_cpll", "sclk_dpll", "sclk_mpll", "sclk_spll" }; @@ -737,8 +778,6 @@ static struct of_device_id ext_clk_match[] __initdata = { /* register exynos5420 clocks */ static void __init exynos5420_clk_init(struct device_node *np) { - void __iomem *reg_base; - if (np) { reg_base = of_iomap(np, 0); if (!reg_base) @@ -747,9 +786,7 @@ static void __init exynos5420_clk_init(struct device_node *np) panic("%s: unable to determine soc\n", __func__); } - samsung_clk_init(np, reg_base, CLK_NR_CLKS, - exynos5420_clk_regs, ARRAY_SIZE(exynos5420_clk_regs), - NULL, 0); + samsung_clk_init(np, reg_base, CLK_NR_CLKS, NULL, 0, NULL, 0); samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks, ARRAY_SIZE(exynos5420_fixed_rate_ext_clks), ext_clk_match); @@ -765,5 +802,7 @@ static void __init exynos5420_clk_init(struct device_node *np) ARRAY_SIZE(exynos5420_div_clks)); samsung_clk_register_gate(exynos5420_gate_clks, ARRAY_SIZE(exynos5420_gate_clks)); + + exynos5420_clk_sleep_init(); } CLK_OF_DECLARE(exynos5420_clk, "samsung,exynos5420-clock", exynos5420_clk_init); -- cgit v1.2.3 From 08c0d829d8835061981371f325e9c2b7f887c418 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Fri, 14 Feb 2014 08:16:01 +0900 Subject: clk: samsung: s3c64xx: Move suspend/resume handling to SoC driver Since there are multiple differences in how suspend/resume of particular Exynos SoCs must be handled, SoC driver is better place for suspend/resume handlers and so this patch moves them. Signed-off-by: Tomasz Figa Acked-by: Kyungmin Park Reviewed-by: Thomas Abraham Reviewed-by: Sylwester Nawrocki Signed-off-by: Kukjin Kim --- drivers/clk/samsung/clk-s3c64xx.c | 79 +++++++++++++++++++++++++++++++++------ 1 file changed, 68 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c index 8e27aee6887e..d3fbfa566974 100644 --- a/drivers/clk/samsung/clk-s3c64xx.c +++ b/drivers/clk/samsung/clk-s3c64xx.c @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -61,6 +62,13 @@ enum s3c64xx_plls { apll, mpll, epll, }; +static void __iomem *reg_base; +static bool is_s3c6400; + +#ifdef CONFIG_PM_SLEEP +static struct samsung_clk_reg_dump *s3c64xx_save_common; +static struct samsung_clk_reg_dump *s3c64xx_save_soc; + /* * List of controller registers to be saved and restored during * a suspend/resume cycle. @@ -87,6 +95,60 @@ static unsigned long s3c6410_clk_regs[] __initdata = { MEM0_GATE, }; +static int s3c64xx_clk_suspend(void) +{ + samsung_clk_save(reg_base, s3c64xx_save_common, + ARRAY_SIZE(s3c64xx_clk_regs)); + + if (!is_s3c6400) + samsung_clk_save(reg_base, s3c64xx_save_soc, + ARRAY_SIZE(s3c6410_clk_regs)); + + return 0; +} + +static void s3c64xx_clk_resume(void) +{ + samsung_clk_restore(reg_base, s3c64xx_save_common, + ARRAY_SIZE(s3c64xx_clk_regs)); + + if (!is_s3c6400) + samsung_clk_restore(reg_base, s3c64xx_save_soc, + ARRAY_SIZE(s3c6410_clk_regs)); +} + +static struct syscore_ops s3c64xx_clk_syscore_ops = { + .suspend = s3c64xx_clk_suspend, + .resume = s3c64xx_clk_resume, +}; + +static void s3c64xx_clk_sleep_init(void) +{ + s3c64xx_save_common = samsung_clk_alloc_reg_dump(s3c64xx_clk_regs, + ARRAY_SIZE(s3c64xx_clk_regs)); + if (!s3c64xx_save_common) + goto err_warn; + + if (!is_s3c6400) { + s3c64xx_save_soc = samsung_clk_alloc_reg_dump(s3c6410_clk_regs, + ARRAY_SIZE(s3c6410_clk_regs)); + if (!s3c64xx_save_soc) + goto err_soc; + } + + register_syscore_ops(&s3c64xx_clk_syscore_ops); + return; + +err_soc: + kfree(s3c64xx_save_common); +err_warn: + pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", + __func__); +} +#else +static void s3c64xx_clk_sleep_init(void) {} +#endif + /* List of parent clocks common for all S3C64xx SoCs. */ PNAME(spi_mmc_p) = { "mout_epll", "dout_mpll", "fin_pll", "clk27m" }; PNAME(uart_p) = { "mout_epll", "dout_mpll" }; @@ -391,11 +453,11 @@ static void __init s3c64xx_clk_register_fixed_ext(unsigned long fin_pll_f, /* Register s3c64xx clocks. */ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, - unsigned long xusbxti_f, bool is_s3c6400, - void __iomem *reg_base) + unsigned long xusbxti_f, bool s3c6400, + void __iomem *base) { - unsigned long *soc_regs = NULL; - unsigned long nr_soc_regs = 0; + reg_base = base; + is_s3c6400 = s3c6400; if (np) { reg_base = of_iomap(np, 0); @@ -403,13 +465,7 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, panic("%s: failed to map registers\n", __func__); } - if (!is_s3c6400) { - soc_regs = s3c6410_clk_regs; - nr_soc_regs = ARRAY_SIZE(s3c6410_clk_regs); - } - - samsung_clk_init(np, reg_base, NR_CLKS, s3c64xx_clk_regs, - ARRAY_SIZE(s3c64xx_clk_regs), soc_regs, nr_soc_regs); + samsung_clk_init(np, reg_base, NR_CLKS, NULL, 0, NULL, 0); /* Register external clocks. */ if (!np) @@ -452,6 +508,7 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, samsung_clk_register_alias(s3c64xx_clock_aliases, ARRAY_SIZE(s3c64xx_clock_aliases)); + s3c64xx_clk_sleep_init(); pr_info("%s clocks: apll = %lu, mpll = %lu\n" "\tepll = %lu, arm_clk = %lu\n", -- cgit v1.2.3 From 3efb25116774f69f0649fd6774fd46306cabdb56 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Fri, 14 Feb 2014 08:16:01 +0900 Subject: clk: samsung: Drop old suspend/resume code Since all SoC drivers have been moved to local suspend/resume handling, the old code can be safely dropped. Signed-off-by: Tomasz Figa Acked-by: Kyungmin Park Acked-by: Heiko Stuebner Reviewed-by: Thomas Abraham Reviewed-by: Sylwester Nawrocki Signed-off-by: Kukjin Kim --- drivers/clk/samsung/clk-exynos4.c | 2 +- drivers/clk/samsung/clk-exynos5250.c | 2 +- drivers/clk/samsung/clk-exynos5420.c | 2 +- drivers/clk/samsung/clk-exynos5440.c | 2 +- drivers/clk/samsung/clk-s3c64xx.c | 2 +- drivers/clk/samsung/clk.c | 54 +----------------------------------- drivers/clk/samsung/clk.h | 4 +-- 7 files changed, 7 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 325f29248af5..b620a8375b7f 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -1122,7 +1122,7 @@ static void __init exynos4_clk_init(struct device_node *np, if (!reg_base) panic("%s: failed to map registers\n", __func__); - samsung_clk_init(np, reg_base, CLK_NR_CLKS, NULL, 0, NULL, 0); + samsung_clk_init(np, reg_base, CLK_NR_CLKS); samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks, ARRAY_SIZE(exynos4_fixed_rate_ext_clks), diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index b3cccf044607..e7ee4420da81 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -694,7 +694,7 @@ static void __init exynos5250_clk_init(struct device_node *np) panic("%s: unable to determine soc\n", __func__); } - samsung_clk_init(np, reg_base, CLK_NR_CLKS, NULL, 0, NULL, 0); + samsung_clk_init(np, reg_base, CLK_NR_CLKS); samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks, ARRAY_SIZE(exynos5250_fixed_rate_ext_clks), ext_clk_match); diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 8ce078049fb4..60b26819bed5 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -786,7 +786,7 @@ static void __init exynos5420_clk_init(struct device_node *np) panic("%s: unable to determine soc\n", __func__); } - samsung_clk_init(np, reg_base, CLK_NR_CLKS, NULL, 0, NULL, 0); + samsung_clk_init(np, reg_base, CLK_NR_CLKS); samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks, ARRAY_SIZE(exynos5420_fixed_rate_ext_clks), ext_clk_match); diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c index cbc15b56891d..2bfad5a993d0 100644 --- a/drivers/clk/samsung/clk-exynos5440.c +++ b/drivers/clk/samsung/clk-exynos5440.c @@ -101,7 +101,7 @@ static void __init exynos5440_clk_init(struct device_node *np) return; } - samsung_clk_init(np, reg_base, CLK_NR_CLKS, NULL, 0, NULL, 0); + samsung_clk_init(np, reg_base, CLK_NR_CLKS); samsung_clk_of_register_fixed_ext(exynos5440_fixed_rate_ext_clks, ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match); diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c index d3fbfa566974..8bda658137a8 100644 --- a/drivers/clk/samsung/clk-s3c64xx.c +++ b/drivers/clk/samsung/clk-s3c64xx.c @@ -465,7 +465,7 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, panic("%s: failed to map registers\n", __func__); } - samsung_clk_init(np, reg_base, NR_CLKS, NULL, 0, NULL, 0); + samsung_clk_init(np, reg_base, NR_CLKS); /* Register external clocks. */ if (!np) diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index ec761e344fd0..91bec3ebdc8f 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -21,7 +21,6 @@ static void __iomem *reg_base; static struct clk_onecell_data clk_data; #endif -#ifdef CONFIG_PM_SLEEP void samsung_clk_save(void __iomem *base, struct samsung_clk_reg_dump *rd, unsigned int num_regs) @@ -55,63 +54,12 @@ struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump( return rd; } -static struct samsung_clk_reg_dump *reg_dump; -static unsigned long nr_reg_dump; - -static int samsung_clk_suspend(void) -{ - struct samsung_clk_reg_dump *rd = reg_dump; - unsigned long i; - - for (i = 0; i < nr_reg_dump; i++, rd++) - rd->value = __raw_readl(reg_base + rd->offset); - - return 0; -} - -static void samsung_clk_resume(void) -{ - struct samsung_clk_reg_dump *rd = reg_dump; - unsigned long i; - - for (i = 0; i < nr_reg_dump; i++, rd++) - __raw_writel(rd->value, reg_base + rd->offset); -} - -static struct syscore_ops samsung_clk_syscore_ops = { - .suspend = samsung_clk_suspend, - .resume = samsung_clk_resume, -}; -#endif /* CONFIG_PM_SLEEP */ - /* setup the essentials required to support clock lookup using ccf */ void __init samsung_clk_init(struct device_node *np, void __iomem *base, - unsigned long nr_clks, unsigned long *rdump, - unsigned long nr_rdump, unsigned long *soc_rdump, - unsigned long nr_soc_rdump) + unsigned long nr_clks) { reg_base = base; -#ifdef CONFIG_PM_SLEEP - if (rdump && nr_rdump) { - unsigned int idx; - reg_dump = kzalloc(sizeof(struct samsung_clk_reg_dump) - * (nr_rdump + nr_soc_rdump), GFP_KERNEL); - if (!reg_dump) { - pr_err("%s: memory alloc for register dump failed\n", - __func__); - return; - } - - for (idx = 0; idx < nr_rdump; idx++) - reg_dump[idx].offset = rdump[idx]; - for (idx = 0; idx < nr_soc_rdump; idx++) - reg_dump[nr_rdump + idx].offset = soc_rdump[idx]; - nr_reg_dump = nr_rdump + nr_soc_rdump; - register_syscore_ops(&samsung_clk_syscore_ops); - } -#endif - clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL); if (!clk_table) panic("could not allocate clock lookup table\n"); diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index 93cb8a0deb7b..c7141ba826e0 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -313,9 +313,7 @@ struct samsung_pll_clock { _lock, _con, _rtable, _alias) extern void __init samsung_clk_init(struct device_node *np, void __iomem *base, - unsigned long nr_clks, unsigned long *rdump, - unsigned long nr_rdump, unsigned long *soc_rdump, - unsigned long nr_soc_rdump); + unsigned long nr_clks); extern void __init samsung_clk_of_register_fixed_ext( struct samsung_fixed_rate_clock *fixed_rate_clk, unsigned int nr_fixed_rate_clk, -- cgit v1.2.3 From 4fcf47e2db145f72b31b344fda64a8a6dacd8d1d Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Fri, 14 Feb 2014 08:16:01 +0900 Subject: 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 Acked-by: Kyungmin Park Reviewed-by: Thomas Abraham Reviewed-by: Sylwester Nawrocki Signed-off-by: Kukjin Kim --- drivers/clk/samsung/clk-exynos4.c | 76 ++++++++++++++++++++++++++++++++++----- 1 file changed, 68 insertions(+), 8 deletions(-) (limited to 'drivers') 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; #ifdef CONFIG_PM_SLEEP static struct samsung_clk_reg_dump *exynos4_save_common; static struct samsung_clk_reg_dump *exynos4_save_soc; +static struct samsung_clk_reg_dump *exynos4_save_pll; /* * list of controller registers to be saved and restored during a @@ -165,6 +166,17 @@ static unsigned long exynos4x12_clk_save[] __initdata = { E4X12_MPLL_CON0, }; +static unsigned long exynos4_clk_pll_regs[] __initdata = { + EPLL_LOCK, + VPLL_LOCK, + EPLL_CON0, + EPLL_CON1, + EPLL_CON2, + VPLL_CON0, + VPLL_CON1, + VPLL_CON2, +}; + static unsigned long exynos4_clk_regs[] __initdata = { SRC_LEFTBUS, DIV_LEFTBUS, @@ -172,12 +184,6 @@ static unsigned long exynos4_clk_regs[] __initdata = { SRC_RIGHTBUS, DIV_RIGHTBUS, GATE_IP_RIGHTBUS, - EPLL_CON0, - EPLL_CON1, - EPLL_CON2, - VPLL_CON0, - VPLL_CON1, - VPLL_CON2, SRC_TOP0, SRC_TOP1, SRC_CAM, @@ -238,23 +244,70 @@ static unsigned long exynos4_clk_regs[] __initdata = { GATE_IP_CPU, }; +static const struct samsung_clk_reg_dump src_mask_suspend[] = { + { .offset = SRC_MASK_TOP, .value = 0x00000001, }, + { .offset = SRC_MASK_CAM, .value = 0x11111111, }, + { .offset = SRC_MASK_TV, .value = 0x00000111, }, + { .offset = SRC_MASK_LCD0, .value = 0x00001111, }, + { .offset = SRC_MASK_MAUDIO, .value = 0x00000001, }, + { .offset = SRC_MASK_FSYS, .value = 0x01011111, }, + { .offset = SRC_MASK_PERIL0, .value = 0x01111111, }, + { .offset = SRC_MASK_PERIL1, .value = 0x01110111, }, + { .offset = SRC_MASK_DMC, .value = 0x00010000, }, +}; + +static const struct samsung_clk_reg_dump src_mask_suspend_e4210[] = { + { .offset = E4210_SRC_MASK_LCD1, .value = 0x00001111, }, +}; + +#define PLL_ENABLED (1 << 31) +#define PLL_LOCKED (1 << 29) + +static void exynos4_clk_wait_for_pll(u32 reg) +{ + u32 pll_con; + + pll_con = readl(reg_base + reg); + if (!(pll_con & PLL_ENABLED)) + return; + + while (!(pll_con & PLL_LOCKED)) { + cpu_relax(); + pll_con = readl(reg_base + reg); + } +} + static int exynos4_clk_suspend(void) { samsung_clk_save(reg_base, exynos4_save_common, ARRAY_SIZE(exynos4_clk_regs)); + samsung_clk_save(reg_base, exynos4_save_pll, + ARRAY_SIZE(exynos4_clk_pll_regs)); - if (exynos4_soc == EXYNOS4210) + if (exynos4_soc == EXYNOS4210) { samsung_clk_save(reg_base, exynos4_save_soc, ARRAY_SIZE(exynos4210_clk_save)); - else + samsung_clk_restore(reg_base, src_mask_suspend_e4210, + ARRAY_SIZE(src_mask_suspend_e4210)); + } else { samsung_clk_save(reg_base, exynos4_save_soc, ARRAY_SIZE(exynos4x12_clk_save)); + } + + samsung_clk_restore(reg_base, src_mask_suspend, + ARRAY_SIZE(src_mask_suspend)); return 0; } static void exynos4_clk_resume(void) { + samsung_clk_restore(reg_base, exynos4_save_pll, + ARRAY_SIZE(exynos4_clk_pll_regs)); + + exynos4_clk_wait_for_pll(EPLL_CON0); + exynos4_clk_wait_for_pll(VPLL_CON0); + samsung_clk_restore(reg_base, exynos4_save_common, ARRAY_SIZE(exynos4_clk_regs)); @@ -289,9 +342,16 @@ static void exynos4_clk_sleep_init(void) if (!exynos4_save_soc) goto err_common; + exynos4_save_pll = samsung_clk_alloc_reg_dump(exynos4_clk_pll_regs, + ARRAY_SIZE(exynos4_clk_pll_regs)); + if (!exynos4_save_pll) + goto err_soc; + register_syscore_ops(&exynos4_clk_syscore_ops); return; +err_soc: + kfree(exynos4_save_soc); err_common: kfree(exynos4_save_common); err_warn: -- cgit v1.2.3