Root/
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 | |
15 | /* |
16 | * DOC: basic fixed multiplier and divider clock that cannot gate |
17 | * |
18 | * Traits of this clock: |
19 | * prepare - clk_prepare only ensures that parents are prepared |
20 | * enable - clk_enable only ensures that parents are enabled |
21 | * rate - rate is fixed. clk->rate = parent->rate / div * mult |
22 | * parent - fixed parent. No clk_set_parent support |
23 | */ |
24 | |
25 | #define to_clk_fixed_factor(_hw) container_of(_hw, struct clk_fixed_factor, hw) |
26 | |
27 | static unsigned long clk_factor_recalc_rate(struct clk_hw *hw, |
28 | unsigned long parent_rate) |
29 | { |
30 | struct clk_fixed_factor *fix = to_clk_fixed_factor(hw); |
31 | unsigned long long int rate; |
32 | |
33 | rate = (unsigned long long int)parent_rate * fix->mult; |
34 | do_div(rate, fix->div); |
35 | return (unsigned long)rate; |
36 | } |
37 | |
38 | static long clk_factor_round_rate(struct clk_hw *hw, unsigned long rate, |
39 | unsigned long *prate) |
40 | { |
41 | struct clk_fixed_factor *fix = to_clk_fixed_factor(hw); |
42 | |
43 | if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) { |
44 | unsigned long best_parent; |
45 | |
46 | best_parent = (rate / fix->mult) * fix->div; |
47 | *prate = __clk_round_rate(__clk_get_parent(hw->clk), |
48 | 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 | return 0; |
58 | } |
59 | |
60 | struct clk_ops clk_fixed_factor_ops = { |
61 | .round_rate = clk_factor_round_rate, |
62 | .set_rate = clk_factor_set_rate, |
63 | .recalc_rate = clk_factor_recalc_rate, |
64 | }; |
65 | EXPORT_SYMBOL_GPL(clk_fixed_factor_ops); |
66 | |
67 | struct clk *clk_register_fixed_factor(struct device *dev, const char *name, |
68 | const char *parent_name, unsigned long flags, |
69 | unsigned int mult, unsigned int div) |
70 | { |
71 | struct clk_fixed_factor *fix; |
72 | struct clk_init_data init; |
73 | struct clk *clk; |
74 | |
75 | fix = kmalloc(sizeof(*fix), GFP_KERNEL); |
76 | if (!fix) { |
77 | pr_err("%s: could not allocate fixed factor clk\n", __func__); |
78 | return ERR_PTR(-ENOMEM); |
79 | } |
80 | |
81 | /* struct clk_fixed_factor assignments */ |
82 | fix->mult = mult; |
83 | fix->div = div; |
84 | fix->hw.init = &init; |
85 | |
86 | init.name = name; |
87 | init.ops = &clk_fixed_factor_ops; |
88 | init.flags = flags | CLK_IS_BASIC; |
89 | init.parent_names = &parent_name; |
90 | init.num_parents = 1; |
91 | |
92 | clk = clk_register(dev, &fix->hw); |
93 | |
94 | if (IS_ERR(clk)) |
95 | kfree(fix); |
96 | |
97 | return clk; |
98 | } |
99 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9