Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: add versatile ICST307 driver

The ICST307 VCO clock has a shared driver in the ARM
architecture. This patch provides a wrapper into the common
clock framework so we can use the implementation in the
ARM architecture without duplicating the code until all
ARM platforms using this VCO are moved over. At that point
we can merge the driver from the ARM platform into the
generic file altogether.

Cc: Russell King <linux@arm.linux.org.uk>
Cc: Mike Turquette <mturquette@ti.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
[mturquette@linaro.org: removed versatile Kconfig]
Signed-off-by: Mike Turquette <mturquette@linaro.org>

authored by

Linus Walleij and committed by
Mike Turquette
91b87a47 d59fdcfc

+113
+1
drivers/clk/Makefile
··· 6 6 obj-$(CONFIG_ARCH_MXS) += mxs/ 7 7 obj-$(CONFIG_PLAT_SPEAR) += spear/ 8 8 obj-$(CONFIG_ARCH_U300) += clk-u300.o 9 + obj-$(CONFIG_ARCH_INTEGRATOR) += versatile/ 9 10 10 11 # Chip specific 11 12 obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
+2
drivers/clk/versatile/Makefile
··· 1 + # Makefile for Versatile-specific clocks 2 + obj-$(CONFIG_ICST) += clk-icst.o
+100
drivers/clk/versatile/clk-icst.c
··· 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 + }
+10
drivers/clk/versatile/clk-icst.h
··· 1 + #include <asm/hardware/icst.h> 2 + 3 + struct clk_icst_desc { 4 + const struct icst_params *params; 5 + struct icst_vco (*getvco)(void); 6 + void (*setvco)(struct icst_vco); 7 + }; 8 + 9 + struct clk *icst_clk_register(struct device *dev, 10 + const struct clk_icst_desc *desc);