2 * Driver for the ICST307 VCO clock found in the ARM Reference designs.
3 * We wrap the custom interface from <asm/hardware/icst.h> into the generic
6 * TODO: when all ARM reference designs are migrated to generic clocks, the
7 * ICST clock code from the ARM tree should probably be merged into this
10 #include <linux/clk.h>
11 #include <linux/clkdev.h>
12 #include <linux/err.h>
13 #include <linux/clk-provider.h>
18 * struct clk_icst - ICST VCO clock wrapper
19 * @hw: corresponding clock hardware entry
20 * @params: parameters for this ICST instance
22 * @setvco: function to commit ICST settings to hardware
26 const struct icst_params *params;
28 struct icst_vco (*getvco)(void);
29 void (*setvco)(struct icst_vco);
32 #define to_icst(_hw) container_of(_hw, struct clk_icst, hw)
34 static unsigned long icst_recalc_rate(struct clk_hw *hw,
35 unsigned long parent_rate)
37 struct clk_icst *icst = to_icst(hw);
41 icst->rate = icst_hz(icst->params, vco);
45 static long icst_round_rate(struct clk_hw *hw, unsigned long rate,
48 struct clk_icst *icst = to_icst(hw);
51 vco = icst_hz_to_vco(icst->params, rate);
52 return icst_hz(icst->params, vco);
55 static int icst_set_rate(struct clk_hw *hw, unsigned long rate,
56 unsigned long parent_rate)
58 struct clk_icst *icst = to_icst(hw);
61 vco = icst_hz_to_vco(icst->params, rate);
62 icst->rate = icst_hz(icst->params, vco);
67 static const struct clk_ops icst_ops = {
68 .recalc_rate = icst_recalc_rate,
69 .round_rate = icst_round_rate,
70 .set_rate = icst_set_rate,
73 struct clk * __init icst_clk_register(struct device *dev,
74 const struct clk_icst_desc *desc)
77 struct clk_icst *icst;
78 struct clk_init_data init;
80 icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL);
82 pr_err("could not allocate ICST clock!\n");
83 return ERR_PTR(-ENOMEM);
87 init.flags = CLK_IS_ROOT;
88 init.parent_names = NULL;
90 icst->hw.init = &init;
91 icst->params = desc->params;
92 icst->getvco = desc->getvco;
93 icst->setvco = desc->setvco;
95 clk = clk_register(dev, &icst->hw);