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_get_flags(hw->clk) & CLK_SET_RATE_PARENT) { 45 unsigned long best_parent; 46 47 best_parent = (rate / fix->mult) * fix->div; 48 *prate = __clk_round_rate(__clk_get_parent(hw->clk), 49 best_parent); 50 } 51 52 return (*prate / fix->div) * fix->mult; 53 } 54 55 static int clk_factor_set_rate(struct clk_hw *hw, unsigned long rate, 56 unsigned long parent_rate) 57 { 58 return 0; 59 } 60 61 struct clk_ops clk_fixed_factor_ops = { 62 .round_rate = clk_factor_round_rate, 63 .set_rate = clk_factor_set_rate, 64 .recalc_rate = clk_factor_recalc_rate, 65 }; 66 EXPORT_SYMBOL_GPL(clk_fixed_factor_ops); 67 68 struct clk *clk_register_fixed_factor(struct device *dev, const char *name, 69 const char *parent_name, unsigned long flags, 70 unsigned int mult, unsigned int div) 71 { 72 struct clk_fixed_factor *fix; 73 struct clk_init_data init; 74 struct clk *clk; 75 76 fix = kmalloc(sizeof(*fix), GFP_KERNEL); 77 if (!fix) { 78 pr_err("%s: could not allocate fixed factor clk\n", __func__); 79 return ERR_PTR(-ENOMEM); 80 } 81 82 /* struct clk_fixed_factor assignments */ 83 fix->mult = mult; 84 fix->div = div; 85 fix->hw.init = &init; 86 87 init.name = name; 88 init.ops = &clk_fixed_factor_ops; 89 init.flags = flags | CLK_IS_BASIC; 90 init.parent_names = &parent_name; 91 init.num_parents = 1; 92 93 clk = clk_register(dev, &fix->hw); 94 95 if (IS_ERR(clk)) 96 kfree(fix); 97 98 return clk; 99 } 100 #ifdef CONFIG_OF 101 /** 102 * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock 103 */ 104 void __init of_fixed_factor_clk_setup(struct device_node *node) 105 { 106 struct clk *clk; 107 const char *clk_name = node->name; 108 const char *parent_name; 109 u32 div, mult; 110 111 if (of_property_read_u32(node, "clock-div", &div)) { 112 pr_err("%s Fixed factor clock <%s> must have a clock-div property\n", 113 __func__, node->name); 114 return; 115 } 116 117 if (of_property_read_u32(node, "clock-mult", &mult)) { 118 pr_err("%s Fixed factor clock <%s> must have a clokc-mult property\n", 119 __func__, node->name); 120 return; 121 } 122 123 of_property_read_string(node, "clock-output-names", &clk_name); 124 parent_name = of_clk_get_parent_name(node, 0); 125 126 clk = clk_register_fixed_factor(NULL, clk_name, parent_name, 0, 127 mult, div); 128 if (!IS_ERR(clk)) 129 of_clk_add_provider(node, of_clk_src_simple_get, clk); 130 } 131 EXPORT_SYMBOL_GPL(of_fixed_factor_clk_setup); 132 CLK_OF_DECLARE(fixed_factor_clk, "fixed-factor-clock", 133 of_fixed_factor_clk_setup); 134 #endif 135