diff options
author | Stefan Agner <stefan@agner.ch> | 2016-03-09 21:16:50 -0500 |
---|---|---|
committer | Shawn Guo <shawnguo@kernel.org> | 2016-03-31 05:02:06 -0400 |
commit | 4cfe6aebb272d7c75a2c21ce5db3a9e10f57901a (patch) | |
tree | ef73409542b962251822ff8344a67cda1f3176a0 | |
parent | 349efbeedb2b79292eee12cf6b9a2422ef93853d (diff) |
clk: imx: vf610: add suspend/resume support
The clock register are lost when enterying LPSTOPx, hence provide
suspend/resume functions restoring them. The clock gates get
restored by the individual driver, hence we do not need to restore
them here.
Signed-off-by: Stefan Agner <stefan@agner.ch>
Signed-off-by: Shawn Guo <shawnguo@kernel.org>
-rw-r--r-- | drivers/clk/imx/clk-vf610.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c index 610a72464f1e..66e6faede8e5 100644 --- a/drivers/clk/imx/clk-vf610.c +++ b/drivers/clk/imx/clk-vf610.c | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include <linux/of_address.h> | 11 | #include <linux/of_address.h> |
12 | #include <linux/clk.h> | 12 | #include <linux/clk.h> |
13 | #include <linux/syscore_ops.h> | ||
13 | #include <dt-bindings/clock/vf610-clock.h> | 14 | #include <dt-bindings/clock/vf610-clock.h> |
14 | 15 | ||
15 | #include "clk.h" | 16 | #include "clk.h" |
@@ -40,6 +41,7 @@ | |||
40 | #define CCM_CCGR9 (ccm_base + 0x64) | 41 | #define CCM_CCGR9 (ccm_base + 0x64) |
41 | #define CCM_CCGR10 (ccm_base + 0x68) | 42 | #define CCM_CCGR10 (ccm_base + 0x68) |
42 | #define CCM_CCGR11 (ccm_base + 0x6c) | 43 | #define CCM_CCGR11 (ccm_base + 0x6c) |
44 | #define CCM_CCGRx(x) (CCM_CCGR0 + (x) * 4) | ||
43 | #define CCM_CMEOR0 (ccm_base + 0x70) | 45 | #define CCM_CMEOR0 (ccm_base + 0x70) |
44 | #define CCM_CMEOR1 (ccm_base + 0x74) | 46 | #define CCM_CMEOR1 (ccm_base + 0x74) |
45 | #define CCM_CMEOR2 (ccm_base + 0x78) | 47 | #define CCM_CMEOR2 (ccm_base + 0x78) |
@@ -115,6 +117,13 @@ static struct clk_div_table pll4_audio_div_table[] = { | |||
115 | static struct clk *clk[VF610_CLK_END]; | 117 | static struct clk *clk[VF610_CLK_END]; |
116 | static struct clk_onecell_data clk_data; | 118 | static struct clk_onecell_data clk_data; |
117 | 119 | ||
120 | static u32 cscmr1; | ||
121 | static u32 cscmr2; | ||
122 | static u32 cscdr1; | ||
123 | static u32 cscdr2; | ||
124 | static u32 cscdr3; | ||
125 | static u32 ccgr[12]; | ||
126 | |||
118 | static unsigned int const clks_init_on[] __initconst = { | 127 | static unsigned int const clks_init_on[] __initconst = { |
119 | VF610_CLK_SYS_BUS, | 128 | VF610_CLK_SYS_BUS, |
120 | VF610_CLK_DDR_SEL, | 129 | VF610_CLK_DDR_SEL, |
@@ -134,6 +143,43 @@ static struct clk * __init vf610_get_fixed_clock( | |||
134 | return clk; | 143 | return clk; |
135 | }; | 144 | }; |
136 | 145 | ||
146 | static int vf610_clk_suspend(void) | ||
147 | { | ||
148 | int i; | ||
149 | |||
150 | cscmr1 = readl_relaxed(CCM_CSCMR1); | ||
151 | cscmr2 = readl_relaxed(CCM_CSCMR2); | ||
152 | |||
153 | cscdr1 = readl_relaxed(CCM_CSCDR1); | ||
154 | cscdr2 = readl_relaxed(CCM_CSCDR2); | ||
155 | cscdr3 = readl_relaxed(CCM_CSCDR3); | ||
156 | |||
157 | for (i = 0; i < 12; i++) | ||
158 | ccgr[i] = readl_relaxed(CCM_CCGRx(i)); | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static void vf610_clk_resume(void) | ||
164 | { | ||
165 | int i; | ||
166 | |||
167 | writel_relaxed(cscmr1, CCM_CSCMR1); | ||
168 | writel_relaxed(cscmr2, CCM_CSCMR2); | ||
169 | |||
170 | writel_relaxed(cscdr1, CCM_CSCDR1); | ||
171 | writel_relaxed(cscdr2, CCM_CSCDR2); | ||
172 | writel_relaxed(cscdr3, CCM_CSCDR3); | ||
173 | |||
174 | for (i = 0; i < 12; i++) | ||
175 | writel_relaxed(ccgr[i], CCM_CCGRx(i)); | ||
176 | } | ||
177 | |||
178 | static struct syscore_ops vf610_clk_syscore_ops = { | ||
179 | .suspend = vf610_clk_suspend, | ||
180 | .resume = vf610_clk_resume, | ||
181 | }; | ||
182 | |||
137 | static void __init vf610_clocks_init(struct device_node *ccm_node) | 183 | static void __init vf610_clocks_init(struct device_node *ccm_node) |
138 | { | 184 | { |
139 | struct device_node *np; | 185 | struct device_node *np; |
@@ -414,6 +460,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) | |||
414 | for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) | 460 | for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) |
415 | clk_prepare_enable(clk[clks_init_on[i]]); | 461 | clk_prepare_enable(clk[clks_init_on[i]]); |
416 | 462 | ||
463 | register_syscore_ops(&vf610_clk_syscore_ops); | ||
464 | |||
417 | /* Add the clocks to provider list */ | 465 | /* Add the clocks to provider list */ |
418 | clk_data.clks = clk; | 466 | clk_data.clks = clk; |
419 | clk_data.clk_num = ARRAY_SIZE(clk); | 467 | clk_data.clk_num = ARRAY_SIZE(clk); |