Branch data Line data Source code
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 : 3 : static unsigned long clk_fixed_rate_recalc_rate(struct clk_hw *hw, 28 : : unsigned long parent_rate) 29 : : { 30 : 3 : return to_clk_fixed_rate(hw)->fixed_rate; 31 : : } 32 : : 33 : 3 : static unsigned long clk_fixed_rate_recalc_accuracy(struct clk_hw *hw, 34 : : unsigned long parent_accuracy) 35 : : { 36 : 3 : 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 : 3 : 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 : 3 : fixed = kzalloc(sizeof(*fixed), GFP_KERNEL); 66 : 3 : if (!fixed) 67 : : return ERR_PTR(-ENOMEM); 68 : : 69 : 3 : init.name = name; 70 : 3 : init.ops = &clk_fixed_rate_ops; 71 : 3 : init.flags = flags; 72 : 3 : init.parent_names = (parent_name ? &parent_name: NULL); 73 : 3 : init.num_parents = (parent_name ? 1 : 0); 74 : : 75 : : /* struct clk_fixed_rate assignments */ 76 : 3 : fixed->fixed_rate = fixed_rate; 77 : 3 : fixed->fixed_accuracy = fixed_accuracy; 78 : 3 : fixed->hw.init = &init; 79 : : 80 : : /* register the clock */ 81 : 3 : hw = &fixed->hw; 82 : 3 : ret = clk_hw_register(dev, hw); 83 : 3 : if (ret) { 84 : 0 : kfree(fixed); 85 : : hw = ERR_PTR(ret); 86 : : } 87 : : 88 : 3 : return hw; 89 : : } 90 : : EXPORT_SYMBOL_GPL(clk_hw_register_fixed_rate_with_accuracy); 91 : : 92 : 0 : 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 : 3 : hw = clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name, 99 : : flags, fixed_rate, fixed_accuracy); 100 : 3 : if (IS_ERR(hw)) 101 : : return ERR_CAST(hw); 102 : 3 : 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 : 0 : 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 : 0 : 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 : 0 : 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 : 0 : 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 : 0 : void clk_unregister_fixed_rate(struct clk *clk) 134 : : { 135 : : struct clk_hw *hw; 136 : : 137 : 0 : hw = __clk_get_hw(clk); 138 : 0 : if (!hw) 139 : 0 : return; 140 : : 141 : 0 : clk_unregister(clk); 142 : 0 : kfree(to_clk_fixed_rate(hw)); 143 : : } 144 : : EXPORT_SYMBOL_GPL(clk_unregister_fixed_rate); 145 : : 146 : 0 : 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 : 0 : clk_hw_unregister(hw); 153 : 0 : kfree(fixed); 154 : 0 : } 155 : : EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_rate); 156 : : 157 : : #ifdef CONFIG_OF 158 : 3 : static struct clk *_of_fixed_clk_setup(struct device_node *node) 159 : : { 160 : : struct clk *clk; 161 : 3 : const char *clk_name = node->name; 162 : : u32 rate; 163 : 3 : u32 accuracy = 0; 164 : : int ret; 165 : : 166 : 3 : 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 : 3 : of_property_read_string(node, "clock-output-names", &clk_name); 172 : : 173 : 3 : clk = clk_register_fixed_rate_with_accuracy(NULL, clk_name, NULL, 174 : : 0, rate, accuracy); 175 : 3 : if (IS_ERR(clk)) 176 : : return clk; 177 : : 178 : 3 : ret = of_clk_add_provider(node, of_clk_src_simple_get, clk); 179 : 3 : if (ret) { 180 : 0 : clk_unregister(clk); 181 : 0 : 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 : 3 : void __init of_fixed_clk_setup(struct device_node *node) 191 : : { 192 : 3 : _of_fixed_clk_setup(node); 193 : 3 : } 194 : : CLK_OF_DECLARE(fixed_clk, "fixed-clock", of_fixed_clk_setup); 195 : : 196 : 0 : static int of_fixed_clk_remove(struct platform_device *pdev) 197 : : { 198 : : struct clk *clk = platform_get_drvdata(pdev); 199 : : 200 : 0 : of_clk_del_provider(pdev->dev.of_node); 201 : 0 : clk_unregister_fixed_rate(clk); 202 : : 203 : 0 : return 0; 204 : : } 205 : : 206 : 0 : 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 : 0 : clk = _of_fixed_clk_setup(pdev->dev.of_node); 215 : 0 : if (IS_ERR(clk)) 216 : 0 : return PTR_ERR(clk); 217 : : 218 : : platform_set_drvdata(pdev, clk); 219 : : 220 : 0 : 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 : 3 : builtin_platform_driver(of_fixed_clk_driver); 238 : : #endif