1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com> 4 * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org> 5 * 6 * Fixed rate clock implementation 7 */ 8 9 #include <linux/clk-provider.h> 10 #include <linux/module.h> 11 #include <linux/slab.h> 12 #include <linux/io.h> 13 #include <linux/err.h> 14 #include <linux/of.h> 15 #include <linux/platform_device.h> 16 17 /* 18 * DOC: basic fixed-rate clock that cannot gate 19 * 20 * Traits of this clock: 21 * prepare - clk_(un)prepare only ensures parents are prepared 22 * enable - clk_enable only ensures parents are enabled 23 * rate - rate is always a fixed value. No clk_set_rate support 24 * parent - fixed parent. No clk_set_parent support 25 */ 26 27 static unsigned long clk_fixed_rate_recalc_rate(struct clk_hw *hw, 28 unsigned long parent_rate) 29 { 30 return to_clk_fixed_rate(hw)->fixed_rate; 31 } 32 33 static unsigned long clk_fixed_rate_recalc_accuracy(struct clk_hw *hw, 34 unsigned long parent_accuracy) 35 { 36 return to_clk_fixed_rate(hw)->fixed_accuracy; 37 } 38 39 const struct clk_ops clk_fixed_rate_ops = { 40 .recalc_rate = clk_fixed_rate_recalc_rate, 41 .recalc_accuracy = clk_fixed_rate_recalc_accuracy, 42 }; 43 EXPORT_SYMBOL_GPL(clk_fixed_rate_ops); 44 45 /** 46 * clk_hw_register_fixed_rate_with_accuracy - register fixed-rate clock with 47 * the clock framework 48 * @dev: device that is registering this clock 49 * @name: name of this clock 50 * @parent_name: name of clock's parent 51 * @flags: framework-specific flags 52 * @fixed_rate: non-adjustable clock rate 53 * @fixed_accuracy: non-adjustable clock rate 54 */ 55 struct clk_hw *clk_hw_register_fixed_rate_with_accuracy(struct device *dev, 56 const char *name, const char *parent_name, unsigned long flags, 57 unsigned long fixed_rate, unsigned long fixed_accuracy) 58 { 59 struct clk_fixed_rate *fixed; 60 struct clk_hw *hw; 61 struct clk_init_data init; 62 int ret; 63 64 /* allocate fixed-rate clock */ 65 fixed = kzalloc(sizeof(*fixed), GFP_KERNEL); 66 if (!fixed) 67 return ERR_PTR(-ENOMEM); 68 69 init.name = name; 70 init.ops = &clk_fixed_rate_ops; 71 init.flags = flags | CLK_IS_BASIC; 72 init.parent_names = (parent_name ? &parent_name: NULL); 73 init.num_parents = (parent_name ? 1 : 0); 74 75 /* struct clk_fixed_rate assignments */ 76 fixed->fixed_rate = fixed_rate; 77 fixed->fixed_accuracy = fixed_accuracy; 78 fixed->hw.init = &init; 79 80 /* register the clock */ 81 hw = &fixed->hw; 82 ret = clk_hw_register(dev, hw); 83 if (ret) { 84 kfree(fixed); 85 hw = ERR_PTR(ret); 86 } 87 88 return hw; 89 } 90 EXPORT_SYMBOL_GPL(clk_hw_register_fixed_rate_with_accuracy); 91 92 struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev, 93 const char *name, const char *parent_name, unsigned long flags, 94 unsigned long fixed_rate, unsigned long fixed_accuracy) 95 { 96 struct clk_hw *hw; 97 98 hw = clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name, 99 flags, fixed_rate, fixed_accuracy); 100 if (IS_ERR(hw)) 101 return ERR_CAST(hw); 102 return hw->clk; 103 } 104 EXPORT_SYMBOL_GPL(clk_register_fixed_rate_with_accuracy); 105 106 /** 107 * clk_hw_register_fixed_rate - register fixed-rate clock with the clock 108 * framework 109 * @dev: device that is registering this clock 110 * @name: name of this clock 111 * @parent_name: name of clock's parent 112 * @flags: framework-specific flags 113 * @fixed_rate: non-adjustable clock rate 114 */ 115 struct clk_hw *clk_hw_register_fixed_rate(struct device *dev, const char *name, 116 const char *parent_name, unsigned long flags, 117 unsigned long fixed_rate) 118 { 119 return clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name, 120 flags, fixed_rate, 0); 121 } 122 EXPORT_SYMBOL_GPL(clk_hw_register_fixed_rate); 123 124 struct clk *clk_register_fixed_rate(struct device *dev, const char *name, 125 const char *parent_name, unsigned long flags, 126 unsigned long fixed_rate) 127 { 128 return clk_register_fixed_rate_with_accuracy(dev, name, parent_name, 129 flags, fixed_rate, 0); 130 } 131 EXPORT_SYMBOL_GPL(clk_register_fixed_rate); 132 133 void clk_unregister_fixed_rate(struct clk *clk) 134 { 135 struct clk_hw *hw; 136 137 hw = __clk_get_hw(clk); 138 if (!hw) 139 return; 140 141 clk_unregister(clk); 142 kfree(to_clk_fixed_rate(hw)); 143 } 144 EXPORT_SYMBOL_GPL(clk_unregister_fixed_rate); 145 146 void clk_hw_unregister_fixed_rate(struct clk_hw *hw) 147 { 148 struct clk_fixed_rate *fixed; 149 150 fixed = to_clk_fixed_rate(hw); 151 152 clk_hw_unregister(hw); 153 kfree(fixed); 154 } 155 EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_rate); 156 157 #ifdef CONFIG_OF 158 static struct clk *_of_fixed_clk_setup(struct device_node *node) 159 { 160 struct clk *clk; 161 const char *clk_name = node->name; 162 u32 rate; 163 u32 accuracy = 0; 164 int ret; 165 166 if (of_property_read_u32(node, "clock-frequency", &rate)) 167 return ERR_PTR(-EIO); 168 169 of_property_read_u32(node, "clock-accuracy", &accuracy); 170 171 of_property_read_string(node, "clock-output-names", &clk_name); 172 173 clk = clk_register_fixed_rate_with_accuracy(NULL, clk_name, NULL, 174 0, rate, accuracy); 175 if (IS_ERR(clk)) 176 return clk; 177 178 ret = of_clk_add_provider(node, of_clk_src_simple_get, clk); 179 if (ret) { 180 clk_unregister(clk); 181 return ERR_PTR(ret); 182 } 183 184 return clk; 185 } 186 187 /** 188 * of_fixed_clk_setup() - Setup function for simple fixed rate clock 189 */ 190 void __init of_fixed_clk_setup(struct device_node *node) 191 { 192 _of_fixed_clk_setup(node); 193 } 194 CLK_OF_DECLARE(fixed_clk, "fixed-clock", of_fixed_clk_setup); 195 196 static int of_fixed_clk_remove(struct platform_device *pdev) 197 { 198 struct clk *clk = platform_get_drvdata(pdev); 199 200 of_clk_del_provider(pdev->dev.of_node); 201 clk_unregister_fixed_rate(clk); 202 203 return 0; 204 } 205 206 static int of_fixed_clk_probe(struct platform_device *pdev) 207 { 208 struct clk *clk; 209 210 /* 211 * This function is not executed when of_fixed_clk_setup 212 * succeeded. 213 */ 214 clk = _of_fixed_clk_setup(pdev->dev.of_node); 215 if (IS_ERR(clk)) 216 return PTR_ERR(clk); 217 218 platform_set_drvdata(pdev, clk); 219 220 return 0; 221 } 222 223 static const struct of_device_id of_fixed_clk_ids[] = { 224 { .compatible = "fixed-clock" }, 225 { } 226 }; 227 MODULE_DEVICE_TABLE(of, of_fixed_clk_ids); 228 229 static struct platform_driver of_fixed_clk_driver = { 230 .driver = { 231 .name = "of_fixed_clk", 232 .of_match_table = of_fixed_clk_ids, 233 }, 234 .probe = of_fixed_clk_probe, 235 .remove = of_fixed_clk_remove, 236 }; 237 builtin_platform_driver(of_fixed_clk_driver); 238 #endif 239