aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
authorTero Kristo <t-kristo@ti.com>2013-09-13 05:02:15 -0400
committerMike Turquette <mturquette@linaro.org>2014-01-17 15:35:04 -0500
commitb4761198bfaf29649dc58a48e8b123ea4174ba95 (patch)
tree7c350ec98d991e2e6035a6e0098002d28ea3223c /drivers/clk
parent975e15487d5abfd5f33fea9c1ba0b987604f0d0f (diff)
CLK: ti: add support for ti divider-clock
This patch adds support for TI divider clock binding, which simply uses the basic clock divider to provide the features needed. Signed-off-by: Tero Kristo <t-kristo@ti.com> Acked-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Mike Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/ti/Makefile2
-rw-r--r--drivers/clk/ti/composite.c2
-rw-r--r--drivers/clk/ti/divider.c487
3 files changed, 489 insertions, 2 deletions
diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile
index ac4ea50672ed..8690b0b442c0 100644
--- a/drivers/clk/ti/Makefile
+++ b/drivers/clk/ti/Makefile
@@ -1,4 +1,4 @@
1ifneq ($(CONFIG_OF),) 1ifneq ($(CONFIG_OF),)
2obj-y += clk.o autoidle.o 2obj-y += clk.o autoidle.o
3clk-common = dpll.o composite.o 3clk-common = dpll.o composite.o divider.o
4endif 4endif
diff --git a/drivers/clk/ti/composite.c b/drivers/clk/ti/composite.c
index 6539b650cae0..ffb8db4829bf 100644
--- a/drivers/clk/ti/composite.c
+++ b/drivers/clk/ti/composite.c
@@ -31,7 +31,7 @@
31static unsigned long ti_composite_recalc_rate(struct clk_hw *hw, 31static unsigned long ti_composite_recalc_rate(struct clk_hw *hw,
32 unsigned long parent_rate) 32 unsigned long parent_rate)
33{ 33{
34 return clk_divider_ops.recalc_rate(hw, parent_rate); 34 return ti_clk_divider_ops.recalc_rate(hw, parent_rate);
35} 35}
36 36
37static long ti_composite_round_rate(struct clk_hw *hw, unsigned long rate, 37static long ti_composite_round_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
new file mode 100644
index 000000000000..a15e445570b2
--- /dev/null
+++ b/drivers/clk/ti/divider.c
@@ -0,0 +1,487 @@
1/*
2 * TI Divider Clock
3 *
4 * Copyright (C) 2013 Texas Instruments, Inc.
5 *
6 * Tero Kristo <t-kristo@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
13 * kind, whether express or implied; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/clk-provider.h>
19#include <linux/slab.h>
20#include <linux/err.h>
21#include <linux/of.h>
22#include <linux/of_address.h>
23#include <linux/clk/ti.h>
24
25#undef pr_fmt
26#define pr_fmt(fmt) "%s: " fmt, __func__
27
28#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
29
30#define div_mask(d) ((1 << ((d)->width)) - 1)
31
32static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
33{
34 unsigned int maxdiv = 0;
35 const struct clk_div_table *clkt;
36
37 for (clkt = table; clkt->div; clkt++)
38 if (clkt->div > maxdiv)
39 maxdiv = clkt->div;
40 return maxdiv;
41}
42
43static unsigned int _get_maxdiv(struct clk_divider *divider)
44{
45 if (divider->flags & CLK_DIVIDER_ONE_BASED)
46 return div_mask(divider);
47 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
48 return 1 << div_mask(divider);
49 if (divider->table)
50 return _get_table_maxdiv(divider->table);
51 return div_mask(divider) + 1;
52}
53
54static unsigned int _get_table_div(const struct clk_div_table *table,
55 unsigned int val)
56{
57 const struct clk_div_table *clkt;
58
59 for (clkt = table; clkt->div; clkt++)
60 if (clkt->val == val)
61 return clkt->div;
62 return 0;
63}
64
65static unsigned int _get_div(struct clk_divider *divider, unsigned int val)
66{
67 if (divider->flags & CLK_DIVIDER_ONE_BASED)
68 return val;
69 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
70 return 1 << val;
71 if (divider->table)
72 return _get_table_div(divider->table, val);
73 return val + 1;
74}
75
76static unsigned int _get_table_val(const struct clk_div_table *table,
77 unsigned int div)
78{
79 const struct clk_div_table *clkt;
80
81 for (clkt = table; clkt->div; clkt++)
82 if (clkt->div == div)
83 return clkt->val;
84 return 0;
85}
86
87static unsigned int _get_val(struct clk_divider *divider, u8 div)
88{
89 if (divider->flags & CLK_DIVIDER_ONE_BASED)
90 return div;
91 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
92 return __ffs(div);
93 if (divider->table)
94 return _get_table_val(divider->table, div);
95 return div - 1;
96}
97
98static unsigned long ti_clk_divider_recalc_rate(struct clk_hw *hw,
99 unsigned long parent_rate)
100{
101 struct clk_divider *divider = to_clk_divider(hw);
102 unsigned int div, val;
103
104 val = ti_clk_ll_ops->clk_readl(divider->reg) >> divider->shift;
105 val &= div_mask(divider);
106
107 div = _get_div(divider, val);
108 if (!div) {
109 WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO),
110 "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
111 __clk_get_name(hw->clk));
112 return parent_rate;
113 }
114
115 return parent_rate / div;
116}
117
118/*
119 * The reverse of DIV_ROUND_UP: The maximum number which
120 * divided by m is r
121 */
122#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
123
124static bool _is_valid_table_div(const struct clk_div_table *table,
125 unsigned int div)
126{
127 const struct clk_div_table *clkt;
128
129 for (clkt = table; clkt->div; clkt++)
130 if (clkt->div == div)
131 return true;
132 return false;
133}
134
135static bool _is_valid_div(struct clk_divider *divider, unsigned int div)
136{
137 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
138 return is_power_of_2(div);
139 if (divider->table)
140 return _is_valid_table_div(divider->table, div);
141 return true;
142}
143
144static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
145 unsigned long *best_parent_rate)
146{
147 struct clk_divider *divider = to_clk_divider(hw);
148 int i, bestdiv = 0;
149 unsigned long parent_rate, best = 0, now, maxdiv;
150 unsigned long parent_rate_saved = *best_parent_rate;
151
152 if (!rate)
153 rate = 1;
154
155 maxdiv = _get_maxdiv(divider);
156
157 if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
158 parent_rate = *best_parent_rate;
159 bestdiv = DIV_ROUND_UP(parent_rate, rate);
160 bestdiv = bestdiv == 0 ? 1 : bestdiv;
161 bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
162 return bestdiv;
163 }
164
165 /*
166 * The maximum divider we can use without overflowing
167 * unsigned long in rate * i below
168 */
169 maxdiv = min(ULONG_MAX / rate, maxdiv);
170
171 for (i = 1; i <= maxdiv; i++) {
172 if (!_is_valid_div(divider, i))