1 /* 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 4 * clock framework. 5 * 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 8 * file. 9 */ 10 #include <linux/clk.h> 11 #include <linux/clkdev.h> 12 #include <linux/err.h> 13 #include <linux/clk-provider.h> 14 15 #include "clk-icst.h" 16 17 /** 18 * struct clk_icst - ICST VCO clock wrapper 19 * @hw: corresponding clock hardware entry 20 * @params: parameters for this ICST instance 21 * @rate: current rate 22 * @setvco: function to commit ICST settings to hardware 23 */ 24 struct clk_icst { 25 struct clk_hw hw; 26 const struct icst_params *params; 27 unsigned long rate; 28 struct icst_vco (*getvco)(void); 29 void (*setvco)(struct icst_vco); 30 }; 31 32 #define to_icst(_hw) container_of(_hw, struct clk_icst, hw) 33 34 static unsigned long icst_recalc_rate(struct clk_hw *hw, 35 unsigned long parent_rate) 36 { 37 struct clk_icst *icst = to_icst(hw); 38 struct icst_vco vco; 39 40 vco = icst->getvco(); 41 icst->rate = icst_hz(icst->params, vco); 42 return icst->rate; 43 } 44 45 static long icst_round_rate(struct clk_hw *hw, unsigned long rate, 46 unsigned long *prate) 47 { 48 struct clk_icst *icst = to_icst(hw); 49 struct icst_vco vco; 50 51 vco = icst_hz_to_vco(icst->params, rate); 52 return icst_hz(icst->params, vco); 53 } 54 55 static int icst_set_rate(struct clk_hw *hw, unsigned long rate, 56 unsigned long parent_rate) 57 { 58 struct clk_icst *icst = to_icst(hw); 59 struct icst_vco vco; 60 61 vco = icst_hz_to_vco(icst->params, rate); 62 icst->rate = icst_hz(icst->params, vco); 63 icst->setvco(vco); 64 return 0; 65 } 66 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, 71 }; 72 73 struct clk * __init icst_clk_register(struct device *dev, 74 const struct clk_icst_desc *desc) 75 { 76 struct clk *clk; 77 struct clk_icst *icst; 78 struct clk_init_data init; 79 80 icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL); 81 if (!icst) { 82 pr_err("could not allocate ICST clock!\n"); 83 return ERR_PTR(-ENOMEM); 84 } 85 init.name = "icst"; 86 init.ops = &icst_ops; 87 init.flags = CLK_IS_ROOT; 88 init.parent_names = NULL; 89 init.num_parents = 0; 90 icst->hw.init = &init; 91 icst->params = desc->params; 92 icst->getvco = desc->getvco; 93 icst->setvco = desc->setvco; 94 95 clk = clk_register(dev, &icst->hw); 96 if (IS_ERR(clk)) 97 kfree(icst); 98 99 return clk; 100 } 101