aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 =