clk-fixed-factor.c (8188B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> 4 */ 5#include <linux/module.h> 6#include <linux/clk-provider.h> 7#include <linux/slab.h> 8#include <linux/err.h> 9#include <linux/of.h> 10#include <linux/platform_device.h> 11 12/* 13 * DOC: basic fixed multiplier and divider clock that cannot gate 14 * 15 * Traits of this clock: 16 * prepare - clk_prepare only ensures that parents are prepared 17 * enable - clk_enable only ensures that parents are enabled 18 * rate - rate is fixed. clk->rate = parent->rate / div * mult 19 * parent - fixed parent. No clk_set_parent support 20 */ 21 22static unsigned long clk_factor_recalc_rate(struct clk_hw *hw, 23 unsigned long parent_rate) 24{ 25 struct clk_fixed_factor *fix = to_clk_fixed_factor(hw); 26 unsigned long long int rate; 27 28 rate = (unsigned long long int)parent_rate * fix->mult; 29 do_div(rate, fix->div); 30 return (unsigned long)rate; 31} 32 33static long clk_factor_round_rate(struct clk_hw *hw, unsigned long rate, 34 unsigned long *prate) 35{ 36 struct clk_fixed_factor *fix = to_clk_fixed_factor(hw); 37 38 if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) { 39 unsigned long best_parent; 40 41 best_parent = (rate / fix->mult) * fix->div; 42 *prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent); 43 } 44 45 return (*prate / fix->div) * fix->mult; 46} 47 48static int clk_factor_set_rate(struct clk_hw *hw, unsigned long rate, 49 unsigned long parent_rate) 50{ 51 /* 52 * We must report success but we can do so unconditionally because 53 * clk_factor_round_rate returns values that ensure this call is a 54 * nop. 55 */ 56 57 return 0; 58} 59 60const struct clk_ops clk_fixed_factor_ops = { 61 .round_rate = clk_factor_round_rate, 62 .set_rate = clk_factor_set_rate, 63 .recalc_rate = clk_factor_recalc_rate, 64}; 65EXPORT_SYMBOL_GPL(clk_fixed_factor_ops); 66 67static void devm_clk_hw_register_fixed_factor_release(struct device *dev, void *res) 68{ 69 struct clk_fixed_factor *fix = res; 70 71 /* 72 * We can not use clk_hw_unregister_fixed_factor, since it will kfree() 73 * the hw, resulting in double free. Just unregister the hw and let 74 * devres code kfree() it. 75 */ 76 clk_hw_unregister(&fix->hw); 77} 78 79static struct clk_hw * 80__clk_hw_register_fixed_factor(struct device *dev, struct device_node *np, 81 const char *name, const char *parent_name, int index, 82 unsigned long flags, unsigned int mult, unsigned int div, 83 bool devm) 84{ 85 struct clk_fixed_factor *fix; 86 struct clk_init_data init = { }; 87 struct clk_parent_data pdata = { .index = index }; 88 struct clk_hw *hw; 89 int ret; 90 91 /* You can't use devm without a dev */ 92 if (devm && !dev) 93 return ERR_PTR(-EINVAL); 94 95 if (devm) 96 fix = devres_alloc(devm_clk_hw_register_fixed_factor_release, 97 sizeof(*fix), GFP_KERNEL); 98 else 99 fix = kmalloc(sizeof(*fix), GFP_KERNEL); 100 if (!fix) 101 return ERR_PTR(-ENOMEM); 102 103 /* struct clk_fixed_factor assignments */ 104 fix->mult = mult; 105 fix->div = div; 106 fix->hw.init = &init; 107 108 init.name = name; 109 init.ops = &clk_fixed_factor_ops; 110 init.flags = flags; 111 if (parent_name) 112 init.parent_names = &parent_name; 113 else 114 init.parent_data = &pdata; 115 init.num_parents = 1; 116 117 hw = &fix->hw; 118 if (dev) 119 ret = clk_hw_register(dev, hw); 120 else 121 ret = of_clk_hw_register(np, hw); 122 if (ret) { 123 if (devm) 124 devres_free(fix); 125 else 126 kfree(fix); 127 hw = ERR_PTR(ret); 128 } else if (devm) 129 devres_add(dev, fix); 130 131 return hw; 132} 133 134/** 135 * devm_clk_hw_register_fixed_factor_index - Register a fixed factor clock with 136 * parent from DT index 137 * @dev: device that is registering this clock 138 * @name: name of this clock 139 * @index: index of phandle in @dev 'clocks' property 140 * @flags: fixed factor flags 141 * @mult: multiplier 142 * @div: divider 143 * 144 * Return: Pointer to fixed factor clk_hw structure that was registered or 145 * an error pointer. 146 */ 147struct clk_hw *devm_clk_hw_register_fixed_factor_index(struct device *dev, 148 const char *name, unsigned int index, unsigned long flags, 149 unsigned int mult, unsigned int div) 150{ 151 return __clk_hw_register_fixed_factor(dev, NULL, name, NULL, index, 152 flags, mult, div, true); 153} 154EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor_index); 155 156struct clk_hw *clk_hw_register_fixed_factor(struct device *dev, 157 const char *name, const char *parent_name, unsigned long flags, 158 unsigned int mult, unsigned int div) 159{ 160 return __clk_hw_register_fixed_factor(dev, NULL, name, parent_name, -1, 161 flags, mult, div, false); 162} 163EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor); 164 165struct clk *clk_register_fixed_factor(struct device *dev, const char *name, 166 const char *parent_name, unsigned long flags, 167 unsigned int mult, unsigned int div) 168{ 169 struct clk_hw *hw; 170 171 hw = clk_hw_register_fixed_factor(dev, name, parent_name, flags, mult, 172 div); 173 if (IS_ERR(hw)) 174 return ERR_CAST(hw); 175 return hw->clk; 176} 177EXPORT_SYMBOL_GPL(clk_register_fixed_factor); 178 179void clk_unregister_fixed_factor(struct clk *clk) 180{ 181 struct clk_hw *hw; 182 183 hw = __clk_get_hw(clk); 184 if (!hw) 185 return; 186 187 clk_unregister(clk); 188 kfree(to_clk_fixed_factor(hw)); 189} 190EXPORT_SYMBOL_GPL(clk_unregister_fixed_factor); 191 192void clk_hw_unregister_fixed_factor(struct clk_hw *hw) 193{ 194 struct clk_fixed_factor *fix; 195 196 fix = to_clk_fixed_factor(hw); 197 198 clk_hw_unregister(hw); 199 kfree(fix); 200} 201EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_factor); 202 203struct clk_hw *devm_clk_hw_register_fixed_factor(struct device *dev, 204 const char *name, const char *parent_name, unsigned long flags, 205 unsigned int mult, unsigned int div) 206{ 207 return __clk_hw_register_fixed_factor(dev, NULL, name, parent_name, -1, 208 flags, mult, div, true); 209} 210EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor); 211 212#ifdef CONFIG_OF 213static const struct of_device_id set_rate_parent_matches[] = { 214 { .compatible = "allwinner,sun4i-a10-pll3-2x-clk" }, 215 { /* Sentinel */ }, 216}; 217 218static struct clk_hw *_of_fixed_factor_clk_setup(struct device_node *node) 219{ 220 struct clk_hw *hw; 221 const char *clk_name = node->name; 222 unsigned long flags = 0; 223 u32 div, mult; 224 int ret; 225 226 if (of_property_read_u32(node, "clock-div", &div)) { 227 pr_err("%s Fixed factor clock <%pOFn> must have a clock-div property\n", 228 __func__, node); 229 return ERR_PTR(-EIO); 230 } 231 232 if (of_property_read_u32(node, "clock-mult", &mult)) { 233 pr_err("%s Fixed factor clock <%pOFn> must have a clock-mult property\n", 234 __func__, node); 235 return ERR_PTR(-EIO); 236 } 237 238 of_property_read_string(node, "clock-output-names", &clk_name); 239 240 if (of_match_node(set_rate_parent_matches, node)) 241 flags |= CLK_SET_RATE_PARENT; 242 243 hw = __clk_hw_register_fixed_factor(NULL, node, clk_name, NULL, 0, 244 flags, mult, div, false); 245 if (IS_ERR(hw)) { 246 /* 247 * Clear OF_POPULATED flag so that clock registration can be 248 * attempted again from probe function. 249 */ 250 of_node_clear_flag(node, OF_POPULATED); 251 return ERR_CAST(hw); 252 } 253 254 ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw); 255 if (ret) { 256 clk_hw_unregister_fixed_factor(hw); 257 return ERR_PTR(ret); 258 } 259 260 return hw; 261} 262 263/** 264 * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock 265 * @node: device node for the clock 266 */ 267void __init of_fixed_factor_clk_setup(struct device_node *node) 268{ 269 _of_fixed_factor_clk_setup(node); 270} 271CLK_OF_DECLARE(fixed_factor_clk, "fixed-factor-clock", 272 of_fixed_factor_clk_setup); 273 274static int of_fixed_factor_clk_remove(struct platform_device *pdev) 275{ 276 struct clk_hw *clk = platform_get_drvdata(pdev); 277 278 of_clk_del_provider(pdev->dev.of_node); 279 clk_hw_unregister_fixed_factor(clk); 280 281 return 0; 282} 283 284static int of_fixed_factor_clk_probe(struct platform_device *pdev) 285{ 286 struct clk_hw *clk; 287 288 /* 289 * This function is not executed when of_fixed_factor_clk_setup 290 * succeeded. 291 */ 292 clk = _of_fixed_factor_clk_setup(pdev->dev.of_node); 293 if (IS_ERR(clk)) 294 return PTR_ERR(clk); 295 296 platform_set_drvdata(pdev, clk); 297 298 return 0; 299} 300 301static const struct of_device_id of_fixed_factor_clk_ids[] = { 302 { .compatible = "fixed-factor-clock" }, 303 { } 304}; 305MODULE_DEVICE_TABLE(of, of_fixed_factor_clk_ids); 306 307static struct platform_driver of_fixed_factor_clk_driver = { 308 .driver = { 309 .name = "of_fixed_factor_clk", 310 .of_match_table = of_fixed_factor_clk_ids, 311 }, 312 .probe = of_fixed_factor_clk_probe, 313 .remove = of_fixed_factor_clk_remove, 314}; 315builtin_platform_driver(of_fixed_factor_clk_driver); 316#endif