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

clk: fixed-factor: Convert into a module platform driver

Adds support for fixed-factor clock providers which have not been
enabled via of_clk_init().

This is required by Device trees overlays that introduce clocks
providers.

Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
[sboyd@codeaurora.org: Make new private function static, don't
check clk for NULL when unregistering in driver remove]
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>

authored by

Ricardo Ribalda Delgado and committed by
Stephen Boyd
971451b3 989eafd0

+65 -8
+65 -8
drivers/clk/clk-fixed-factor.c
··· 12 12 #include <linux/slab.h> 13 13 #include <linux/err.h> 14 14 #include <linux/of.h> 15 + #include <linux/platform_device.h> 15 16 16 17 /* 17 18 * DOC: basic fixed multiplier and divider clock that cannot gate ··· 148 147 { /* Sentinel */ }, 149 148 }; 150 149 151 - /** 152 - * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock 153 - */ 154 - void __init of_fixed_factor_clk_setup(struct device_node *node) 150 + static struct clk *_of_fixed_factor_clk_setup(struct device_node *node) 155 151 { 156 152 struct clk *clk; 157 153 const char *clk_name = node->name; 158 154 const char *parent_name; 159 155 unsigned long flags = 0; 160 156 u32 div, mult; 157 + int ret; 161 158 162 159 if (of_property_read_u32(node, "clock-div", &div)) { 163 160 pr_err("%s Fixed factor clock <%s> must have a clock-div property\n", 164 161 __func__, node->name); 165 - return; 162 + return ERR_PTR(-EIO); 166 163 } 167 164 168 165 if (of_property_read_u32(node, "clock-mult", &mult)) { 169 166 pr_err("%s Fixed factor clock <%s> must have a clock-mult property\n", 170 167 __func__, node->name); 171 - return; 168 + return ERR_PTR(-EIO); 172 169 } 173 170 174 171 of_property_read_string(node, "clock-output-names", &clk_name); ··· 177 178 178 179 clk = clk_register_fixed_factor(NULL, clk_name, parent_name, flags, 179 180 mult, div); 180 - if (!IS_ERR(clk)) 181 - of_clk_add_provider(node, of_clk_src_simple_get, clk); 181 + if (IS_ERR(clk)) 182 + return clk; 183 + 184 + ret = of_clk_add_provider(node, of_clk_src_simple_get, clk); 185 + if (ret) { 186 + clk_unregister(clk); 187 + return ERR_PTR(ret); 188 + } 189 + 190 + return clk; 191 + } 192 + 193 + /** 194 + * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock 195 + */ 196 + void __init of_fixed_factor_clk_setup(struct device_node *node) 197 + { 198 + _of_fixed_factor_clk_setup(node); 182 199 } 183 200 EXPORT_SYMBOL_GPL(of_fixed_factor_clk_setup); 184 201 CLK_OF_DECLARE(fixed_factor_clk, "fixed-factor-clock", 185 202 of_fixed_factor_clk_setup); 203 + 204 + static int of_fixed_factor_clk_remove(struct platform_device *pdev) 205 + { 206 + struct clk *clk = platform_get_drvdata(pdev); 207 + 208 + clk_unregister_fixed_factor(clk); 209 + 210 + return 0; 211 + } 212 + 213 + static int of_fixed_factor_clk_probe(struct platform_device *pdev) 214 + { 215 + struct clk *clk; 216 + 217 + /* 218 + * This function is not executed when of_fixed_factor_clk_setup 219 + * succeeded. 220 + */ 221 + clk = _of_fixed_factor_clk_setup(pdev->dev.of_node); 222 + if (IS_ERR(clk)) 223 + return PTR_ERR(clk); 224 + 225 + platform_set_drvdata(pdev, clk); 226 + 227 + return 0; 228 + } 229 + 230 + static const struct of_device_id of_fixed_factor_clk_ids[] = { 231 + { .compatible = "fixed-factor-clock" }, 232 + { } 233 + }; 234 + MODULE_DEVICE_TABLE(of, of_fixed_factor_clk_ids); 235 + 236 + static struct platform_driver of_fixed_factor_clk_driver = { 237 + .driver = { 238 + .name = "of_fixed_factor_clk", 239 + .of_match_table = of_fixed_factor_clk_ids, 240 + }, 241 + .probe = of_fixed_factor_clk_probe, 242 + .remove = of_fixed_factor_clk_remove, 243 + }; 244 + builtin_platform_driver(of_fixed_factor_clk_driver); 186 245 #endif