diff options
-rw-r--r-- | drivers/clk/samsung/clk-exynos5260.c | 185 | ||||
-rw-r--r-- | drivers/clk/samsung/clk.c | 95 | ||||
-rw-r--r-- | drivers/clk/samsung/clk.h | 34 |
3 files changed, 155 insertions, 159 deletions
diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c index 2527e39aadcf..e2e5193d1049 100644 --- a/drivers/clk/samsung/clk-exynos5260.c +++ b/drivers/clk/samsung/clk-exynos5260.c | |||
@@ -11,10 +11,8 @@ | |||
11 | 11 | ||
12 | #include <linux/clk.h> | 12 | #include <linux/clk.h> |
13 | #include <linux/clkdev.h> | 13 | #include <linux/clkdev.h> |
14 | #include <linux/clk-provider.h> | ||
15 | #include <linux/of.h> | 14 | #include <linux/of.h> |
16 | #include <linux/of_address.h> | 15 | #include <linux/of_address.h> |
17 | #include <linux/syscore_ops.h> | ||
18 | 16 | ||
19 | #include "clk-exynos5260.h" | 17 | #include "clk-exynos5260.h" |
20 | #include "clk.h" | 18 | #include "clk.h" |
@@ -22,39 +20,6 @@ | |||
22 | 20 | ||
23 | #include <dt-bindings/clock/exynos5260-clk.h> | 21 | #include <dt-bindings/clock/exynos5260-clk.h> |
24 | 22 | ||
25 | static LIST_HEAD(clock_reg_cache_list); | ||
26 | |||
27 | struct exynos5260_clock_reg_cache { | ||
28 | struct list_head node; | ||
29 | void __iomem *reg_base; | ||
30 | struct samsung_clk_reg_dump *rdump; | ||
31 | unsigned int rd_num; | ||
32 | }; | ||
33 | |||
34 | struct exynos5260_cmu_info { | ||
35 | /* list of pll clocks and respective count */ | ||
36 | struct samsung_pll_clock *pll_clks; | ||
37 | unsigned int nr_pll_clks; | ||
38 | /* list of mux clocks and respective count */ | ||
39 | struct samsung_mux_clock *mux_clks; | ||
40 | unsigned int nr_mux_clks; | ||
41 | /* list of div clocks and respective count */ | ||
42 | struct samsung_div_clock *div_clks; | ||
43 | unsigned int nr_div_clks; | ||
44 | /* list of gate clocks and respective count */ | ||
45 | struct samsung_gate_clock *gate_clks; | ||
46 | unsigned int nr_gate_clks; | ||
47 | /* list of fixed clocks and respective count */ | ||
48 | struct samsung_fixed_rate_clock *fixed_clks; | ||
49 | unsigned int nr_fixed_clks; | ||
50 | /* total number of clocks with IDs assigned*/ | ||
51 | unsigned int nr_clk_ids; | ||
52 | |||
53 | /* list and number of clocks registers */ | ||
54 | unsigned long *clk_regs; | ||
55 | unsigned int nr_clk_regs; | ||
56 | }; | ||
57 | |||
58 | /* | 23 | /* |
59 | * Applicable for all 2550 Type PLLS for Exynos5260, listed below | 24 | * Applicable for all 2550 Type PLLS for Exynos5260, listed below |
60 | * DISP_PLL, EGL_PLL, KFC_PLL, MEM_PLL, BUS_PLL, MEDIA_PLL, G3D_PLL. | 25 | * DISP_PLL, EGL_PLL, KFC_PLL, MEM_PLL, BUS_PLL, MEDIA_PLL, G3D_PLL. |
@@ -113,104 +78,6 @@ static struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initdata = { | |||
113 | PLL_36XX_RATE(66000000, 176, 2, 5, 0), | 78 | PLL_36XX_RATE(66000000, 176, 2, 5, 0), |
114 | }; | 79 | }; |
115 | 80 | ||
116 | #ifdef CONFIG_PM_SLEEP | ||
117 | |||
118 | static int exynos5260_clk_suspend(void) | ||
119 | { | ||
120 | struct exynos5260_clock_reg_cache *cache; | ||
121 | |||
122 | list_for_each_entry(cache, &clock_reg_cache_list, node) | ||
123 | samsung_clk_save(cache->reg_base, cache->rdump, | ||
124 | cache->rd_num); | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static void exynos5260_clk_resume(void) | ||
130 | { | ||
131 | struct exynos5260_clock_reg_cache *cache; | ||
132 | |||
133 | list_for_each_entry(cache, &clock_reg_cache_list, node) | ||
134 | samsung_clk_restore(cache->reg_base, cache->rdump, | ||
135 | cache->rd_num); | ||
136 | } | ||
137 | |||
138 | static struct syscore_ops exynos5260_clk_syscore_ops = { | ||
139 | .suspend = exynos5260_clk_suspend, | ||
140 | .resume = exynos5260_clk_resume, | ||
141 | }; | ||
142 | |||
143 | static void exynos5260_clk_sleep_init(void __iomem *reg_base, | ||
144 | unsigned long *rdump, | ||
145 | unsigned long nr_rdump) | ||
146 | { | ||
147 | struct exynos5260_clock_reg_cache *reg_cache; | ||
148 | |||
149 | reg_cache = kzalloc(sizeof(struct exynos5260_clock_reg_cache), | ||
150 | GFP_KERNEL); | ||
151 | if (!reg_cache) | ||
152 | panic("could not allocate register cache.\n"); | ||
153 | |||
154 | reg_cache->rdump = samsung_clk_alloc_reg_dump(rdump, nr_rdump); | ||
155 | |||
156 | if (!reg_cache->rdump) | ||
157 | panic("could not allocate register dump storage.\n"); | ||
158 | |||
159 | if (list_empty(&clock_reg_cache_list)) | ||
160 | register_syscore_ops(&exynos5260_clk_syscore_ops); | ||
161 | |||
162 | reg_cache->rd_num = nr_rdump; | ||
163 | reg_cache->reg_base = reg_base; | ||
164 | list_add_tail(®_cache->node, &clock_reg_cache_list); | ||
165 | } | ||
166 | |||
167 | #else | ||
168 | static void exynos5260_clk_sleep_init(void __iomem *reg_base, | ||
169 | unsigned long *rdump, | ||
170 | unsigned long nr_rdump){} | ||
171 | #endif | ||
172 | |||
173 | /* | ||
174 | * Common function which registers plls, muxes, dividers and gates | ||
175 | * for each CMU. It also add CMU register list to register cache. | ||
176 | */ | ||
177 | |||
178 | void __init exynos5260_cmu_register_one(struct device_node *np, | ||
179 | struct exynos5260_cmu_info *cmu) | ||
180 | { | ||
181 | void __iomem *reg_base; | ||
182 | struct samsung_clk_provider *ctx; | ||
183 | |||
184 | reg_base = of_iomap(np, 0); | ||
185 | if (!reg_base) | ||
186 | panic("%s: failed to map registers\n", __func__); | ||
187 | |||
188 | ctx = samsung_clk_init(np, reg_base, cmu->nr_clk_ids); | ||
189 | if (!ctx) | ||
190 | panic("%s: unable to alllocate ctx\n", __func__); | ||
191 | |||
192 | if (cmu->pll_clks) | ||
193 | samsung_clk_register_pll(ctx, cmu->pll_clks, cmu->nr_pll_clks, | ||
194 | reg_base); | ||
195 | if (cmu->mux_clks) | ||
196 | samsung_clk_register_mux(ctx, cmu->mux_clks, | ||
197 | cmu->nr_mux_clks); | ||
198 | if (cmu->div_clks) | ||
199 | samsung_clk_register_div(ctx, cmu->div_clks, cmu->nr_div_clks); | ||
200 | if (cmu->gate_clks) | ||
201 | samsung_clk_register_gate(ctx, cmu->gate_clks, | ||
202 | cmu->nr_gate_clks); | ||
203 | if (cmu->fixed_clks) | ||
204 | samsung_clk_register_fixed_rate(ctx, cmu->fixed_clks, | ||
205 | cmu->nr_fixed_clks); | ||
206 | if (cmu->clk_regs) | ||
207 | exynos5260_clk_sleep_init(reg_base, cmu->clk_regs, | ||
208 | cmu->nr_clk_regs); | ||
209 | |||
210 | samsung_clk_of_add_provider(np, ctx); | ||
211 | } | ||
212 | |||
213 | |||
214 | /* CMU_AUD */ | 81 | /* CMU_AUD */ |
215 | 82 | ||
216 | static unsigned long aud_clk_regs[] __initdata = { | 83 | static unsigned long aud_clk_regs[] __initdata = { |
@@ -268,7 +135,7 @@ struct samsung_gate_clock aud_gate_clks[] __initdata = { | |||
268 | 135 | ||
269 | static void __init exynos5260_clk_aud_init(struct device_node *np) | 136 | static void __init exynos5260_clk_aud_init(struct device_node *np) |
270 | { | 137 | { |
271 | struct exynos5260_cmu_info cmu = {0}; | 138 | struct samsung_cmu_info cmu = {0}; |
272 | 139 | ||
273 | cmu.mux_clks = aud_mux_clks; | 140 | cmu.mux_clks = aud_mux_clks; |
274 | cmu.nr_mux_clks = ARRAY_SIZE(aud_mux_clks); | 141 | cmu.nr_mux_clks = ARRAY_SIZE(aud_mux_clks); |
@@ -280,7 +147,7 @@ static void __init exynos5260_clk_aud_init(struct device_node *np) | |||
280 | cmu.clk_regs = aud_clk_regs; | 147 | cmu.clk_regs = aud_clk_regs; |
281 | cmu.nr_clk_regs = ARRAY_SIZE(aud_clk_regs); | 148 | cmu.nr_clk_regs = ARRAY_SIZE(aud_clk_regs); |
282 | 149 | ||
283 | exynos5260_cmu_register_one(np, &cmu); | 150 | samsung_cmu_register_one(np, &cmu); |
284 | } | 151 | } |
285 | 152 | ||
286 | CLK_OF_DECLARE(exynos5260_clk_aud, "samsung,exynos5260-clock-aud", | 153 | CLK_OF_DECLARE(exynos5260_clk_aud, "samsung,exynos5260-clock-aud", |
@@ -458,7 +325,7 @@ struct samsung_gate_clock disp_gate_clks[] __initdata = { | |||
458 | 325 | ||
459 | static void __init exynos5260_clk_disp_init(struct device_node *np) | 326 | static void __init exynos5260_clk_disp_init(struct device_node *np) |
460 | { | 327 | { |
461 | struct exynos5260_cmu_info cmu = {0}; | 328 | struct samsung_cmu_info cmu = {0}; |
462 | 329 | ||
463 | cmu.mux_clks = disp_mux_clks; | 330 | cmu.mux_clks = disp_mux_clks; |
464 | cmu.nr_mux_clks = ARRAY_SIZE(disp_mux_clks); | 331 | cmu.nr_mux_clks = ARRAY_SIZE(disp_mux_clks); |
@@ -470,7 +337,7 @@ static void __init exynos5260_clk_disp_init(struct device_node *np) | |||
470 | cmu.clk_regs = disp_clk_regs; | 337 | cmu.clk_regs = disp_clk_regs; |
471 | cmu.nr_clk_regs = ARRAY_SIZE(disp_clk_regs); | 338 | cmu.nr_clk_regs = ARRAY_SIZE(disp_clk_regs); |
472 | 339 | ||
473 | exynos5260_cmu_register_one(np, &cmu); | 340 | samsung_cmu_register_one(np, &cmu); |
474 | } | 341 | } |
475 | 342 | ||
476 | CLK_OF_DECLARE(exynos5260_clk_disp, "samsung,exynos5260-clock-disp", | 343 | CLK_OF_DECLARE(exynos5260_clk_disp, "samsung,exynos5260-clock-disp", |
@@ -522,7 +389,7 @@ static struct samsung_pll_clock egl_pll_clks[] __initdata = { | |||
522 | 389 | ||
523 | static void __init exynos5260_clk_egl_init(struct device_node *np) | 390 | static void __init exynos5260_clk_egl_init(struct device_node *np) |
524 | { | 391 | { |
525 | struct exynos5260_cmu_info cmu = {0}; | 392 | struct samsung_cmu_info cmu = {0}; |
526 | 393 | ||
527 | cmu.pll_clks = egl_pll_clks; | 394 | cmu.pll_clks = egl_pll_clks; |
528 | cmu.nr_pll_clks = ARRAY_SIZE(egl_pll_clks); | 395 | cmu.nr_pll_clks = ARRAY_SIZE(egl_pll_clks); |
@@ -534,7 +401,7 @@ static void __init exynos5260_clk_egl_init(struct device_node *np) | |||
534 | cmu.clk_regs = egl_clk_regs; | 401 | cmu.clk_regs = egl_clk_regs; |
535 | cmu.nr_clk_regs = ARRAY_SIZE(egl_clk_regs); | 402 | cmu.nr_clk_regs = ARRAY_SIZE(egl_clk_regs); |
536 | 403 | ||
537 | exynos5260_cmu_register_one(np, &cmu); | 404 | samsung_cmu_register_one(np, &cmu); |
538 | } | 405 | } |
539 | 406 | ||
540 | CLK_OF_DECLARE(exynos5260_clk_egl, "samsung,exynos5260-clock-egl", | 407 | CLK_OF_DECLARE(exynos5260_clk_egl, "samsung,exynos5260-clock-egl", |
@@ -624,7 +491,7 @@ struct samsung_gate_clock fsys_gate_clks[] __initdata = { | |||
624 | 491 | ||
625 | static void __init exynos5260_clk_fsys_init(struct device_node *np) | 492 | static void __init exynos5260_clk_fsys_init(struct device_node *np) |
626 | { | 493 | { |
627 | struct exynos5260_cmu_info cmu = {0}; | 494 | struct samsung_cmu_info cmu = {0}; |
628 | 495 | ||
629 | cmu.mux_clks = fsys_mux_clks; | 496 | cmu.mux_clks = fsys_mux_clks; |
630 | cmu.nr_mux_clks = ARRAY_SIZE(fsys_mux_clks); | 497 | cmu.nr_mux_clks = ARRAY_SIZE(fsys_mux_clks); |
@@ -634,7 +501,7 @@ static void __init exynos5260_clk_fsys_init(struct device_node *np) | |||
634 | cmu.clk_regs = fsys_clk_regs; | 501 | cmu.clk_regs = fsys_clk_regs; |
635 | cmu.nr_clk_regs = ARRAY_SIZE(fsys_clk_regs); | 502 | cmu.nr_clk_regs = ARRAY_SIZE(fsys_clk_regs); |
636 | 503 | ||
637 | exynos5260_cmu_register_one(np, &cmu); | 504 | samsung_cmu_register_one(np, &cmu); |
638 | } | 505 | } |
639 | 506 | ||
640 | CLK_OF_DECLARE(exynos5260_clk_fsys, "samsung,exynos5260-clock-fsys", | 507 | CLK_OF_DECLARE(exynos5260_clk_fsys, "samsung,exynos5260-clock-fsys", |
@@ -713,7 +580,7 @@ struct samsung_gate_clock g2d_gate_clks[] __initdata = { | |||
713 | 580 | ||
714 | static void __init exynos5260_clk_g2d_init(struct device_node *np) | 581 | static void __init exynos5260_clk_g2d_init(struct device_node *np) |
715 | { | 582 | { |
716 | struct exynos5260_cmu_info cmu = {0}; | 583 | struct samsung_cmu_info cmu = {0}; |
717 | 584 | ||
718 | cmu.mux_clks = g2d_mux_clks; | 585 | cmu.mux_clks = g2d_mux_clks; |
719 | cmu.nr_mux_clks = ARRAY_SIZE(g2d_mux_clks); | 586 | cmu.nr_mux_clks = ARRAY_SIZE(g2d_mux_clks); |
@@ -725,7 +592,7 @@ static void __init exynos5260_clk_g2d_init(struct device_node *np) | |||
725 | cmu.clk_regs = g2d_clk_regs; | 592 | cmu.clk_regs = g2d_clk_regs; |
726 | cmu.nr_clk_regs = ARRAY_SIZE(g2d_clk_regs); | 593 | cmu.nr_clk_regs = ARRAY_SIZE(g2d_clk_regs); |
727 | 594 | ||
728 | exynos5260_cmu_register_one(np, &cmu); | 595 | samsung_cmu_register_one(np, &cmu); |
729 | } | 596 | } |
730 | 597 | ||
731 | CLK_OF_DECLARE(exynos5260_clk_g2d, "samsung,exynos5260-clock-g2d", | 598 | CLK_OF_DECLARE(exynos5260_clk_g2d, "samsung,exynos5260-clock-g2d", |
@@ -774,7 +641,7 @@ static struct samsung_pll_clock g3d_pll_clks[] __initdata = { | |||
774 | 641 | ||
775 | static void __init exynos5260_clk_g3d_init(struct device_node *np) | 642 | static void __init exynos5260_clk_g3d_init(struct device_node *np) |
776 | { | 643 | { |
777 | struct exynos5260_cmu_info cmu = {0}; | 644 | struct samsung_cmu_info cmu = {0}; |
778 | 645 | ||
779 | cmu.pll_clks = g3d_pll_clks; | 646 | cmu.pll_clks = g3d_pll_clks; |
780 | cmu.nr_pll_clks = ARRAY_SIZE(g3d_pll_clks); | 647 | cmu.nr_pll_clks = ARRAY_SIZE(g3d_pll_clks); |
@@ -788,7 +655,7 @@ static void __init exynos5260_clk_g3d_init(struct device_node *np) | |||
788 | cmu.clk_regs = g3d_clk_regs; | 655 | cmu.clk_regs = g3d_clk_regs; |
789 | cmu.nr_clk_regs = ARRAY_SIZE(g3d_clk_regs); | 656 | cmu.nr_clk_regs = ARRAY_SIZE(g3d_clk_regs); |
790 | 657 | ||
791 | exynos5260_cmu_register_one(np, &cmu); | 658 | samsung_cmu_register_one(np, &cmu); |
792 | } | 659 | } |
793 | 660 | ||
794 | CLK_OF_DECLARE(exynos5260_clk_g3d, "samsung,exynos5260-clock-g3d", | 661 | CLK_OF_DECLARE(exynos5260_clk_g3d, "samsung,exynos5260-clock-g3d", |
@@ -909,7 +776,7 @@ struct samsung_gate_clock gscl_gate_clks[] __initdata = { | |||
909 | 776 | ||
910 | static void __init exynos5260_clk_gscl_init(struct device_node *np) | 777 | static void __init exynos5260_clk_gscl_init(struct device_node *np) |
911 | { | 778 | { |
912 | struct exynos5260_cmu_info cmu = {0}; | 779 | struct samsung_cmu_info cmu = {0}; |
913 | 780 | ||
914 | cmu.mux_clks = gscl_mux_clks; | 781 | cmu.mux_clks = gscl_mux_clks; |
915 | cmu.nr_mux_clks = ARRAY_SIZE(gscl_mux_clks); | 782 | cmu.nr_mux_clks = ARRAY_SIZE(gscl_mux_clks); |
@@ -921,7 +788,7 @@ static void __init exynos5260_clk_gscl_init(struct device_node *np) | |||
921 | cmu.clk_regs = gscl_clk_regs; | 788 | cmu.clk_regs = gscl_clk_regs; |
922 | cmu.nr_clk_regs = ARRAY_SIZE(gscl_clk_regs); | 789 | cmu.nr_clk_regs = ARRAY_SIZE(gscl_clk_regs); |
923 | 790 | ||
924 | exynos5260_cmu_register_one(np, &cmu); | 791 | samsung_cmu_register_one(np, &cmu); |
925 | } | 792 | } |
926 | 793 | ||
927 | CLK_OF_DECLARE(exynos5260_clk_gscl, "samsung,exynos5260-clock-gscl", | 794 | CLK_OF_DECLARE(exynos5260_clk_gscl, "samsung,exynos5260-clock-gscl", |
@@ -1028,7 +895,7 @@ struct samsung_gate_clock isp_gate_clks[] __initdata = { | |||
1028 | 895 | ||
1029 | static void __init exynos5260_clk_isp_init(struct device_node *np) | 896 | static void __init exynos5260_clk_isp_init(struct device_node *np) |
1030 | { | 897 | { |
1031 | struct exynos5260_cmu_info cmu = {0}; | 898 | struct samsung_cmu_info cmu = {0}; |
1032 | 899 | ||
1033 | cmu.mux_clks = isp_mux_clks; | 900 | cmu.mux_clks = isp_mux_clks; |
1034 | cmu.nr_mux_clks = ARRAY_SIZE(isp_mux_clks); | 901 | cmu.nr_mux_clks = ARRAY_SIZE(isp_mux_clks); |
@@ -1040,7 +907,7 @@ static void __init exynos5260_clk_isp_init(struct device_node *np) | |||
1040 | cmu.clk_regs = isp_clk_regs; | 907 | cmu.clk_regs = isp_clk_regs; |
1041 | cmu.nr_clk_regs = ARRAY_SIZE(isp_clk_regs); | 908 | cmu.nr_clk_regs = ARRAY_SIZE(isp_clk_regs); |
1042 | 909 | ||
1043 | exynos5260_cmu_register_one(np, &cmu); | 910 | samsung_cmu_register_one(np, &cmu); |
1044 | } | 911 | } |
1045 | 912 | ||
1046 | CLK_OF_DECLARE(exynos5260_clk_isp, "samsung,exynos5260-clock-isp", | 913 | CLK_OF_DECLARE(exynos5260_clk_isp, "samsung,exynos5260-clock-isp", |
@@ -1092,7 +959,7 @@ static struct samsung_pll_clock kfc_pll_clks[] __initdata = { | |||
1092 | 959 | ||
1093 | static void __init exynos5260_clk_kfc_init(struct device_node *np) | 960 | static void __init exynos5260_clk_kfc_init(struct device_node *np) |
1094 | { | 961 | { |
1095 | struct exynos5260_cmu_info cmu = {0}; | 962 | struct samsung_cmu_info cmu = {0}; |
1096 | 963 | ||
1097 | cmu.pll_clks = kfc_pll_clks; | 964 | cmu.pll_clks = kfc_pll_clks; |
1098 | cmu.nr_pll_clks = ARRAY_SIZE(kfc_pll_clks); | 965 | cmu.nr_pll_clks = ARRAY_SIZE(kfc_pll_clks); |
@@ -1104,7 +971,7 @@ static void __init exynos5260_clk_kfc_init(struct device_node *np) | |||
1104 | cmu.clk_regs = kfc_clk_regs; | 971 | cmu.clk_regs = kfc_clk_regs; |
1105 | cmu.nr_clk_regs = ARRAY_SIZE(kfc_clk_regs); | 972 | cmu.nr_clk_regs = ARRAY_SIZE(kfc_clk_regs); |
1106 | 973 | ||
1107 | exynos5260_cmu_register_one(np, &cmu); | 974 | samsung_cmu_register_one(np, &cmu); |
1108 | } | 975 | } |
1109 | 976 | ||
1110 | CLK_OF_DECLARE(exynos5260_clk_kfc, "samsung,exynos5260-clock-kfc", | 977 | CLK_OF_DECLARE(exynos5260_clk_kfc, "samsung,exynos5260-clock-kfc", |
@@ -1148,7 +1015,7 @@ struct samsung_gate_clock mfc_gate_clks[] __initdata = { | |||
1148 | 1015 | ||
1149 | static void __init exynos5260_clk_mfc_init(struct device_node *np) | 1016 | static void __init exynos5260_clk_mfc_init(struct device_node *np) |
1150 | { | 1017 | { |
1151 | struct exynos5260_cmu_info cmu = {0}; | 1018 | struct samsung_cmu_info cmu = {0}; |
1152 | 1019 | ||
1153 | cmu.mux_clks = mfc_mux_clks; | 1020 | cmu.mux_clks = mfc_mux_clks; |
1154 | cmu.nr_mux_clks = ARRAY_SIZE(mfc_mux_clks); | 1021 | cmu.nr_mux_clks = ARRAY_SIZE(mfc_mux_clks); |
@@ -1160,7 +1027,7 @@ static void __init exynos5260_clk_mfc_init(struct device_node *np) | |||
1160 | cmu.clk_regs = mfc_clk_regs; | 1027 | cmu.clk_regs = mfc_clk_regs; |
1161 | cmu.nr_clk_regs = ARRAY_SIZE(mfc_clk_regs); | 1028 | cmu.nr_clk_regs = ARRAY_SIZE(mfc_clk_regs); |
1162 | 1029 | ||
1163 | exynos5260_cmu_register_one(np, &cmu); | 1030 | samsung_cmu_register_one(np, &cmu); |
1164 | } | 1031 | } |
1165 | 1032 | ||
1166 | CLK_OF_DECLARE(exynos5260_clk_mfc, "samsung,exynos5260-clock-mfc", | 1033 | CLK_OF_DECLARE(exynos5260_clk_mfc, "samsung,exynos5260-clock-mfc", |
@@ -1295,7 +1162,7 @@ static struct samsung_pll_clock mif_pll_clks[] __initdata = { | |||
1295 | 1162 | ||
1296 | static void __init exynos5260_clk_mif_init(struct device_node *np) | 1163 | static void __init exynos5260_clk_mif_init(struct device_node *np) |
1297 | { | 1164 | { |
1298 | struct exynos5260_cmu_info cmu = {0}; | 1165 | struct samsung_cmu_info cmu = {0}; |
1299 | 1166 | ||
1300 | cmu.pll_clks = mif_pll_clks; | 1167 | cmu.pll_clks = mif_pll_clks; |
1301 | cmu.nr_pll_clks = ARRAY_SIZE(mif_pll_clks); | 1168 | cmu.nr_pll_clks = ARRAY_SIZE(mif_pll_clks); |
@@ -1309,7 +1176,7 @@ static void __init exynos5260_clk_mif_init(struct device_node *np) | |||
1309 | cmu.clk_regs = mif_clk_regs; | 1176 | cmu.clk_regs = mif_clk_regs; |
1310 | cmu.nr_clk_regs = ARRAY_SIZE(mif_clk_regs); | 1177 | cmu.nr_clk_regs = ARRAY_SIZE(mif_clk_regs); |
1311 | 1178 | ||
1312 | exynos5260_cmu_register_one(np, &cmu); | 1179 | samsung_cmu_register_one(np, &cmu); |
1313 | } | 1180 | } |
1314 | 1181 | ||
1315 | CLK_OF_DECLARE(exynos5260_clk_mif, "samsung,exynos5260-clock-mif", | 1182 | CLK_OF_DECLARE(exynos5260_clk_mif, "samsung,exynos5260-clock-mif", |
@@ -1503,7 +1370,7 @@ struct samsung_gate_clock peri_gate_clks[] __initdata = { | |||
1503 | 1370 | ||
1504 | static void __init exynos5260_clk_peri_init(struct device_node *np) | 1371 | static void __init exynos5260_clk_peri_init(struct device_node *np) |
1505 | { | 1372 | { |
1506 | struct exynos5260_cmu_info cmu = {0}; | 1373 | struct samsung_cmu_info cmu = {0}; |
1507 | 1374 | ||
1508 | cmu.mux_clks = peri_mux_clks; | 1375 | cmu.mux_clks = peri_mux_clks; |
1509 | cmu.nr_mux_clks = ARRAY_SIZE(peri_mux_clks); | 1376 | cmu.nr_mux_clks = ARRAY_SIZE(peri_mux_clks); |
@@ -1515,7 +1382,7 @@ static void __init exynos5260_clk_peri_init(struct device_node *np) | |||
1515 | cmu.clk_regs = peri_clk_regs; | 1382 | cmu.clk_regs = peri_clk_regs; |
1516 | cmu.nr_clk_regs = ARRAY_SIZE(peri_clk_regs); | 1383 | cmu.nr_clk_regs = ARRAY_SIZE(peri_clk_regs); |
1517 | 1384 | ||
1518 | exynos5260_cmu_register_one(np, &cmu); | 1385 | samsung_cmu_register_one(np, &cmu); |
1519 | } | 1386 | } |
1520 | 1387 | ||
1521 | CLK_OF_DECLARE(exynos5260_clk_peri, "samsung,exynos5260-clock-peri", | 1388 | CLK_OF_DECLARE(exynos5260_clk_peri, "samsung,exynos5260-clock-peri", |
@@ -1959,7 +1826,7 @@ static struct samsung_pll_clock top_pll_clks[] __initdata = { | |||
1959 | 1826 | ||
1960 | static void __init exynos5260_clk_top_init(struct device_node *np) | 1827 | static void __init exynos5260_clk_top_init(struct device_node *np) |
1961 | { | 1828 | { |
1962 | struct exynos5260_cmu_info cmu = {0}; | 1829 | struct samsung_cmu_info cmu = {0}; |
1963 | 1830 | ||
1964 | cmu.pll_clks = top_pll_clks; | 1831 | cmu.pll_clks = top_pll_clks; |
1965 | cmu.nr_pll_clks = ARRAY_SIZE(top_pll_clks); | 1832 | cmu.nr_pll_clks = ARRAY_SIZE(top_pll_clks); |
@@ -1975,7 +1842,7 @@ static void __init exynos5260_clk_top_init(struct device_node *np) | |||
1975 | cmu.clk_regs = top_clk_regs; | 1842 | cmu.clk_regs = top_clk_regs; |
1976 | cmu.nr_clk_regs = ARRAY_SIZE(top_clk_regs); | 1843 | cmu.nr_clk_regs = ARRAY_SIZE(top_clk_regs); |
1977 | 1844 | ||
1978 | exynos5260_cmu_register_one(np, &cmu); | 1845 | samsung_cmu_register_one(np, &cmu); |
1979 | } | 1846 | } |
1980 | 1847 | ||
1981 | CLK_OF_DECLARE(exynos5260_clk_top, "samsung,exynos5260-clock-top", | 1848 | CLK_OF_DECLARE(exynos5260_clk_top, "samsung,exynos5260-clock-top", |
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index deab84d9f37d..a64823627d3a 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c | |||
@@ -14,6 +14,8 @@ | |||
14 | #include <linux/syscore_ops.h> | 14 | #include <linux/syscore_ops.h> |
15 | #include "clk.h" | 15 | #include "clk.h" |
16 | 16 | ||
17 | static LIST_HEAD(clock_reg_cache_list); | ||
18 | |||
17 | void samsung_clk_save(void __iomem *base, | 19 | void samsung_clk_save(void __iomem *base, |
18 | struct samsung_clk_reg_dump *rd, | 20 | struct samsung_clk_reg_dump *rd, |
19 | unsigned int num_regs) | 21 | unsigned int num_regs) |
@@ -313,3 +315,96 @@ unsigned long _get_rate(const char *clk_name) | |||
313 | 315 | ||
314 | return clk_get_rate(clk); | 316 | return clk_get_rate(clk); |
315 | } | 317 | } |
318 | |||
319 | #ifdef CONFIG_PM_SLEEP | ||
320 | static int samsung_clk_suspend(void) | ||
321 | { | ||
322 | struct samsung_clock_reg_cache *reg_cache; | ||
323 | |||
324 | list_for_each_entry(reg_cache, &clock_reg_cache_list, node) | ||
325 | samsung_clk_save(reg_cache->reg_base, reg_cache->rdump, | ||
326 | reg_cache->rd_num); | ||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | static void samsung_clk_resume(void) | ||
331 | { | ||
332 | struct samsung_clock_reg_cache *reg_cache; | ||
333 | |||
334 | list_for_each_entry(reg_cache, &clock_reg_cache_list, node) | ||
335 | samsung_clk_restore(reg_cache->reg_base, reg_cache->rdump, | ||
336 | reg_cache->rd_num); | ||
337 | } | ||
338 | |||
339 | static struct syscore_ops samsung_clk_syscore_ops = { | ||
340 | .suspend = samsung_clk_suspend, | ||
341 | .resume = samsung_clk_resume, | ||
342 | }; | ||
343 | |||
344 | static void samsung_clk_sleep_init(void __iomem *reg_base, | ||
345 | const unsigned long *rdump, | ||
346 | unsigned long nr_rdump) | ||
347 | { | ||
348 | struct samsung_clock_reg_cache *reg_cache; | ||
349 | |||
350 | reg_cache = kzalloc(sizeof(struct samsung_clock_reg_cache), | ||
351 | GFP_KERNEL); | ||
352 | if (!reg_cache) | ||
353 | panic("could not allocate register reg_cache.\n"); | ||
354 | reg_cache->rdump = samsung_clk_alloc_reg_dump(rdump, nr_rdump); | ||
355 | |||
356 | if (!reg_cache->rdump) | ||
357 | panic("could not allocate register dump storage.\n"); | ||
358 | |||
359 | if (list_empty(&clock_reg_cache_list)) | ||
360 | register_syscore_ops(&samsung_clk_syscore_ops); | ||
361 | |||
362 | reg_cache->reg_base = reg_base; | ||
363 | reg_cache->rd_num = nr_rdump; | ||
364 | list_add_tail(®_cache->node, &clock_reg_cache_list); | ||
365 | } | ||
366 | |||
367 | #else | ||
368 | static void samsung_clk_sleep_init(void __iomem *reg_base, | ||
369 | const unsigned long *rdump, | ||
370 | unsigned long nr_rdump) {} | ||
371 | #endif | ||
372 | |||
373 | /* | ||
374 | * Common function which registers plls, muxes, dividers and gates | ||
375 | * for each CMU. It also add CMU register list to register cache. | ||
376 | */ | ||
377 | void __init samsung_cmu_register_one(struct device_node *np, | ||
378 | struct samsung_cmu_info *cmu) | ||
379 | { | ||
380 | void __iomem *reg_base; | ||
381 | struct samsung_clk_provider *ctx; | ||
382 | |||
383 | reg_base = of_iomap(np, 0); | ||
384 | if (!reg_base) | ||
385 | panic("%s: failed to map registers\n", __func__); | ||
386 | |||
387 | ctx = samsung_clk_init(np, reg_base, cmu->nr_clk_ids); | ||
388 | if (!ctx) | ||
389 | panic("%s: unable to alllocate ctx\n", __func__); | ||
390 | |||
391 | if (cmu->pll_clks) | ||
392 | samsung_clk_register_pll(ctx, cmu->pll_clks, cmu->nr_pll_clks, | ||
393 | reg_base); | ||
394 | if (cmu->mux_clks) | ||
395 | samsung_clk_register_mux(ctx, cmu->mux_clks, | ||
396 | cmu->nr_mux_clks); | ||
397 | if (cmu->div_clks) | ||
398 | samsung_clk_register_div(ctx, cmu->div_clks, cmu->nr_div_clks); | ||
399 | if (cmu->gate_clks) | ||
400 | samsung_clk_register_gate(ctx, cmu->gate_clks, | ||
401 | cmu->nr_gate_clks); | ||
402 | if (cmu->fixed_clks) | ||
403 | samsung_clk_register_fixed_rate(ctx, cmu->fixed_clks, | ||
404 | cmu->nr_fixed_clks); | ||
405 | if (cmu->clk_regs) | ||
406 | samsung_clk_sleep_init(reg_base, cmu->clk_regs, | ||
407 | cmu->nr_clk_regs); | ||
408 | |||
409 | samsung_clk_of_add_provider(np, ctx); | ||
410 | } | ||
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index 66ab36b5cef1..b3d0f4d97f97 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h | |||
@@ -324,6 +324,37 @@ struct samsung_pll_clock { | |||
324 | __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \ | 324 | __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \ |
325 | _lock, _con, _rtable, _alias) | 325 | _lock, _con, _rtable, _alias) |
326 | 326 | ||
327 | struct samsung_clock_reg_cache { | ||
328 | struct list_head node; | ||
329 | void __iomem *reg_base; | ||
330 | struct samsung_clk_reg_dump *rdump; | ||
331 | unsigned int rd_num; | ||
332 | }; | ||
333 | |||
334 | struct samsung_cmu_info { | ||
335 | /* list of pll clocks and respective count */ | ||
336 | struct samsung_pll_clock *pll_clks; | ||
337 | unsigned int nr_pll_clks; | ||
338 | /* list of mux clocks and respective count */ | ||
339 | struct samsung_mux_clock *mux_clks; | ||
340 | unsigned int nr_mux_clks; | ||
341 | /* list of div clocks and respective count */ | ||
342 | struct samsung_div_clock *div_clks; | ||
343 | unsigned int nr_div_clks; | ||
344 | /* list of gate clocks and respective count */ | ||
345 | struct samsung_gate_clock *gate_clks; | ||
346 | unsigned int nr_gate_clks; | ||
347 | /* list of fixed clocks and respective count */ | ||
348 | struct samsung_fixed_rate_clock *fixed_clks; | ||
349 | unsigned int nr_fixed_clks; | ||
350 | /* total number of clocks with IDs assigned*/ | ||
351 | unsigned int nr_clk_ids; | ||
352 | |||
353 | /* list and number of clocks registers */ | ||
354 | unsigned long *clk_regs; | ||
355 | unsigned int nr_clk_regs; | ||
356 | }; | ||
357 | |||
327 | extern struct samsung_clk_provider *__init samsung_clk_init( | 358 | extern struct samsung_clk_provider *__init samsung_clk_init( |
328 | struct device_node *np, void __iomem *base, | 359 | struct device_node *np, void __iomem *base, |
329 | unsigned long nr_clks); | 360 | unsigned long nr_clks); |
@@ -362,6 +393,9 @@ extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx, | |||
362 | struct samsung_pll_clock *pll_list, | 393 | struct samsung_pll_clock *pll_list, |
363 | unsigned int nr_clk, void __iomem *base); | 394 | unsigned int nr_clk, void __iomem *base); |
364 | 395 | ||
396 | extern void __init samsung_cmu_register_one(struct device_node *, | ||
397 | struct samsung_cmu_info *); | ||
398 | |||
365 | extern unsigned long _get_rate(const char *clk_name); | 399 | extern unsigned long _get_rate(const char *clk_name); |
366 | 400 | ||
367 | extern void samsung_clk_save(void __iomem *base, | 401 | extern void samsung_clk_save(void __iomem *base, |