aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2014-12-04 10:46:43 -0500
committerArnd Bergmann <arnd@arndb.de>2014-12-04 10:46:43 -0500
commitab64920c3742ba992a3bf0b06f9750d1cad9d050 (patch)
tree3391e85b0bb7372d7d34775047e9d8c894042938 /drivers/clk
parent756f80cee766574ae282baa97fdcf9cc6d0cc70c (diff)
parent6e6db2bea3ea9424a0cb19d89d47664bc13e31bc (diff)
Merge tag 'mvebu-soc-suspend-3.19' of git://git.infradead.org/linux-mvebu into next/soc
Pull "mvebu SoC suspend changes for v3.19" from Jason Cooper: - Armada 370/XP suspend/resume support - mvebu SoC driver suspend/resume support - irqchip - clocksource - mbus - clk * tag 'mvebu-soc-suspend-3.19' of git://git.infradead.org/linux-mvebu: ARM: mvebu: add SDRAM controller description for Armada XP ARM: mvebu: adjust mbus controller description on Armada 370/XP ARM: mvebu: add suspend/resume DT information for Armada XP GP ARM: mvebu: synchronize secondary CPU clocks on resume ARM: mvebu: make sure MMU is disabled in armada_370_xp_cpu_resume ARM: mvebu: Armada XP GP specific suspend/resume code ARM: mvebu: reserve the first 10 KB of each memory bank for suspend/resume ARM: mvebu: implement suspend/resume support for Armada XP clk: mvebu: add suspend/resume for gatable clocks bus: mvebu-mbus: provide a mechanism to save SDRAM window configuration bus: mvebu-mbus: suspend/resume support clocksource: time-armada-370-xp: add suspend/resume support irqchip: armada-370-xp: Add suspend/resume support Documentation: dt-bindings: minimal documentation for MVEBU SDRAM controller Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/mvebu/common.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/drivers/clk/mvebu/common.c b/drivers/clk/mvebu/common.c
index b7fcb469c87a..0d4d1216f2dd 100644
--- a/drivers/clk/mvebu/common.c
+++ b/drivers/clk/mvebu/common.c
@@ -19,6 +19,7 @@
19#include <linux/io.h> 19#include <linux/io.h>
20#include <linux/of.h> 20#include <linux/of.h>
21#include <linux/of_address.h> 21#include <linux/of_address.h>
22#include <linux/syscore_ops.h>
22 23
23#include "common.h" 24#include "common.h"
24 25
@@ -177,14 +178,17 @@ struct clk_gating_ctrl {
177 spinlock_t *lock; 178 spinlock_t *lock;
178 struct clk **gates; 179 struct clk **gates;
179 int num_gates; 180 int num_gates;
181 void __iomem *base;
182 u32 saved_reg;
180}; 183};
181 184
182#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw) 185#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
183 186
187static struct clk_gating_ctrl *ctrl;
188
184static struct clk *clk_gating_get_src( 189static struct clk *clk_gating_get_src(
185 struct of_phandle_args *clkspec, void *data) 190 struct of_phandle_args *clkspec, void *data)
186{ 191{
187 struct clk_gating_ctrl *ctrl = (struct clk_gating_ctrl *)data;
188 int n; 192 int n;
189 193
190 if (clkspec->args_count < 1) 194 if (clkspec->args_count < 1)
@@ -199,15 +203,35 @@ static struct clk *clk_gating_get_src(
199 return ERR_PTR(-ENODEV); 203 return ERR_PTR(-ENODEV);
200} 204}
201 205
206static int mvebu_clk_gating_suspend(void)
207{
208 ctrl->saved_reg = readl(ctrl->base);
209 return 0;
210}
211
212static void mvebu_clk_gating_resume(void)
213{
214 writel(ctrl->saved_reg, ctrl->base);
215}
216
217static struct syscore_ops clk_gate_syscore_ops = {
218 .suspend = mvebu_clk_gating_suspend,
219 .resume = mvebu_clk_gating_resume,
220};
221
202void __init mvebu_clk_gating_setup(struct device_node *np, 222void __init mvebu_clk_gating_setup(struct device_node *np,
203 const struct clk_gating_soc_desc *desc) 223 const struct clk_gating_soc_desc *desc)
204{ 224{
205 struct clk_gating_ctrl *ctrl;
206 struct clk *clk; 225 struct clk *clk;
207 void __iomem *base; 226 void __iomem *base;
208 const char *default_parent = NULL; 227 const char *default_parent = NULL;
209 int n; 228 int n;
210 229
230 if (ctrl) {
231 pr_err("mvebu-clk-gating: cannot instantiate more than one gatable clock device\n");
232 return;
233 }
234
211 base = of_iomap(np, 0); 235 base = of_iomap(np, 0);
212 if (WARN_ON(!base)) 236 if (WARN_ON(!base))
213 return; 237 return;
@@ -225,6 +249,8 @@ void __init mvebu_clk_gating_setup(struct device_node *np,
225 /* lock must already be initialized */ 249 /* lock must already be initialized */
226 ctrl->lock = &ctrl_gating_lock; 250 ctrl->lock = &ctrl_gating_lock;
227 251
252 ctrl->base = base;
253
228 /* Count, allocate, and register clock gates */ 254 /* Count, allocate, and register clock gates */
229 for (n = 0; desc[n].name;) 255 for (n = 0; desc[n].name;)
230 n++; 256 n++;
@@ -246,6 +272,8 @@ void __init mvebu_clk_gating_setup(struct device_node *np,
246 272
247 of_clk_add_provider(np, clk_gating_get_src, ctrl); 273 of_clk_add_provider(np, clk_gating_get_src, ctrl);
248 274
275 register_syscore_ops(&clk_gate_syscore_ops);
276
249 return; 277 return;
250gates_out: 278gates_out:
251 kfree(ctrl); 279 kfree(ctrl);