1 /* 2 * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 * 8 * Standard functionality for the common clock API. 9 */ 10 #include <linux/module.h> 11 #include <linux/clk-provider.h> 12 #include <linux/slab.h> 13 #include <linux/err.h> 14 #include <linux/of.h> 15 16 /* 17 * DOC: basic fixed multiplier and divider clock that cannot gate 18 * 19 * Traits of this clock: 20 * prepare - clk_prepare only ensures that parents are prepared 21 * enable - clk_enable only ensures that parents are enabled 22 * rate - rate is fixed. clk->rate = parent->rate / div * mult 23 * parent - fixed parent. No clk_set_parent support 24 */ 25 26 #define to_clk_fixed_factor(_hw) container_of(_hw, struct clk_fixed_factor, hw) 27 28 static unsigned long clk_factor_recalc_rate(struct clk_hw *hw, 29 unsigned long parent_rate) 30 { 31 struct clk_fixed_factor *fix = to_clk_fixed_factor(hw); 32 unsigned long long int rate; 33 34 rate = (unsigned long long int)parent_rate * fix->mult; 35 do_div(rate, fix->div); 36 return (unsigned long)rate; 37 } 38 39 static long clk_factor_round_rate(struct clk_hw *hw, unsigned long rate, 40 unsigned long *prate) 41 { 42 struct clk_fixed_factor *fix = to_clk_fixed_factor(hw); 43 44 if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) { 45 unsigned long best_parent; 46 47 best_parent = (rate / fix->mult) * fix->div; 48 *prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent); 49 } 50 51 return (*prate / fix->div) * fix->mult; 52 } 53 54 static int clk_factor_set_rate(struct clk_hw *hw, unsigned long rate, 55 unsigned long parent_rate) 56 { 57 /* 58 * We must report success but we can do so unconditionally because 59 * clk_factor_round_rate returns values that ensure this call is a 60 * nop. 61 */ 62 63 return 0; 64 } 65 66 const struct clk_ops clk_fixed_factor_ops = { 67 .round_rate = clk_factor_round_rate, 68 .set_rate = clk_factor_set_rate, 69 .recalc_rate = clk_factor_recalc_rate, 70 }; 71 EXPORT_SYMBOL_GPL(clk_fixed_factor_ops); 72 73 struct clk *clk_register_fixed_factor(struct device *dev, const char *name, 74 const char *parent_name, unsigned long flags, 75 unsigned int mult, unsigned int div) 76 { 77 struct clk_fixed_factor *fix; 78 struct clk_init_data init; 79 struct clk *clk; 80 81 fix = kmalloc(sizeof(*fix), GFP_KERNEL); 82 if (!fix) 83 return ERR_PTR(-ENOMEM); 84 85 /* struct clk_fixed_factor assignments */ 86 fix->mult = mult; 87 fix->div = div; 88 fix->hw.init = &init; 89 90 init.name = name; 91 init.ops = &clk_fixed_factor_ops; 92 init.flags = flags | CLK_IS_BASIC; 93 init.parent_names = &parent_name; 94 init.num_parents = 1; 95 96 clk = clk_register(dev, &fix->hw); 97 98 if (IS_ERR(clk)) 99 kfree(fix); 100 101 return clk; 102 } 103 EXPORT_SYMBOL_GPL(clk_register_fixed_factor); 104 105 #ifdef CONFIG_OF 106 /** 107 * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock 108 */ 109 void __init of_fixed_factor_clk_setup(struct device_node *node) 110 { 111 struct clk *clk; 112 const char *clk_name = node->name; 113 const char *parent_name; 114 u32 div, mult; 115 116 if (of_property_read_u32(node, "clock-div", &div)) { 117 pr_err("%s Fixed factor clock <%s> must have a clock-div property\n", 118 __func__, node->name); 119 return; 120 } 121 122 if (of_property_read_u32(node, "clock-mult", &mult)) { 123 pr_err("%s Fixed factor clock <%s> must have a clock-mult property\n", 124 __func__, node->name); 125 return; 126 } 127 128 of_property_read_string(node, "clock-output-names", &clk_name); 129 parent_name = of_clk_get_parent_name(node, 0); 130 131 clk = clk_register_fixed_factor(NULL, clk_name, parent_name, 0, 132 mult, div); 133 if (!IS_ERR(clk)) 134 of_clk_add_provider(node, of_clk_src_simple_get, clk); 135 } 136 EXPORT_SYMBOL_GPL(of_fixed_factor_clk_setup); 137 CLK_OF_DECLARE(fixed_factor_clk, "fixed-factor-clock", 138 of_fixed_factor_clk_setup); 139 #endif 140