aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Turquette <mturquette@linaro.org>2014-08-27 20:11:38 -0400
committerMike Turquette <mturquette@linaro.org>2014-09-01 20:43:52 -0400
commite8e8a9b0d86c093b208789fd71501c91a919ffdb (patch)
treee443d76dee27e562bc7b94b5d52eb49493798cb8
parent87e392164ab6c0f3f055f8483dc7dc3f1afa19ad (diff)
clk: mvebu: powersave clock is a multiplexer
Kirkwood is unique among the mvebu SoCs for having a clock multiplexer that feeds into the cpu. This multiplexer can select either the cpu pll or the ddr clock as its input signal, allowing for a choice between performance and power savings. This patch introduces the code needed to register the clock multiplexer on Kirkwood SoCs but does not include the clock data to actually register the clock. That will be done in a follow-up patch which is necessary to prevent breaking git bisect. Cc: Tomeu Vizoso <tomeu.vizoso@collabora.com> Tested-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Mike Turquette <mturquette@linaro.org>
-rw-r--r--drivers/clk/mvebu/kirkwood.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/drivers/clk/mvebu/kirkwood.c b/drivers/clk/mvebu/kirkwood.c
index ddb666a86500..f73a2fa8a561 100644
--- a/drivers/clk/mvebu/kirkwood.c
+++ b/drivers/clk/mvebu/kirkwood.c
@@ -13,9 +13,11 @@
13 */ 13 */
14 14
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <linux/slab.h>
16#include <linux/clk-provider.h> 17#include <linux/clk-provider.h>
17#include <linux/io.h> 18#include <linux/io.h>
18#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/of_address.h>
19#include "common.h" 21#include "common.h"
20 22
21/* 23/*
@@ -225,6 +227,91 @@ static const struct clk_gating_soc_desc kirkwood_gating_desc[] __initconst = {
225 { } 227 { }
226}; 228};
227 229
230
231/*
232 * Clock Muxing Control
233 */
234
235struct clk_muxing_soc_desc {
236 const char *name;
237 const char **parents;
238 int num_parents;
239 int shift;
240 int width;
241 unsigned long flags;
242};
243
244struct clk_muxing_ctrl {
245 spinlock_t *lock;
246 struct clk **muxes;
247 int num_muxes;
248};
249
250#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw)
251
252static struct clk *clk_muxing_get_src(
253 struct of_phandle_args *clkspec, void *data)
254{
255 struct clk_muxing_ctrl *ctrl = (struct clk_muxing_ctrl *)data;
256 int n;
257
258 if (clkspec->args_count < 1)
259 return ERR_PTR(-EINVAL);
260
261 for (n = 0; n < ctrl->num_muxes; n++) {
262 struct clk_mux *mux =
263 to_clk_mux(__clk_get_hw(ctrl->muxes[n]));
264 if (clkspec->args[0] == mux->shift)
265 return ctrl->muxes[n];
266 }
267 return ERR_PTR(-ENODEV);
268}
269
270static void __init kirkwood_clk_muxing_setup(struct device_node *np,
271 const struct clk_muxing_soc_desc *desc)
272{
273 struct clk_muxing_ctrl *ctrl;
274 void __iomem *base;
275 int n;
276
277 base = of_iomap(np, 0);
278 if (WARN_ON(!base))
279 return;
280
281 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
282 if (WARN_ON(!ctrl))
283 goto ctrl_out;
284
285 /* lock must already be initialized */
286 ctrl->lock = &ctrl_gating_lock;
287
288 /* Count, allocate, and register clock muxes */
289 for (n = 0; desc[n].name;)
290 n++;
291
292 ctrl->num_muxes = n;
293 ctrl->muxes = kcalloc(ctrl->num_muxes, sizeof(struct clk *),
294 GFP_KERNEL);
295 if (WARN_ON(!ctrl->muxes))
296 goto muxes_out;
297
298 for (n = 0; n < ctrl->num_muxes; n++) {
299 ctrl->muxes[n] = clk_register_mux(NULL, desc[n].name,
300 desc[n].parents, desc[n].num_parents,
301 desc[n].flags, base, desc[n].shift,
302 desc[n].width, desc[n].flags, ctrl->lock);
303 WARN_ON(IS_ERR(ctrl->muxes[n]));
304 }
305
306 of_clk_add_provider(np, clk_muxing_get_src, ctrl);
307
308 return;
309muxes_out:
310 kfree(ctrl);
311ctrl_out:
312 iounmap(base);
313}
314
228static void __init kirkwood_clk_init(struct device_node *np) 315static void __init kirkwood_clk_init(struct device_node *np)
229{ 316{
230 struct device_node *cgnp = 317 struct device_node *cgnp =