aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/Kconfig7
-rw-r--r--drivers/clk/Makefile8
-rw-r--r--drivers/clk/clk-divider.c189
-rw-r--r--drivers/clk/clk-fixed-factor.c2
-rw-r--r--drivers/clk/clk-fixed-rate.c25
-rw-r--r--drivers/clk/clk-gate.c2
-rw-r--r--drivers/clk/clk-highbank.c346
-rw-r--r--drivers/clk/clk-mux.c2
-rw-r--r--drivers/clk/clk-u300.c746
-rw-r--r--drivers/clk/clk-wm831x.c428
-rw-r--r--drivers/clk/clk.c182
-rw-r--r--drivers/clk/clkdev.c77
-rw-r--r--drivers/clk/mxs/clk-imx23.c12
-rw-r--r--drivers/clk/mxs/clk-imx28.c32
-rw-r--r--drivers/clk/spear/clk-aux-synth.c2
-rw-r--r--drivers/clk/spear/clk-frac-synth.c2
-rw-r--r--drivers/clk/spear/clk-gpt-synth.c2
-rw-r--r--drivers/clk/spear/clk-vco-pll.c2
-rw-r--r--drivers/clk/spear/clk.c2
-rw-r--r--drivers/clk/spear/clk.h2
-rw-r--r--drivers/clk/spear/spear1310_clock.c2
-rw-r--r--drivers/clk/spear/spear1340_clock.c2
-rw-r--r--drivers/clk/spear/spear3xx_clock.c2
-rw-r--r--drivers/clk/spear/spear6xx_clock.c4
-rw-r--r--drivers/clk/versatile/Makefile3
-rw-r--r--drivers/clk/versatile/clk-icst.c100
-rw-r--r--drivers/clk/versatile/clk-icst.h10
-rw-r--r--drivers/clk/versatile/clk-integrator.c111
28 files changed, 2214 insertions, 90 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 4864407e3fc4..3f99b9099658 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -34,4 +34,11 @@ config COMMON_CLK_DEBUG
34 clk_flags, clk_prepare_count, clk_enable_count & 34 clk_flags, clk_prepare_count, clk_enable_count &
35 clk_notifier_count. 35 clk_notifier_count.
36 36
37config COMMON_CLK_WM831X
38 tristate "Clock driver for WM831x/2x PMICs"
39 depends on MFD_WM831X
40 ---help---
41 Supports the clocking subsystem of the WM831x/2x series of
42 PMICs from Wolfson Microlectronics.
43
37endmenu 44endmenu
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index b9a5158a30b1..02ffdf647b5e 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,7 +1,13 @@
1 1# common clock types
2obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o 2obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o
3obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \ 3obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \
4 clk-mux.o clk-divider.o clk-fixed-factor.o 4 clk-mux.o clk-divider.o clk-fixed-factor.o
5# SoCs specific 5# SoCs specific
6obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
6obj-$(CONFIG_ARCH_MXS) += mxs/ 7obj-$(CONFIG_ARCH_MXS) += mxs/
7obj-$(CONFIG_PLAT_SPEAR) += spear/ 8obj-$(CONFIG_PLAT_SPEAR) += spear/
9obj-$(CONFIG_ARCH_U300) += clk-u300.o
10obj-$(CONFIG_ARCH_INTEGRATOR) += versatile/
11
12# Chip specific
13obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 8ea11b444528..a9204c69148d 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -30,18 +30,89 @@
30#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw) 30#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
31 31
32#define div_mask(d) ((1 << (d->width)) - 1) 32#define div_mask(d) ((1 << (d->width)) - 1)
33#define is_power_of_two(i) !(i & ~i)
34
35static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
36{
37 unsigned int maxdiv = 0;
38 const struct clk_div_table *clkt;
39
40 for (clkt = table; clkt->div; clkt++)
41 if (clkt->div > maxdiv)
42 maxdiv = clkt->div;
43 return maxdiv;
44}
45
46static unsigned int _get_maxdiv(struct clk_divider *divider)
47{
48 if (divider->flags & CLK_DIVIDER_ONE_BASED)
49 return div_mask(divider);
50 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
51 return 1 << div_mask(divider);
52 if (divider->table)
53 return _get_table_maxdiv(divider->table);
54 return div_mask(divider) + 1;
55}
56
57static unsigned int _get_table_div(const struct clk_div_table *table,
58 unsigned int val)
59{
60 const struct clk_div_table *clkt;
61
62 for (clkt = table; clkt->div; clkt++)
63 if (clkt->val == val)
64 return clkt->div;
65 return 0;
66}
67
68static unsigned int _get_div(struct clk_divider *divider, unsigned int val)
69{
70 if (divider->flags & CLK_DIVIDER_ONE_BASED)
71 return val;
72 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
73 return 1 << val;
74 if (divider->table)
75 return _get_table_div(divider->table, val);
76 return val + 1;
77}
78
79static unsigned int _get_table_val(const struct clk_div_table *table,
80 unsigned int div)
81{
82 const struct clk_div_table *clkt;
83
84 for (clkt = table; clkt->div; clkt++)
85 if (clkt->div == div)
86 return clkt->val;
87 return 0;
88}
89
90static unsigned int _get_val(struct clk_divider *divider, u8 div)
91{
92 if (divider->flags & CLK_DIVIDER_ONE_BASED)
93 return div;
94 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
95 return __ffs(div);
96 if (divider->table)
97 return _get_table_val(divider->table, div);
98 return div - 1;
99}
33 100
34static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, 101static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
35 unsigned long parent_rate) 102 unsigned long parent_rate)
36{ 103{
37 struct clk_divider *divider = to_clk_divider(hw); 104 struct clk_divider *divider = to_clk_divider(hw);
38 unsigned int div; 105 unsigned int div, val;
39 106
40 div = readl(divider->reg) >> divider->shift; 107 val = readl(divider->reg) >> divider->shift;
41 div &= div_mask(divider); 108 val &= div_mask(divider);
42 109
43 if (!(divider->flags & CLK_DIVIDER_ONE_BASED)) 110 div = _get_div(divider, val);
44 div++; 111 if (!div) {
112 WARN(1, "%s: Invalid divisor for clock %s\n", __func__,
113 __clk_get_name(hw->clk));
114 return parent_rate;
115 }
45 116
46 return parent_rate / div; 117 return parent_rate / div;
47} 118}
@@ -52,6 +123,26 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
52 */ 123 */
53#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1) 124#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
54 125
126static bool _is_valid_table_div(const struct clk_div_table *table,
127 unsigned int div)
128{
129 const struct clk_div_table *clkt;
130
131 for (clkt = table; clkt->div; clkt++)
132 if (clkt->div == div)
133 return true;
134 return false;
135}
136
137static bool _is_valid_div(struct clk_divider *divider, unsigned int div)
138{
139 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
140 return is_power_of_two(div);
141 if (divider->table)
142 return _is_valid_table_div(divider->table, div);
143 return true;
144}
145
55static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, 146static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
56 unsigned long *best_parent_rate) 147 unsigned long *best_parent_rate)
57{ 148{
@@ -62,10 +153,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
62 if (!rate) 153 if (!rate)
63 rate = 1; 154 rate = 1;
64 155
65 maxdiv = (1 << divider->width); 156 maxdiv = _get_maxdiv(divider);
66
67 if (divider->flags & CLK_DIVIDER_ONE_BASED)
68 maxdiv--;
69 157
70 if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) { 158 if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
71 parent_rate = *best_parent_rate; 159 parent_rate = *best_parent_rate;
@@ -82,6 +170,8 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
82 maxdiv = min(ULONG_MAX / rate, maxdiv); 170 maxdiv = min(ULONG_MAX / rate, maxdiv);
83 171
84 for (i = 1; i <= maxdiv; i++) { 172 for (i = 1; i <= maxdiv; i++) {
173 if (!_is_valid_div(divider, i))
174 continue;
85 parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 175 parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
86 MULT_ROUND_UP(rate, i)); 176 MULT_ROUND_UP(rate, i));
87 now = parent_rate / i; 177 now = parent_rate / i;
@@ -93,9 +183,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
93 } 183 }
94 184
95 if (!bestdiv) { 185 if (!bestdiv) {
96 bestdiv = (1 << divider->width); 186 bestdiv = _get_maxdiv(divider);
97 if (divider->flags & CLK_DIVIDER_ONE_BASED)
98 bestdiv--;
99 *best_parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 1); 187 *best_parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 1);
100 } 188 }
101 189
@@ -115,24 +203,22 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
115 unsigned long parent_rate) 203 unsigned long parent_rate)
116{ 204{
117 struct clk_divider *divider = to_clk_divider(hw); 205 struct clk_divider *divider = to_clk_divider(hw);
118 unsigned int div; 206 unsigned int div, value;
119 unsigned long flags = 0; 207 unsigned long flags = 0;
120 u32 val; 208 u32 val;
121 209
122 div = parent_rate / rate; 210 div = parent_rate / rate;
211 value = _get_val(divider, div);
123 212
124 if (!(divider->flags & CLK_DIVIDER_ONE_BASED)) 213 if (value > div_mask(divider))
125 div--; 214 value = div_mask(divider);
126
127 if (div > div_mask(divider))
128 div = div_mask(divider);
129 215
130 if (divider->lock) 216 if (divider->lock)
131 spin_lock_irqsave(divider->lock, flags); 217 spin_lock_irqsave(divider->lock, flags);
132 218
133 val = readl(divider->reg); 219 val = readl(divider->reg);
134 val &= ~(div_mask(divider) << divider->shift); 220 val &= ~(div_mask(divider) << divider->shift);
135 val |= div << divider->shift; 221 val |= value << divider->shift;
136 writel(val, divider->reg); 222 writel(val, divider->reg);
137 223
138 if (divider->lock) 224 if (divider->lock)
@@ -148,22 +234,11 @@ const struct clk_ops clk_divider_ops = {
148}; 234};
149EXPORT_SYMBOL_GPL(clk_divider_ops); 235EXPORT_SYMBOL_GPL(clk_divider_ops);
150 236
151/** 237static struct clk *_register_divider(struct device *dev, const char *name,
152 * clk_register_divider - register a divider clock with the clock framework
153 * @dev: device registering this clock
154 * @name: name of this clock
155 * @parent_name: name of clock's parent
156 * @flags: framework-specific flags
157 * @reg: register address to adjust divider
158 * @shift: number of bits to shift the bitfield
159 * @width: width of the bitfield
160 * @clk_divider_flags: divider-specific flags for this clock
161 * @lock: shared register lock for this clock
162 */
163struct clk *clk_register_divider(struct device *dev, const char *name,
164 const char *parent_name, unsigned long flags, 238 const char *parent_name, unsigned long flags,
165 void __iomem *reg, u8 shift, u8 width, 239 void __iomem *reg, u8 shift, u8 width,
166 u8 clk_divider_flags, spinlock_t *lock) 240 u8 clk_divider_flags, const struct clk_div_table *table,
241 spinlock_t *lock)
167{ 242{
168 struct clk_divider *div; 243 struct clk_divider *div;
169 struct clk *clk; 244 struct clk *clk;
@@ -178,7 +253,7 @@ struct clk *clk_register_divider(struct device *dev, const char *name,
178 253
179 init.name = name; 254 init.name = name;
180 init.ops = &clk_divider_ops; 255 init.ops = &clk_divider_ops;
181 init.flags = flags; 256 init.flags = flags | CLK_IS_BASIC;
182 init.parent_names = (parent_name ? &parent_name: NULL); 257 init.parent_names = (parent_name ? &parent_name: NULL);
183 init.num_parents = (parent_name ? 1 : 0); 258 init.num_parents = (parent_name ? 1 : 0);
184 259
@@ -189,6 +264,7 @@ struct clk *clk_register_divider(struct device *dev, const char *name,
189 div->flags = clk_divider_flags; 264 div->flags = clk_divider_flags;
190 div->lock = lock; 265 div->lock = lock;
191 div->hw.init = &init; 266 div->hw.init = &init;
267 div->table = table;
192 268
193 /* register the clock */ 269 /* register the clock */
194 clk = clk_register(dev, &div->hw); 270 clk = clk_register(dev, &div->hw);
@@ -198,3 +274,48 @@ struct clk *clk_register_divider(struct device *dev, const char *name,
198 274
199 return clk; 275 return clk;
200} 276}
277
278/**
279 * clk_register_divider - register a divider clock with the clock framework
280 * @dev: device registering this clock
281 * @name: name of this clock
282 * @parent_name: name of clock's parent
283 * @flags: framework-specific flags
284 * @reg: register address to adjust divider
285 * @shift: number of bits to shift the bitfield
286 * @width: width of the bitfield
287 * @clk_divider_flags: divider-specific flags for this clock
288 * @lock: shared register lock for this clock
289 */
290struct clk *clk_register_divider(struct device *dev, const char *name,
291 const char *parent_name, unsigned long flags,
292 void __iomem *reg, u8 shift, u8 width,
293 u8 clk_divider_flags, spinlock_t *lock)
294{
295 return _register_divider(dev, name, parent_name, flags, reg, shift,
296 width, clk_divider_flags, NULL, lock);
297}
298
299/**
300 * clk_register_divider_table - register a table based divider clock with
301 * the clock framework
302 * @dev: device registering this clock
303 * @name: name of this clock
304 * @parent_name: name of clock's parent
305 * @flags: framework-specific flags
306 * @reg: register address to adjust divider
307 * @shift: number of bits to shift the bitfield
308 * @width: width of the bitfield
309 * @clk_divider_flags: divider-specific flags for this clock
310 * @table: array of divider/value pairs ending with a div set to 0
311 * @lock: shared register lock for this clock
312 */
313struct clk *clk_register_divider_table(struct device *dev, const char *name,
314 const char *parent_name, unsigned long flags,
315 void __iomem *reg, u8 shift, u8 width,
316 u8 clk_divider_flags, const struct clk_div_table *table,
317 spinlock_t *lock)
318{
319 return _register_divider(dev, name, parent_name, flags, reg, shift,
320 width, clk_divider_flags, table, lock);
321}
diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index c8c003e217ad..a4899855c0f6 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -82,7 +82,7 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
82 82
83 init.name = name; 83 init.name = name;
84 init.ops = &clk_fixed_factor_ops; 84 init.ops = &clk_fixed_factor_ops;
85 init.flags = flags; 85 init.flags = flags | CLK_IS_BASIC;
86 init.parent_names = &parent_name; 86 init.parent_names = &parent_name;
87 init.num_parents = 1; 87 init.num_parents = 1;
88 88
diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c
index cbd246229786..f5ec0eebd4d7 100644
--- a/drivers/clk/clk-fixed-rate.c
+++ b/drivers/clk/clk-fixed-rate.c
@@ -14,6 +14,7 @@
14#include <linux/slab.h> 14#include <linux/slab.h>
15#include <linux/io.h> 15#include <linux/io.h>
16#include <linux/err.h> 16#include <linux/err.h>
17#include <linux/of.h>
17 18
18/* 19/*
19 * DOC: basic fixed-rate clock that cannot gate 20 * DOC: basic fixed-rate clock that cannot gate
@@ -63,7 +64,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
63 64
64 init.name = name; 65 init.name = name;
65 init.ops = &clk_fixed_rate_ops; 66 init.ops = &clk_fixed_rate_ops;
66 init.flags = flags; 67 init.flags = flags | CLK_IS_BASIC;
67 init.parent_names = (parent_name ? &parent_name: NULL); 68 init.parent_names = (parent_name ? &parent_name: NULL);
68 init.num_parents = (parent_name ? 1 : 0); 69 init.num_parents = (parent_name ? 1 : 0);
69 70
@@ -79,3 +80,25 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
79 80
80 return clk; 81 return clk;
81} 82}
83
84#ifdef CONFIG_OF
85/**
86 * of_fixed_clk_setup() - Setup function for simple fixed rate clock
87 */
88void __init of_fixed_clk_setup(struct device_node *node)
89{
90 struct clk *clk;
91 const char *clk_name = node->name;
92 u32 rate;
93
94 if (of_property_read_u32(node, "clock-frequency", &rate))
95 return;
96
97 of_property_read_string(node, "clock-output-names", &clk_name);
98
99 clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate);
100 if (clk)
101 of_clk_add_provider(node, of_clk_src_simple_get, clk);
102}
103EXPORT_SYMBOL_GPL(of_fixed_clk_setup);
104#endif
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 578465e04be6..15114febfd92 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -130,7 +130,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
130 130
131 init.name = name; 131 init.name = name;
132 init.ops = &clk_gate_ops; 132 init.ops = &clk_gate_ops;
133 init.flags = flags; 133 init.flags = flags | CLK_IS_BASIC;
134 init.parent_names = (parent_name ? &parent_name: NULL); 134 init.parent_names = (parent_name ? &parent_name: NULL);
135 init.num_parents = (parent_name ? 1 : 0); 135 init.num_parents = (parent_name ? 1 : 0);
136 136
diff --git a/drivers/clk/clk-highbank.c b/drivers/clk/clk-highbank.c
new file mode 100644
index 000000000000..52fecadf004a
--- /dev/null
+++ b/drivers/clk/clk-highbank.c
@@ -0,0 +1,346 @@
1/*
2 * Copyright 2011-2012 Calxeda, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/kernel.h>
18#include <linux/slab.h>
19#include <linux/err.h>
20#include <linux/clk-provider.h>
21#include <linux/io.h>
22#include <linux/of.h>
23
24extern void __iomem *sregs_base;
25
26#define HB_PLL_LOCK_500 0x20000000
27#define HB_PLL_LOCK 0x10000000
28#define HB_PLL_DIVF_SHIFT 20
29#define HB_PLL_DIVF_MASK 0x0ff00000
30#define HB_PLL_DIVQ_SHIFT 16
31#define HB_PLL_DIVQ_MASK 0x00070000
32#define HB_PLL_DIVR_SHIFT 8
33#define HB_PLL_DIVR_MASK 0x00001f00
34#define HB_PLL_RANGE_SHIFT 4
35#define HB_PLL_RANGE_MASK 0x00000070
36#define HB_PLL_BYPASS 0x00000008
37#define HB_PLL_RESET 0x00000004
38#define HB_PLL_EXT_BYPASS 0x00000002
39#define HB_PLL_EXT_ENA 0x00000001
40
41#define HB_PLL_VCO_MIN_FREQ 2133000000
42#define HB_PLL_MAX_FREQ HB_PLL_VCO_MIN_FREQ
43#define HB_PLL_MIN_FREQ (HB_PLL_VCO_MIN_FREQ / 64)
44
45#define HB_A9_BCLK_DIV_MASK 0x00000006
46#define HB_A9_BCLK_DIV_SHIFT 1
47#define HB_A9_PCLK_DIV 0x00000001
48
49struct hb_clk {
50 struct clk_hw hw;
51 void __iomem *reg;
52 char *parent_name;
53};
54#define to_hb_clk(p) container_of(p, struct hb_clk, hw)
55
56static int clk_pll_prepare(struct clk_hw *hwclk)
57 {
58 struct hb_clk *hbclk = to_hb_clk(hwclk);
59 u32 reg;
60
61 reg = readl(hbclk->reg);
62 reg &= ~HB_PLL_RESET;
63 writel(reg, hbclk->reg);
64
65 while ((readl(hbclk->reg) & HB_PLL_LOCK) == 0)
66 ;
67 while ((readl(hbclk->reg) & HB_PLL_LOCK_500) == 0)
68 ;
69
70 return 0;
71}
72
73static void clk_pll_unprepare(struct clk_hw *hwclk)
74{
75 struct hb_clk *hbclk = to_hb_clk(hwclk);
76 u32 reg;
77
78 reg = readl(hbclk->reg);
79 reg |= HB_PLL_RESET;
80 writel(reg, hbclk->reg);
81}
82
83static int clk_pll_enable(struct clk_hw *hwclk)
84{
85 struct hb_clk *hbclk = to_hb_clk(hwclk);
86 u32 reg;
87
88 reg = readl(hbclk->reg);
89 reg |= HB_PLL_EXT_ENA;
90 writel(reg, hbclk->reg);
91
92 return 0;
93}
94
95static void clk_pll_disable(struct clk_hw *hwclk)
96{
97 struct hb_clk *hbclk = to_hb_clk(hwclk);
98 u32 reg;
99
100 reg = readl(hbclk->reg);
101 reg &= ~HB_PLL_EXT_ENA;
102 writel(reg, hbclk->reg);
103}
104
105static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
106 unsigned long parent_rate)
107{
108 struct hb_clk *hbclk = to_hb_clk(hwclk);
109 unsigned long divf, divq, vco_freq, reg;
110
111 reg = readl(hbclk->reg);
112 if (reg & HB_PLL_EXT_BYPASS)
113 return parent_rate;
114
115 divf = (reg & HB_PLL_DIVF_MASK) >> HB_PLL_DIVF_SHIFT;
116 divq = (reg & HB_PLL_DIVQ_MASK) >> HB_PLL_DIVQ_SHIFT;
117 vco_freq = parent_rate * (divf + 1);
118
119 return vco_freq / (1 << divq);
120}
121
122static void clk_pll_calc(unsigned long rate, unsigned long ref_freq,
123 u32 *pdivq, u32 *pdivf)
124{
125 u32 divq, divf;
126 unsigned long vco_freq;
127
128 if (rate < HB_PLL_MIN_FREQ)
129 rate = HB_PLL_MIN_FREQ;
130 if (rate > HB_PLL_MAX_FREQ)
131 rate = HB_PLL_MAX_FREQ;
132
133 for (divq = 1; divq <= 6; divq++) {
134 if ((rate * (1 << divq)) >= HB_PLL_VCO_MIN_FREQ)
135 break;
136 }
137
138 vco_freq = rate * (1 << divq);
139 divf = (vco_freq + (ref_freq / 2)) / ref_freq;
140 divf--;
141
142 *pdivq = divq;
143 *pdivf = divf;
144}
145
146static long clk_pll_round_rate(struct clk_hw *hwclk, unsigned long rate,
147 unsigned long *parent_rate)
148{
149 u32 divq, divf;
150 unsigned long ref_freq = *parent_rate;
151
152 clk_pll_calc(rate, ref_freq, &divq, &divf);
153
154 return (ref_freq * (divf + 1)) / (1 << divq);
155}
156
157static int clk_pll_set_rate(struct clk_hw *hwclk, unsigned long rate,
158 unsigned long parent_rate)
159{
160 struct hb_clk *hbclk = to_hb_clk(hwclk);
161 u32 divq, divf;
162 u32 reg;
163
164 clk_pll_calc(rate, parent_rate, &divq, &divf);
165
166 reg = readl(hbclk->reg);
167 if (divf != ((reg & HB_PLL_DIVF_MASK) >> HB_PLL_DIVF_SHIFT)) {
168 /* Need to re-lock PLL, so put it into bypass mode */
169 reg |= HB_PLL_EXT_BYPASS;
170 writel(reg | HB_PLL_EXT_BYPASS, hbclk->reg);
171
172 writel(reg | HB_PLL_RESET, hbclk->reg);
173 reg &= ~(HB_PLL_DIVF_MASK | HB_PLL_DIVQ_MASK);
174 reg |= (divf << HB_PLL_DIVF_SHIFT) | (divq << HB_PLL_DIVQ_SHIFT);
175 writel(reg | HB_PLL_RESET, hbclk->reg);
176 writel(reg, hbclk->reg);
177
178 while ((readl(hbclk->reg) & HB_PLL_LOCK) == 0)
179 ;
180 while ((readl(hbclk->reg) & HB_PLL_LOCK_500) == 0)
181 ;
182 reg |= HB_PLL_EXT_ENA;
183 reg &= ~HB_PLL_EXT_BYPASS;
184 } else {
185 reg &= ~HB_PLL_DIVQ_MASK;
186 reg |= divq << HB_PLL_DIVQ_SHIFT;
187 }
188 writel(reg, hbclk->reg);
189
190 return 0;
191}
192
193static const struct clk_ops clk_pll_ops = {
194 .prepare = clk_pll_prepare,
195 .unprepare = clk_pll_unprepare,
196 .enable = clk_pll_enable,
197 .disable = clk_pll_disable,
198 .recalc_rate = clk_pll_recalc_rate,
199 .round_rate = clk_pll_round_rate,
200 .set_rate = clk_pll_set_rate,
201};
202
203static unsigned long clk_cpu_periphclk_recalc_rate(struct clk_hw *hwclk,
204 unsigned long parent_rate)
205{
206 struct hb_clk *hbclk = to_hb_clk(hwclk);
207 u32 div = (readl(hbclk->reg) & HB_A9_PCLK_DIV) ? 8 : 4;
208 return parent_rate / div;
209}
210
211static const struct clk_ops a9periphclk_ops = {
212 .recalc_rate = clk_cpu_periphclk_recalc_rate,
213};
214
215static unsigned long clk_cpu_a9bclk_recalc_rate(struct clk_hw *hwclk,
216 unsigned long parent_rate)
217{
218 struct hb_clk *hbclk = to_hb_clk(hwclk);
219 u32 div = (readl(hbclk->reg) & HB_A9_BCLK_DIV_MASK) >> HB_A9_BCLK_DIV_SHIFT;
220
221 return parent_rate / (div + 2);
222}
223
224static const struct clk_ops a9bclk_ops = {
225 .recalc_rate = clk_cpu_a9bclk_recalc_rate,
226};
227
228static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
229 unsigned long parent_rate)
230{
231 struct hb_clk *hbclk = to_hb_clk(hwclk);
232 u32 div;
233
234 div = readl(hbclk->reg) & 0x1f;
235 div++;
236 div *= 2;
237
238 return parent_rate / div;
239}
240
241static long clk_periclk_round_rate(struct clk_hw *hwclk, unsigned long rate,
242 unsigned long *parent_rate)
243{
244 u32 div;
245
246 div = *parent_rate / rate;
247 div++;
248 div &= ~0x1;
249
250 return *parent_rate / div;
251}
252
253static int clk_periclk_set_rate(struct clk_hw *hwclk, unsigned long rate,
254 unsigned long parent_rate)
255{
256 struct hb_clk *hbclk = to_hb_clk(hwclk);
257 u32 div;
258
259 div = parent_rate / rate;
260 if (div & 0x1)
261 return -EINVAL;
262
263 writel(div >> 1, hbclk->reg);
264 return 0;
265}
266
267static const struct clk_ops periclk_ops = {
268 .recalc_rate = clk_periclk_recalc_rate,
269 .round_rate = clk_periclk_round_rate,
270 .set_rate = clk_periclk_set_rate,
271};
272
273static __init struct clk *hb_clk_init(struct device_node *node, const struct clk_ops *ops)
274{
275 u32 reg;
276 struct clk *clk;
277 struct hb_clk *hb_clk;
278 const char *clk_name = node->name;
279 const char *parent_name;
280 struct clk_init_data init;
281 int rc;
282
283 rc = of_property_read_u32(node, "reg", &reg);
284 if (WARN_ON(rc))
285 return NULL;
286
287 hb_clk = kzalloc(sizeof(*hb_clk), GFP_KERNEL);
288 if (WARN_ON(!hb_clk))
289 return NULL;
290
291 hb_clk->reg = sregs_base + reg;
292
293 of_property_read_string(node, "clock-output-names", &clk_name);
294
295 init.name = clk_name;
296 init.ops = ops;
297 init.flags = 0;
298 parent_name = of_clk_get_parent_name(node, 0);
299 init.parent_names = &parent_name;
300 init.num_parents = 1;
301
302 hb_clk->hw.init = &init;
303
304 clk = clk_register(NULL, &hb_clk->hw);
305 if (WARN_ON(IS_ERR(clk))) {
306 kfree(hb_clk);
307 return NULL;
308 }
309 rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
310 return clk;
311}
312
313static void __init hb_pll_init(struct device_node *node)
314{
315 hb_clk_init(node, &clk_pll_ops);
316}
317
318static void __init hb_a9periph_init(struct device_node *node)
319{
320 hb_clk_init(node, &a9periphclk_ops);
321}
322
323static void __init hb_a9bus_init(struct device_node *node)
324{
325 struct clk *clk = hb_clk_init(node, &a9bclk_ops);
326 clk_prepare_enable(clk);
327}
328
329static void __init hb_emmc_init(struct device_node *node)
330{
331 hb_clk_init(node, &periclk_ops);
332}
333
334static const __initconst struct of_device_id clk_match[] = {
335 { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
336 { .compatible = "calxeda,hb-pll-clock", .data = hb_pll_init, },
337 { .compatible = "calxeda,hb-a9periph-clock", .data = hb_a9periph_init, },
338 { .compatible = "calxeda,hb-a9bus-clock", .data = hb_a9bus_init, },
339 { .compatible = "calxeda,hb-emmc-clock", .data = hb_emmc_init, },
340 {}
341};
342
343void __init highbank_clocks_init(void)
344{
345 of_clk_init(clk_match);
346}
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index fd36a8ea73d9..508c032edce4 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -106,7 +106,7 @@ struct clk *clk_register_mux(struct device *dev, const char *name,
106 106
107 init.name = name; 107 init.name = name;
108 init.ops = &clk_mux_ops; 108 init.ops = &clk_mux_ops;
109 init.flags = flags; 109 init.flags = flags | CLK_IS_BASIC;
110 init.parent_names = parent_names; 110 init.parent_names = parent_names;
111 init.num_parents = num_parents; 111 init.num_parents = num_parents;
112 112
diff --git a/drivers/clk/clk-u300.c b/drivers/clk/clk-u300.c
new file mode 100644
index 000000000000..a15f7928fb11
--- /dev/null
+++ b/drivers/clk/clk-u300.c
@@ -0,0 +1,746 @@
1/*
2 * U300 clock implementation
3 * Copyright (C) 2007-2012 ST-Ericsson AB
4 * License terms: GNU General Public License (GPL) version 2
5 * Author: Linus Walleij <linus.walleij@stericsson.com>
6 * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
7 */
8#include <linux/clk.h>
9#include <linux/clkdev.h>
10#include <linux/err.h>
11#include <linux/io.h>
12#include <linux/clk-provider.h>
13#include <linux/spinlock.h>
14#include <mach/syscon.h>
15
16/*
17 * The clocking hierarchy currently looks like this.
18 * NOTE: the idea is NOT to show how the clocks are routed on the chip!
19 * The ideas is to show dependencies, so a clock higher up in the
20 * hierarchy has to be on in order for another clock to be on. Now,
21 * both CPU and DMA can actually be on top of the hierarchy, and that
22 * is not modeled currently. Instead we have the backbone AMBA bus on
23 * top. This bus cannot be programmed in any way but conceptually it
24 * needs to be active for the bridges and devices to transport data.
25 *
26 * Please be aware that a few clocks are hw controlled, which mean that
27 * the hw itself can turn on/off or change the rate of the clock when
28 * needed!
29 *
30 * AMBA bus
31 * |
32 * +- CPU
33 * +- FSMC NANDIF NAND Flash interface
34 * +- SEMI Shared Memory interface
35 * +- ISP Image Signal Processor (U335 only)
36 * +- CDS (U335 only)
37 * +- DMA Direct Memory Access Controller
38 * +- AAIF APP/ACC Inteface (Mobile Scalable Link, MSL)
39 * +- APEX
40 * +- VIDEO_ENC AVE2/3 Video Encoder
41 * +- XGAM Graphics Accelerator Controller
42 * +- AHB
43 * |
44 * +- ahb:0 AHB Bridge
45 * | |
46 * | +- ahb:1 INTCON Interrupt controller
47 * | +- ahb:3 MSPRO Memory Stick Pro controller
48 * | +- ahb:4 EMIF External Memory interface
49 * |
50 * +- fast:0 FAST bridge
51 * | |
52 * | +- fast:1 MMCSD MMC/SD card reader controller
53 * | +- fast:2 I2S0 PCM I2S channel 0 controller
54 * | +- fast:3 I2S1 PCM I2S channel 1 controller
55 * | +- fast:4 I2C0 I2C channel 0 controller
56 * | +- fast:5 I2C1 I2C channel 1 controller
57 * | +- fast:6 SPI SPI controller
58 * | +- fast:7 UART1 Secondary UART (U335 only)
59 * |
60 * +- slow:0 SLOW bridge
61 * |
62 * +- slow:1 SYSCON (not possible to control)
63 * +- slow:2 WDOG Watchdog
64 * +- slow:3 UART0 primary UART
65 * +- slow:4 TIMER_APP Application timer - used in Linux
66 * +- slow:5 KEYPAD controller
67 * +- slow:6 GPIO controller
68 * +- slow:7 RTC controller
69 * +- slow:8 BT Bus Tracer (not used currently)
70 * +- slow:9 EH Event Handler (not used currently)
71 * +- slow:a TIMER_ACC Access style timer (not used currently)
72 * +- slow:b PPM (U335 only, what is that?)
73 */
74
75/* Global syscon virtual base */
76static void __iomem *syscon_vbase;
77
78/**
79 * struct clk_syscon - U300 syscon clock
80 * @hw: corresponding clock hardware entry
81 * @hw_ctrld: whether this clock is hardware controlled (for refcount etc)
82 * and does not need any magic pokes to be enabled/disabled
83 * @reset: state holder, whether this block's reset line is asserted or not
84 * @res_reg: reset line enable/disable flag register
85 * @res_bit: bit for resetting or taking this consumer out of reset
86 * @en_reg: clock line enable/disable flag register
87 * @en_bit: bit for enabling/disabling this consumer clock line
88 * @clk_val: magic value to poke in the register to enable/disable
89 * this one clock
90 */
91struct clk_syscon {
92 struct clk_hw hw;
93 bool hw_ctrld;
94 bool reset;
95 void __iomem *res_reg;
96 u8 res_bit;
97 void __iomem *en_reg;
98 u8 en_bit;
99 u16 clk_val;
100};
101
102#define to_syscon(_hw) container_of(_hw, struct clk_syscon, hw)
103
104static DEFINE_SPINLOCK(syscon_resetreg_lock);
105
106/*
107 * Reset control functions. We remember if a block has been
108 * taken out of reset and don't remove the reset assertion again
109 * and vice versa. Currently we only remove resets so the
110 * enablement function is defined out.
111 */
112static void syscon_block_reset_enable(struct clk_syscon *sclk)
113{
114 unsigned long iflags;
115 u16 val;
116
117 /* Not all blocks support resetting */
118 if (!sclk->res_reg)
119 return;
120 spin_lock_irqsave(&syscon_resetreg_lock, iflags);
121 val = readw(sclk->res_reg);
122 val |= BIT(sclk->res_bit);
123 writew(val, sclk->res_reg);
124 spin_unlock_irqrestore(&syscon_resetreg_lock, iflags);
125 sclk->reset = true;
126}
127
128static void syscon_block_reset_disable(struct clk_syscon *sclk)
129{
130 unsigned long iflags;
131 u16 val;
132
133 /* Not all blocks support resetting */
134 if (!sclk->res_reg)
135 return;
136 spin_lock_irqsave(&syscon_resetreg_lock, iflags);
137 val = readw(sclk->res_reg);
138 val &= ~BIT(sclk->res_bit);
139 writew(val, sclk->res_reg);
140 spin_unlock_irqrestore(&syscon_resetreg_lock, iflags);
141 sclk->reset = false;
142}
143
144static int syscon_clk_prepare(struct clk_hw *hw)
145{
146 struct clk_syscon *sclk = to_syscon(hw);
147
148 /* If the block is in reset, bring it out */
149 if (sclk->reset)
150 syscon_block_reset_disable(sclk);
151 return 0;
152}
153
154static void syscon_clk_unprepare(struct clk_hw *hw)
155{
156 struct clk_syscon *sclk = to_syscon(hw);
157
158 /* Please don't force the console into reset */
159 if (sclk->clk_val == U300_SYSCON_SBCER_UART_CLK_EN)
160 return;
161 /* When unpreparing, force block into reset */
162 if (!sclk->reset)
163 syscon_block_reset_enable(sclk);
164}
165
166static int syscon_clk_enable(struct clk_hw *hw)
167{
168 struct clk_syscon *sclk = to_syscon(hw);
169
170 /* Don't touch the hardware controlled clocks */
171 if (sclk->hw_ctrld)
172 return 0;
173 /* These cannot be controlled */
174 if (sclk->clk_val == 0xFFFFU)
175 return 0;
176
177 writew(sclk->clk_val, syscon_vbase + U300_SYSCON_SBCER);
178 return 0;
179}
180
181static void syscon_clk_disable(struct clk_hw *hw)
182{
183 struct clk_syscon *sclk = to_syscon(hw);
184
185 /* Don't touch the hardware controlled clocks */
186 if (sclk->hw_ctrld)
187 return;
188 if (sclk->clk_val == 0xFFFFU)
189 return;
190 /* Please don't disable the console port */
191 if (sclk->clk_val == U300_SYSCON_SBCER_UART_CLK_EN)
192 return;
193
194 writew(sclk->clk_val, syscon_vbase + U300_SYSCON_SBCDR);
195}
196
197static int syscon_clk_is_enabled(struct clk_hw *hw)
198{
199 struct clk_syscon *sclk = to_syscon(hw);
200 u16 val;
201
202 /* If no enable register defined, it's always-on */
203 if (!sclk->en_reg)
204 return 1;
205
206 val = readw(sclk->en_reg);
207 val &= BIT(sclk->en_bit);
208
209 return val ? 1 : 0;
210}
211
212static u16 syscon_get_perf(void)
213{
214 u16 val;
215
216 val = readw(syscon_vbase + U300_SYSCON_CCR);
217 val &= U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK;
218 return val;
219}
220
221static unsigned long
222syscon_clk_recalc_rate(struct clk_hw *hw,
223 unsigned long parent_rate)
224{
225 struct clk_syscon *sclk = to_syscon(hw);
226 u16 perf = syscon_get_perf();
227
228 switch(sclk->clk_val) {
229 case U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN:
230 case U300_SYSCON_SBCER_I2C0_CLK_EN:
231 case U300_SYSCON_SBCER_I2C1_CLK_EN:
232 case U300_SYSCON_SBCER_MMC_CLK_EN:
233 case U300_SYSCON_SBCER_SPI_CLK_EN:
234 /* The FAST clocks have one progression */
235 switch(perf) {
236 case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
237 case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
238 return 13000000;
239 default:
240 return parent_rate; /* 26 MHz */
241 }
242 case U300_SYSCON_SBCER_DMAC_CLK_EN:
243 case U300_SYSCON_SBCER_NANDIF_CLK_EN:
244 case U300_SYSCON_SBCER_XGAM_CLK_EN:
245 /* AMBA interconnect peripherals */
246 switch(perf) {
247 case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
248 case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
249 return 6500000;
250 case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
251 return 26000000;
252 default:
253 return parent_rate; /* 52 MHz */
254 }
255 case U300_SYSCON_SBCER_SEMI_CLK_EN:
256 case U300_SYSCON_SBCER_EMIF_CLK_EN:
257 /* EMIF speeds */
258 switch(perf) {
259 case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
260 case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
261 return 13000000;
262 case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
263 return 52000000;
264 default:
265 return 104000000;
266 }
267 case U300_SYSCON_SBCER_CPU_CLK_EN:
268 /* And the fast CPU clock */
269 switch(perf) {
270 case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
271 case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
272 return 13000000;
273 case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
274 return 52000000;
275 case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
276 return 104000000;
277 default:
278 return parent_rate; /* 208 MHz */
279 }
280 default:
281 /*
282 * The SLOW clocks and default just inherit the rate of
283 * their parent (typically PLL13 13 MHz).
284 */
285 return parent_rate;
286 }
287}
288
289static long
290syscon_clk_round_rate(struct clk_hw *hw, unsigned long rate,
291 unsigned long *prate)
292{
293 struct clk_syscon *sclk = to_syscon(hw);
294
295 if (sclk->clk_val != U300_SYSCON_SBCER_CPU_CLK_EN)
296 return *prate;
297 /* We really only support setting the rate of the CPU clock */
298 if (rate <= 13000000)
299 return 13000000;
300 if (rate <= 52000000)
301 return 52000000;
302 if (rate <= 104000000)
303 return 104000000;
304 return 208000000;
305}
306
307static int syscon_clk_set_rate(struct clk_hw *hw, unsigned long rate,
308 unsigned long parent_rate)
309{
310 struct clk_syscon *sclk = to_syscon(hw);
311 u16 val;
312
313 /* We only support setting the rate of the CPU clock */
314 if (sclk->clk_val != U300_SYSCON_SBCER_CPU_CLK_EN)
315 return -EINVAL;
316 switch (rate) {
317 case 13000000:
318 val = U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER;
319 break;
320 case 52000000:
321 val = U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE;
322 break;
323 case 104000000:
324 val = U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH;
325 break;
326 case 208000000:
327 val = U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST;
328 break;
329 default:
330 return -EINVAL;
331 }
332 val |= readw(syscon_vbase + U300_SYSCON_CCR) &
333 ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK ;
334 writew(val, syscon_vbase + U300_SYSCON_CCR);
335 return 0;
336}
337
338static const struct clk_ops syscon_clk_ops = {
339 .prepare = syscon_clk_prepare,
340 .unprepare = syscon_clk_unprepare,
341 .enable = syscon_clk_enable,
342 .disable = syscon_clk_disable,
343 .is_enabled = syscon_clk_is_enabled,
344 .recalc_rate = syscon_clk_recalc_rate,
345 .round_rate = syscon_clk_round_rate,
346 .set_rate = syscon_clk_set_rate,
347};
348
349static struct clk * __init
350syscon_clk_register(struct device *dev, const char *name,
351 const char *parent_name, unsigned long flags,
352 bool hw_ctrld,
353 void __iomem *res_reg, u8 res_bit,
354 void __iomem *en_reg, u8 en_bit,
355 u16 clk_val)
356{
357 struct clk *clk;
358 struct clk_syscon *sclk;
359 struct clk_init_data init;
360
361 sclk = kzalloc(sizeof(struct clk_syscon), GFP_KERNEL);
362 if (!sclk) {
363 pr_err("could not allocate syscon clock %s\n",
364 name);
365 return ERR_PTR(-ENOMEM);
366 }
367 init.name = name;
368 init.ops = &syscon_clk_ops;
369 init.flags = flags;
370 init.parent_names = (parent_name ? &parent_name : NULL);
371 init.num_parents = (parent_name ? 1 : 0);
372 sclk->hw.init = &init;
373 sclk->hw_ctrld = hw_ctrld;
374 /* Assume the block is in reset at registration */
375 sclk->reset = true;
376 sclk->res_reg = res_reg;
377 sclk->res_bit = res_bit;
378 sclk->en_reg = en_reg;
379 sclk->en_bit = en_bit;
380 sclk->clk_val = clk_val;
381
382 clk = clk_register(dev, &sclk->hw);
383 if (IS_ERR(clk))
384 kfree(sclk);
385
386 return clk;
387}
388
389/**
390 * struct clk_mclk - U300 MCLK clock (MMC/SD clock)
391 * @hw: corresponding clock hardware entry
392 * @is_mspro: if this is the memory stick clock rather than MMC/SD
393 */
394struct clk_mclk {
395 struct clk_hw hw;
396 bool is_mspro;
397};
398
399#define to_mclk(_hw) container_of(_hw, struct clk_mclk, hw)
400
401static int mclk_clk_prepare(struct clk_hw *hw)
402{
403 struct clk_mclk *mclk = to_mclk(hw);
404 u16 val;
405
406 /* The MMC and MSPRO clocks need some special set-up */
407 if (!mclk->is_mspro) {
408 /* Set default MMC clock divisor to 18.9 MHz */
409 writew(0x0054U, syscon_vbase + U300_SYSCON_MMF0R);
410 val = readw(syscon_vbase + U300_SYSCON_MMCR);
411 /* Disable the MMC feedback clock */
412 val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE;
413 /* Disable MSPRO frequency */
414 val &= ~U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE;
415 writew(val, syscon_vbase + U300_SYSCON_MMCR);
416 } else {
417 val = readw(syscon_vbase + U300_SYSCON_MMCR);
418 /* Disable the MMC feedback clock */
419 val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE;
420 /* Enable MSPRO frequency */
421 val |= U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE;
422 writew(val, syscon_vbase + U300_SYSCON_MMCR);
423 }
424
425 return 0;
426}
427
428static unsigned long
429mclk_clk_recalc_rate(struct clk_hw *hw,
430 unsigned long parent_rate)
431{
432 u16 perf = syscon_get_perf();
433
434 switch (perf) {
435 case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
436 /*
437 * Here, the 208 MHz PLL gets shut down and the always
438 * on 13 MHz PLL used for RTC etc kicks into use
439 * instead.
440 */
441 return 13000000;
442 case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
443 case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE:
444 case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH:
445 case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST:
446 {
447 /*
448 * This clock is under program control. The register is
449 * divided in two nybbles, bit 7-4 gives cycles-1 to count
450 * high, bit 3-0 gives cycles-1 to count low. Distribute
451 * these with no more than 1 cycle difference between
452 * low and high and add low and high to get the actual
453 * divisor. The base PLL is 208 MHz. Writing 0x00 will
454 * divide by 1 and 1 so the highest frequency possible
455 * is 104 MHz.
456 *
457 * e.g. 0x54 =>
458 * f = 208 / ((5+1) + (4+1)) = 208 / 11 = 18.9 MHz
459 */
460 u16 val = readw(syscon_vbase + U300_SYSCON_MMF0R) &
461 U300_SYSCON_MMF0R_MASK;
462 switch (val) {
463 case 0x0054:
464 return 18900000;
465 case 0x0044:
466 return 20800000;
467 case 0x0043:
468 return 23100000;
469 case 0x0033:
470 return 26000000;
471 case 0x0032:
472 return 29700000;
473 case 0x0022:
474 return 34700000;
475 case 0x0021:
476 return 41600000;
477 case 0x0011:
478 return 52000000;
479 case 0x0000:
480 return 104000000;
481 default:
482 break;
483 }
484 }
485 default:
486 break;
487 }
488 return parent_rate;
489}
490
491static long
492mclk_clk_round_rate(struct clk_hw *hw, unsigned long rate,
493 unsigned long *prate)
494{
495 if (rate <= 18900000)
496 return 18900000;
497 if (rate <= 20800000)
498 return 20800000;
499 if (rate <= 23100000)
500 return 23100000;
501 if (rate <= 26000000)
502 return 26000000;
503 if (rate <= 29700000)
504 return 29700000;
505 if (rate <= 34700000)
506 return 34700000;
507 if (rate <= 41600000)
508 return 41600000;
509 /* Highest rate */
510 return 52000000;
511}
512
513static int mclk_clk_set_rate(struct clk_hw *hw, unsigned long rate,
514 unsigned long parent_rate)
515{
516 u16 val;
517 u16 reg;
518
519 switch (rate) {
520 case 18900000:
521 val = 0x0054;
522 break;
523 case 20800000:
524 val = 0x0044;
525 break;
526 case 23100000:
527 val = 0x0043;
528 break;
529 case 26000000:
530 val = 0x0033;
531 break;
532 case 29700000:
533 val = 0x0032;
534 break;
535 case 34700000:
536 val = 0x0022;
537 break;
538 case 41600000:
539 val = 0x0021;
540 break;
541 case 52000000:
542 val = 0x0011;
543 break;
544 case 104000000:
545 val = 0x0000;
546 break;
547 default:
548 return -EINVAL;
549 }
550
551 reg = readw(syscon_vbase + U300_SYSCON_MMF0R) &
552 ~U300_SYSCON_MMF0R_MASK;
553 writew(reg | val, syscon_vbase + U300_SYSCON_MMF0R);
554 return 0;
555}
556
557static const struct clk_ops mclk_ops = {
558 .prepare = mclk_clk_prepare,
559 .recalc_rate = mclk_clk_recalc_rate,
560 .round_rate = mclk_clk_round_rate,
561 .set_rate = mclk_clk_set_rate,
562};
563
564static struct clk * __init
565mclk_clk_register(struct device *dev, const char *name,
566 const char *parent_name, bool is_mspro)
567{
568 struct clk *clk;
569 struct clk_mclk *mclk;
570 struct clk_init_data init;
571
572 mclk = kzalloc(sizeof(struct clk_mclk), GFP_KERNEL);
573 if (!mclk) {
574 pr_err("could not allocate MMC/SD clock %s\n",
575 name);
576 return ERR_PTR(-ENOMEM);
577 }
578 init.name = "mclk";
579 init.ops = &mclk_ops;
580 init.flags = 0;
581 init.parent_names = (parent_name ? &parent_name : NULL);
582 init.num_parents = (parent_name ? 1 : 0);
583 mclk->hw.init = &init;
584 mclk->is_mspro = is_mspro;
585
586 clk = clk_register(dev, &mclk->hw);
587 if (IS_ERR(clk))
588 kfree(mclk);
589
590 return clk;
591}
592
593void __init u300_clk_init(void __iomem *base)
594{
595 u16 val;
596 struct clk *clk;
597
598 syscon_vbase = base;
599
600 /* Set system to run at PLL208, max performance, a known state. */
601 val = readw(syscon_vbase + U300_SYSCON_CCR);
602 val &= ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK;
603 writew(val, syscon_vbase + U300_SYSCON_CCR);
604 /* Wait for the PLL208 to lock if not locked in yet */
605 while (!(readw(syscon_vbase + U300_SYSCON_CSR) &
606 U300_SYSCON_CSR_PLL208_LOCK_IND));
607
608 /* Power management enable */
609 val = readw(syscon_vbase + U300_SYSCON_PMCR);
610 val |= U300_SYSCON_PMCR_PWR_MGNT_ENABLE;
611 writew(val, syscon_vbase + U300_SYSCON_PMCR);
612
613 /* These are always available (RTC and PLL13) */
614 clk = clk_register_fixed_rate(NULL, "app_32_clk", NULL,
615 CLK_IS_ROOT, 32768);
616 /* The watchdog sits directly on the 32 kHz clock */
617 clk_register_clkdev(clk, NULL, "coh901327_wdog");
618 clk = clk_register_fixed_rate(NULL, "pll13", NULL,
619 CLK_IS_ROOT, 13000000);
620
621 /* These derive from PLL208 */
622 clk = clk_register_fixed_rate(NULL, "pll208", NULL,
623 CLK_IS_ROOT, 208000000);
624 clk = clk_register_fixed_factor(NULL, "app_208_clk", "pll208",
625 0, 1, 1);
626 clk = clk_register_fixed_factor(NULL, "app_104_clk", "pll208",
627 0, 1, 2);
628 clk = clk_register_fixed_factor(NULL, "app_52_clk", "pll208",
629 0, 1, 4);
630 /* The 52 MHz is divided down to 26 MHz */
631 clk = clk_register_fixed_factor(NULL, "app_26_clk", "app_52_clk",
632 0, 1, 2);
633
634 /* Directly on the AMBA interconnect */
635 clk = syscon_clk_register(NULL, "cpu_clk", "app_208_clk", 0, true,
636 syscon_vbase + U300_SYSCON_RRR, 3,
637 syscon_vbase + U300_SYSCON_CERR, 3,
638 U300_SYSCON_SBCER_CPU_CLK_EN);
639 clk = syscon_clk_register(NULL, "dmac_clk", "app_52_clk", 0, true,
640 syscon_vbase + U300_SYSCON_RRR, 4,
641 syscon_vbase + U300_SYSCON_CERR, 4,
642 U300_SYSCON_SBCER_DMAC_CLK_EN);
643 clk_register_clkdev(clk, NULL, "dma");
644 clk = syscon_clk_register(NULL, "fsmc_clk", "app_52_clk", 0, false,
645 syscon_vbase + U300_SYSCON_RRR, 6,
646 syscon_vbase + U300_SYSCON_CERR, 6,
647 U300_SYSCON_SBCER_NANDIF_CLK_EN);
648 clk_register_clkdev(clk, NULL, "fsmc-nand");
649 clk = syscon_clk_register(NULL, "xgam_clk", "app_52_clk", 0, true,
650 syscon_vbase + U300_SYSCON_RRR, 8,
651 syscon_vbase + U300_SYSCON_CERR, 8,
652 U300_SYSCON_SBCER_XGAM_CLK_EN);
653 clk_register_clkdev(clk, NULL, "xgam");
654 clk = syscon_clk_register(NULL, "semi_clk", "app_104_clk", 0, false,
655 syscon_vbase + U300_SYSCON_RRR, 9,
656 syscon_vbase + U300_SYSCON_CERR, 9,
657 U300_SYSCON_SBCER_SEMI_CLK_EN);
658 clk_register_clkdev(clk, NULL, "semi");
659
660 /* AHB bridge clocks */
661 clk = syscon_clk_register(NULL, "ahb_subsys_clk", "app_52_clk", 0, true,
662 syscon_vbase + U300_SYSCON_RRR, 10,
663 syscon_vbase + U300_SYSCON_CERR, 10,
664 U300_SYSCON_SBCER_AHB_SUBSYS_BRIDGE_CLK_EN);
665 clk = syscon_clk_register(NULL, "intcon_clk", "ahb_subsys_clk", 0, false,
666 syscon_vbase + U300_SYSCON_RRR, 12,
667 syscon_vbase + U300_SYSCON_CERR, 12,
668 /* Cannot be enabled, just taken out of reset */
669 0xFFFFU);
670 clk_register_clkdev(clk, NULL, "intcon");
671 clk = syscon_clk_register(NULL, "emif_clk", "ahb_subsys_clk", 0, false,
672 syscon_vbase + U300_SYSCON_RRR, 5,
673 syscon_vbase + U300_SYSCON_CERR, 5,
674 U300_SYSCON_SBCER_EMIF_CLK_EN);
675 clk_register_clkdev(clk, NULL, "pl172");
676
677 /* FAST bridge clocks */
678 clk = syscon_clk_register(NULL, "fast_clk", "app_26_clk", 0, true,
679 syscon_vbase + U300_SYSCON_RFR, 0,
680 syscon_vbase + U300_SYSCON_CEFR, 0,
681 U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN);
682 clk = syscon_clk_register(NULL, "i2c0_p_clk", "fast_clk", 0, false,
683 syscon_vbase + U300_SYSCON_RFR, 1,
684 syscon_vbase + U300_SYSCON_CEFR, 1,
685 U300_SYSCON_SBCER_I2C0_CLK_EN);
686 clk_register_clkdev(clk, NULL, "stu300.0");
687 clk = syscon_clk_register(NULL, "i2c1_p_clk", "fast_clk", 0, false,
688 syscon_vbase + U300_SYSCON_RFR, 2,
689 syscon_vbase + U300_SYSCON_CEFR, 2,
690 U300_SYSCON_SBCER_I2C1_CLK_EN);
691 clk_register_clkdev(clk, NULL, "stu300.1");
692 clk = syscon_clk_register(NULL, "mmc_p_clk", "fast_clk", 0, false,
693 syscon_vbase + U300_SYSCON_RFR, 5,
694 syscon_vbase + U300_SYSCON_CEFR, 5,
695 U300_SYSCON_SBCER_MMC_CLK_EN);
696 clk_register_clkdev(clk, "apb_pclk", "mmci");
697 clk = syscon_clk_register(NULL, "spi_p_clk", "fast_clk", 0, false,
698 syscon_vbase + U300_SYSCON_RFR, 6,
699 syscon_vbase + U300_SYSCON_CEFR, 6,
700 U300_SYSCON_SBCER_SPI_CLK_EN);
701 /* The SPI has no external clock for the outward bus, uses the pclk */
702 clk_register_clkdev(clk, NULL, "pl022");
703 clk_register_clkdev(clk, "apb_pclk", "pl022");
704
705 /* SLOW bridge clocks */
706 clk = syscon_clk_register(NULL, "slow_clk", "pll13", 0, true,
707 syscon_vbase + U300_SYSCON_RSR, 0,
708 syscon_vbase + U300_SYSCON_CESR, 0,
709 U300_SYSCON_SBCER_SLOW_BRIDGE_CLK_EN);
710 clk = syscon_clk_register(NULL, "uart0_clk", "slow_clk", 0, false,
711 syscon_vbase + U300_SYSCON_RSR, 1,
712 syscon_vbase + U300_SYSCON_CESR, 1,
713 U300_SYSCON_SBCER_UART_CLK_EN);
714 /* Same clock is used for APB and outward bus */
715 clk_register_clkdev(clk, NULL, "uart0");
716 clk_register_clkdev(clk, "apb_pclk", "uart0");
717 clk = syscon_clk_register(NULL, "gpio_clk", "slow_clk", 0, false,
718 syscon_vbase + U300_SYSCON_RSR, 4,
719 syscon_vbase + U300_SYSCON_CESR, 4,
720 U300_SYSCON_SBCER_GPIO_CLK_EN);
721 clk_register_clkdev(clk, NULL, "u300-gpio");
722 clk = syscon_clk_register(NULL, "keypad_clk", "slow_clk", 0, false,
723 syscon_vbase + U300_SYSCON_RSR, 5,
724 syscon_vbase + U300_SYSCON_CESR, 6,
725 U300_SYSCON_SBCER_KEYPAD_CLK_EN);
726 clk_register_clkdev(clk, NULL, "coh901461-keypad");
727 clk = syscon_clk_register(NULL, "rtc_clk", "slow_clk", 0, true,
728 syscon_vbase + U300_SYSCON_RSR, 6,
729 /* No clock enable register bit */
730 NULL, 0, 0xFFFFU);
731 clk_register_clkdev(clk, NULL, "rtc-coh901331");
732 clk = syscon_clk_register(NULL, "app_tmr_clk", "slow_clk", 0, false,
733 syscon_vbase + U300_SYSCON_RSR, 7,
734 syscon_vbase + U300_SYSCON_CESR, 7,
735 U300_SYSCON_SBCER_APP_TMR_CLK_EN);
736 clk_register_clkdev(clk, NULL, "apptimer");
737 clk = syscon_clk_register(NULL, "acc_tmr_clk", "slow_clk", 0, false,
738 syscon_vbase + U300_SYSCON_RSR, 8,
739 syscon_vbase + U300_SYSCON_CESR, 8,
740 U300_SYSCON_SBCER_ACC_TMR_CLK_EN);
741 clk_register_clkdev(clk, NULL, "timer");
742
743 /* Then this special MMC/SD clock */
744 clk = mclk_clk_register(NULL, "mmc_clk", "mmc_p_clk", false);
745 clk_register_clkdev(clk, NULL, "mmci");
746}
diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c
new file mode 100644
index 000000000000..e7b7765e85f3
--- /dev/null
+++ b/drivers/clk/clk-wm831x.c
@@ -0,0 +1,428 @@
1/*
2 * WM831x clock control
3 *
4 * Copyright 2011-2 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#include <linux/clk.h>
16#include <linux/clk-provider.h>
17#include <linux/delay.h>
18#include <linux/module.h>
19#include <linux/slab.h>
20#include <linux/platform_device.h>
21#include <linux/mfd/wm831x/core.h>
22
23struct wm831x_clk {
24 struct wm831x *wm831x;
25 struct clk_hw xtal_hw;
26 struct clk_hw fll_hw;
27 struct clk_hw clkout_hw;
28 struct clk *xtal;
29 struct clk *fll;
30 struct clk *clkout;
31 bool xtal_ena;
32};
33
34static int wm831x_xtal_is_enabled(struct clk_hw *hw)
35{
36 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
37 xtal_hw);
38
39 return clkdata->xtal_ena;
40}
41
42static unsigned long wm831x_xtal_recalc_rate(struct clk_hw *hw,
43 unsigned long parent_rate)
44{
45 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
46 xtal_hw);
47
48 if (clkdata->xtal_ena)
49 return 32768;
50 else
51 return 0;
52}
53
54static const struct clk_ops wm831x_xtal_ops = {
55 .is_enabled = wm831x_xtal_is_enabled,
56 .recalc_rate = wm831x_xtal_recalc_rate,
57};
58
59static struct clk_init_data wm831x_xtal_init = {
60 .name = "xtal",
61 .ops = &wm831x_xtal_ops,
62 .flags = CLK_IS_ROOT,
63};
64
65static const unsigned long wm831x_fll_auto_rates[] = {
66 2048000,
67 11289600,
68 12000000,
69 12288000,
70 19200000,
71 22579600,
72 24000000,
73 24576000,
74};
75
76static int wm831x_fll_is_enabled(struct clk_hw *hw)
77{
78 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
79 fll_hw);
80 struct wm831x *wm831x = clkdata->wm831x;
81 int ret;
82
83 ret = wm831x_reg_read(wm831x, WM831X_FLL_CONTROL_1);
84 if (ret < 0) {
85 dev_err(wm831x->dev, "Unable to read FLL_CONTROL_1: %d\n",
86 ret);
87 return true;
88 }
89
90 return (ret & WM831X_FLL_ENA) != 0;
91}
92
93static int wm831x_fll_prepare(struct clk_hw *hw)
94{
95 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
96 fll_hw);
97 struct wm831x *wm831x = clkdata->wm831x;
98 int ret;
99
100 ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_2,
101 WM831X_FLL_ENA, WM831X_FLL_ENA);
102 if (ret != 0)
103 dev_crit(wm831x->dev, "Failed to enable FLL: %d\n", ret);
104
105 usleep_range(2000, 2000);
106
107 return ret;
108}
109
110static void wm831x_fll_unprepare(struct clk_hw *hw)
111{
112 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
113 fll_hw);
114 struct wm831x *wm831x = clkdata->wm831x;
115 int ret;
116
117 ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_2, WM831X_FLL_ENA, 0);
118 if (ret != 0)
119 dev_crit(wm831x->dev, "Failed to disaable FLL: %d\n", ret);
120}
121
122static unsigned long wm831x_fll_recalc_rate(struct clk_hw *hw,
123 unsigned long parent_rate)
124{
125 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
126 fll_hw);
127 struct wm831x *wm831x = clkdata->wm831x;
128 int ret;
129
130 ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
131 if (ret < 0) {
132 dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
133 ret);
134 return 0;
135 }
136
137 if (ret & WM831X_FLL_AUTO)
138 return wm831x_fll_auto_rates[ret & WM831X_FLL_AUTO_FREQ_MASK];
139
140 dev_err(wm831x->dev, "FLL only supported in AUTO mode\n");
141
142 return 0;
143}
144
145static long wm831x_fll_round_rate(struct clk_hw *hw, unsigned long rate,
146 unsigned long *unused)
147{
148 int best = 0;
149 int i;
150
151 for (i = 0; i < ARRAY_SIZE(wm831x_fll_auto_rates); i++)
152 if (abs(wm831x_fll_auto_rates[i] - rate) <
153 abs(wm831x_fll_auto_rates[best] - rate))
154 best = i;
155
156 return wm831x_fll_auto_rates[best];
157}
158
159static int wm831x_fll_set_rate(struct clk_hw *hw, unsigned long rate,
160 unsigned long parent_rate)
161{
162 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
163 fll_hw);
164 struct wm831x *wm831x = clkdata->wm831x;
165 int i;
166
167 for (i = 0; i < ARRAY_SIZE(wm831x_fll_auto_rates); i++)
168 if (wm831x_fll_auto_rates[i] == rate)
169 break;
170 if (i == ARRAY_SIZE(wm831x_fll_auto_rates))
171 return -EINVAL;
172
173 if (wm831x_fll_is_enabled(hw))
174 return -EPERM;
175
176 return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_2,
177 WM831X_FLL_AUTO_FREQ_MASK, i);
178}
179
180static const char *wm831x_fll_parents[] = {
181 "xtal",
182 "clkin",
183};
184
185static u8 wm831x_fll_get_parent(struct clk_hw *hw)
186{
187 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
188 fll_hw);
189 struct wm831x *wm831x = clkdata->wm831x;
190 int ret;
191
192 /* AUTO mode is always clocked from the crystal */
193 ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
194 if (ret < 0) {
195 dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
196 ret);
197 return 0;
198 }
199
200 if (ret & WM831X_FLL_AUTO)
201 return 0;
202
203 ret = wm831x_reg_read(wm831x, WM831X_FLL_CONTROL_5);
204 if (ret < 0) {
205 dev_err(wm831x->dev, "Unable to read FLL_CONTROL_5: %d\n",
206 ret);
207 return 0;
208 }
209
210 switch (ret & WM831X_FLL_CLK_SRC_MASK) {
211 case 0:
212 return 0;
213 case 1:
214 return 1;
215 default:
216 dev_err(wm831x->dev, "Unsupported FLL clock source %d\n",
217 ret & WM831X_FLL_CLK_SRC_MASK);
218 return 0;
219 }
220}
221
222static const struct clk_ops wm831x_fll_ops = {
223 .is_enabled = wm831x_fll_is_enabled,
224 .prepare = wm831x_fll_prepare,
225 .unprepare = wm831x_fll_unprepare,
226 .round_rate = wm831x_fll_round_rate,
227 .recalc_rate = wm831x_fll_recalc_rate,
228 .set_rate = wm831x_fll_set_rate,
229 .get_parent = wm831x_fll_get_parent,
230};
231
232static struct clk_init_data wm831x_fll_init = {
233 .name = "fll",
234 .ops = &wm831x_fll_ops,
235 .parent_names = wm831x_fll_parents,
236 .num_parents = ARRAY_SIZE(wm831x_fll_parents),
237 .flags = CLK_SET_RATE_GATE,
238};
239
240static int wm831x_clkout_is_enabled(struct clk_hw *hw)
241{
242 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
243 clkout_hw);
244 struct wm831x *wm831x = clkdata->wm831x;
245 int ret;
246
247 ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_1);
248 if (ret < 0) {
249 dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",
250 ret);
251 return true;
252 }
253
254 return (ret & WM831X_CLKOUT_ENA) != 0;
255}
256
257static int wm831x_clkout_prepare(struct clk_hw *hw)
258{
259 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
260 clkout_hw);
261 struct wm831x *wm831x = clkdata->wm831x;
262 int ret;
263
264 ret = wm831x_reg_unlock(wm831x);
265 if (ret != 0) {
266 dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret);
267 return ret;
268 }
269
270 ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
271 WM831X_CLKOUT_ENA, WM831X_CLKOUT_ENA);
272 if (ret != 0)
273 dev_crit(wm831x->dev, "Failed to enable CLKOUT: %d\n", ret);
274
275 wm831x_reg_lock(wm831x);
276
277 return ret;
278}
279
280static void wm831x_clkout_unprepare(struct clk_hw *hw)
281{
282 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
283 clkout_hw);
284 struct wm831x *wm831x = clkdata->wm831x;
285 int ret;
286
287 ret = wm831x_reg_unlock(wm831x);
288 if (ret != 0) {
289 dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret);
290 return;
291 }
292
293 ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
294 WM831X_CLKOUT_ENA, 0);
295 if (ret != 0)
296 dev_crit(wm831x->dev, "Failed to disable CLKOUT: %d\n", ret);
297
298 wm831x_reg_lock(wm831x);
299}
300
301static const char *wm831x_clkout_parents[] = {
302 "xtal",
303 "fll",
304};
305
306static u8 wm831x_clkout_get_parent(struct clk_hw *hw)
307{
308 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
309 clkout_hw);
310 struct wm831x *wm831x = clkdata->wm831x;
311 int ret;
312
313 ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_1);
314 if (ret < 0) {
315 dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",
316 ret);
317 return 0;
318 }
319
320 if (ret & WM831X_CLKOUT_SRC)
321 return 0;
322 else
323 return 1;
324}
325
326static int wm831x_clkout_set_parent(struct clk_hw *hw, u8 parent)
327{
328 struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
329 clkout_hw);
330 struct wm831x *wm831x = clkdata->wm831x;
331
332 return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
333 WM831X_CLKOUT_SRC,
334 parent << WM831X_CLKOUT_SRC_SHIFT);
335}
336
337static const struct clk_ops wm831x_clkout_ops = {
338 .is_enabled = wm831x_clkout_is_enabled,
339 .prepare = wm831x_clkout_prepare,
340 .unprepare = wm831x_clkout_unprepare,
341 .get_parent = wm831x_clkout_get_parent,
342 .set_parent = wm831x_clkout_set_parent,
343};
344
345static struct clk_init_data wm831x_clkout_init = {
346 .name = "clkout",
347 .ops = &wm831x_clkout_ops,
348 .parent_names = wm831x_clkout_parents,
349 .num_parents = ARRAY_SIZE(wm831x_clkout_parents),
350 .flags = CLK_SET_RATE_PARENT,
351};
352
353static __devinit int wm831x_clk_probe(struct platform_device *pdev)
354{
355 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
356 struct wm831x_clk *clkdata;
357 int ret;
358
359 clkdata = devm_kzalloc(&pdev->dev, sizeof(*clkdata), GFP_KERNEL);
360 if (!clkdata)
361 return -ENOMEM;
362
363 /* XTAL_ENA can only be set via OTP/InstantConfig so just read once */
364 ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
365 if (ret < 0) {
366 dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
367 ret);
368 return ret;
369 }
370 clkdata->xtal_ena = ret & WM831X_XTAL_ENA;
371
372 clkdata->xtal_hw.init = &wm831x_xtal_init;
373 clkdata->xtal = clk_register(&pdev->dev, &clkdata->xtal_hw);
374 if (!clkdata->xtal)
375 return -EINVAL;
376
377 clkdata->fll_hw.init = &wm831x_fll_init;
378 clkdata->fll = clk_register(&pdev->dev, &clkdata->fll_hw);
379 if (!clkdata->fll) {
380 ret = -EINVAL;
381 goto err_xtal;
382 }
383
384 clkdata->clkout_hw.init = &wm831x_clkout_init;
385 clkdata->clkout = clk_register(&pdev->dev, &clkdata->clkout_hw);
386 if (!clkdata->clkout) {
387 ret = -EINVAL;
388 goto err_fll;
389 }
390
391 dev_set_drvdata(&pdev->dev, clkdata);
392
393 return 0;
394
395err_fll:
396 clk_unregister(clkdata->fll);
397err_xtal:
398 clk_unregister(clkdata->xtal);
399 return ret;
400}
401
402static int __devexit wm831x_clk_remove(struct platform_device *pdev)
403{
404 struct wm831x_clk *clkdata = dev_get_drvdata(&pdev->dev);
405
406 clk_unregister(clkdata->clkout);
407 clk_unregister(clkdata->fll);
408 clk_unregister(clkdata->xtal);
409
410 return 0;
411}
412
413static struct platform_driver wm831x_clk_driver = {
414 .probe = wm831x_clk_probe,
415 .remove = __devexit_p(wm831x_clk_remove),
416 .driver = {
417 .name = "wm831x-clk",
418 .owner = THIS_MODULE,
419 },
420};
421
422module_platform_driver(wm831x_clk_driver);
423
424/* Module information */
425MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
426MODULE_DESCRIPTION("WM831x clock driver");
427MODULE_LICENSE("GPL");
428MODULE_ALIAS("platform:wm831x-clk");
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 687b00d67c8a..c87fdd710560 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -16,6 +16,7 @@
16#include <linux/err.h> 16#include <linux/err.h>
17#include <linux/list.h> 17#include <linux/list.h>
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/of.h>
19 20
20static DEFINE_SPINLOCK(enable_lock); 21static DEFINE_SPINLOCK(enable_lock);
21static DEFINE_MUTEX(prepare_lock); 22static DEFINE_MUTEX(prepare_lock);
@@ -850,18 +851,21 @@ static void clk_change_rate(struct clk *clk)
850{ 851{
851 struct clk *child; 852 struct clk *child;
852 unsigned long old_rate; 853 unsigned long old_rate;
854 unsigned long best_parent_rate = 0;
853 struct hlist_node *tmp; 855 struct hlist_node *tmp;
854 856
855 old_rate = clk->rate; 857 old_rate = clk->rate;
856 858
859 if (clk->parent)
860 best_parent_rate = clk->parent->rate;
861
857 if (clk->ops->set_rate) 862 if (clk->ops->set_rate)
858 clk->ops->set_rate(clk->hw, clk->new_rate, clk->parent->rate); 863 clk->ops->set_rate(clk->hw, clk->new_rate, best_parent_rate);
859 864
860 if (clk->ops->recalc_rate) 865 if (clk->ops->recalc_rate)
861 clk->rate = clk->ops->recalc_rate(clk->hw, 866 clk->rate = clk->ops->recalc_rate(clk->hw, best_parent_rate);
862 clk->parent->rate);
863 else 867 else
864 clk->rate = clk->parent->rate; 868 clk->rate = best_parent_rate;
865 869
866 if (clk->notifier_count && old_rate != clk->rate) 870 if (clk->notifier_count && old_rate != clk->rate)
867 __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate); 871 __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate);
@@ -999,7 +1003,7 @@ static struct clk *__clk_init_parent(struct clk *clk)
999 1003
1000 if (!clk->parents) 1004 if (!clk->parents)
1001 clk->parents = 1005 clk->parents =
1002 kmalloc((sizeof(struct clk*) * clk->num_parents), 1006 kzalloc((sizeof(struct clk*) * clk->num_parents),
1003 GFP_KERNEL); 1007 GFP_KERNEL);
1004 1008
1005 if (!clk->parents) 1009 if (!clk->parents)
@@ -1064,21 +1068,24 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent)
1064 1068
1065 old_parent = clk->parent; 1069 old_parent = clk->parent;
1066 1070
1067 /* find index of new parent clock using cached parent ptrs */ 1071 if (!clk->parents)
1068 for (i = 0; i < clk->num_parents; i++) 1072 clk->parents = kzalloc((sizeof(struct clk*) * clk->num_parents),
1069 if (clk->parents[i] == parent) 1073 GFP_KERNEL);
1070 break;
1071 1074
1072 /* 1075 /*
1073 * find index of new parent clock using string name comparison 1076 * find index of new parent clock using cached parent ptrs,
1074 * also try to cache the parent to avoid future calls to __clk_lookup 1077 * or if not yet cached, use string name comparison and cache
1078 * them now to avoid future calls to __clk_lookup.
1075 */ 1079 */
1076 if (i == clk->num_parents) 1080 for (i = 0; i < clk->num_parents; i++) {
1077 for (i = 0; i < clk->num_parents; i++) 1081 if (clk->parents && clk->parents[i] == parent)
1078 if (!strcmp(clk->parent_names[i], parent->name)) { 1082 break;
1083 else if (!strcmp(clk->parent_names[i], parent->name)) {
1084 if (clk->parents)
1079 clk->parents[i] = __clk_lookup(parent->name); 1085 clk->parents[i] = __clk_lookup(parent->name);
1080 break; 1086 break;
1081 } 1087 }
1088 }
1082 1089
1083 if (i == clk->num_parents) { 1090 if (i == clk->num_parents) {
1084 pr_debug("%s: clock %s is not a possible parent of clock %s\n", 1091 pr_debug("%s: clock %s is not a possible parent of clock %s\n",
@@ -1229,8 +1236,8 @@ int __clk_init(struct device *dev, struct clk *clk)
1229 * If clk->parents is not NULL we skip this entire block. This allows 1236 * If clk->parents is not NULL we skip this entire block. This allows
1230 * for clock drivers to statically initialize clk->parents. 1237 * for clock drivers to statically initialize clk->parents.
1231 */ 1238 */
1232 if (clk->num_parents && !clk->parents) { 1239 if (clk->num_parents > 1 && !clk->parents) {
1233 clk->parents = kmalloc((sizeof(struct clk*) * clk->num_parents), 1240 clk->parents = kzalloc((sizeof(struct clk*) * clk->num_parents),
1234 GFP_KERNEL); 1241 GFP_KERNEL);
1235 /* 1242 /*
1236 * __clk_lookup returns NULL for parents that have not been 1243 * __clk_lookup returns NULL for parents that have not been
@@ -1544,3 +1551,142 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
1544 return ret; 1551 return ret;
1545} 1552}
1546EXPORT_SYMBOL_GPL(clk_notifier_unregister); 1553EXPORT_SYMBOL_GPL(clk_notifier_unregister);
1554
1555#ifdef CONFIG_OF
1556/**
1557 * struct of_clk_provider - Clock provider registration structure
1558 * @link: Entry in global list of clock providers
1559 * @node: Pointer to device tree node of clock provider
1560 * @get: Get clock callback. Returns NULL or a struct clk for the
1561 * given clock specifier
1562 * @data: context pointer to be passed into @get callback
1563 */
1564struct of_clk_provider {
1565 struct list_head link;
1566
1567 struct device_node *node;
1568 struct clk *(*get)(struct of_phandle_args *clkspec, void *data);
1569 void *data;
1570};
1571
1572static LIST_HEAD(of_clk_providers);
1573static DEFINE_MUTEX(of_clk_lock);
1574
1575struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
1576 void *data)
1577{
1578 return data;
1579}
1580EXPORT_SYMBOL_GPL(of_clk_src_simple_get);
1581
1582/**
1583 * of_clk_add_provider() - Register a clock provider for a node
1584 * @np: Device node pointer associated with clock provider
1585 * @clk_src_get: callback for decoding clock
1586 * @data: context pointer for @clk_src_get callback.
1587 */
1588int of_clk_add_provider(struct device_node *np,
1589 struct clk *(*clk_src_get)(struct of_phandle_args *clkspec,
1590 void *data),
1591 void *data)
1592{
1593 struct of_clk_provider *cp;
1594
1595 cp = kzalloc(sizeof(struct of_clk_provider), GFP_KERNEL);
1596 if (!cp)
1597 return -ENOMEM;
1598
1599 cp->node = of_node_get(np);
1600 cp->data = data;
1601 cp->get = clk_src_get;
1602
1603 mutex_lock(&of_clk_lock);
1604 list_add(&cp->link, &of_clk_providers);
1605 mutex_unlock(&of_clk_lock);
1606 pr_debug("Added clock from %s\n", np->full_name);
1607
1608 return 0;
1609}
1610EXPORT_SYMBOL_GPL(of_clk_add_provider);
1611
1612/**
1613 * of_clk_del_provider() - Remove a previously registered clock provider
1614 * @np: Device node pointer associated with clock provider
1615 */
1616void of_clk_del_provider(struct device_node *np)
1617{
1618 struct of_clk_provider *cp;
1619
1620 mutex_lock(&of_clk_lock);
1621 list_for_each_entry(cp, &of_clk_providers, link) {
1622 if (cp->node == np) {
1623 list_del(&cp->link);
1624 of_node_put(cp->node);
1625 kfree(cp);
1626 break;
1627 }
1628 }
1629 mutex_unlock(&of_clk_lock);
1630}
1631EXPORT_SYMBOL_GPL(of_clk_del_provider);
1632
1633struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec)
1634{
1635 struct of_clk_provider *provider;
1636 struct clk *clk = ERR_PTR(-ENOENT);
1637
1638 /* Check if we have such a provider in our array */
1639 mutex_lock(&of_clk_lock);
1640 list_for_each_entry(provider, &of_clk_providers, link) {
1641 if (provider->node == clkspec->np)
1642 clk = provider->get(clkspec, provider->data);
1643 if (!IS_ERR(clk))
1644 break;
1645 }
1646 mutex_unlock(&of_clk_lock);
1647
1648 return clk;
1649}
1650
1651const char *of_clk_get_parent_name(struct device_node *np, int index)
1652{
1653 struct of_phandle_args clkspec;
1654 const char *clk_name;
1655 int rc;
1656
1657 if (index < 0)
1658 return NULL;
1659
1660 rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
1661 &clkspec);
1662 if (rc)
1663 return NULL;
1664
1665 if (of_property_read_string_index(clkspec.np, "clock-output-names",
1666 clkspec.args_count ? clkspec.args[0] : 0,
1667 &clk_name) < 0)
1668 clk_name = clkspec.np->name;
1669
1670 of_node_put(clkspec.np);
1671 return clk_name;
1672}
1673EXPORT_SYMBOL_GPL(of_clk_get_parent_name);
1674
1675/**
1676 * of_clk_init() - Scan and init clock providers from the DT
1677 * @matches: array of compatible values and init functions for providers.
1678 *
1679 * This function scans the device tree for matching clock providers and
1680 * calls their initialization functions
1681 */
1682void __init of_clk_init(const struct of_device_id *matches)
1683{
1684 struct device_node *np;
1685
1686 for_each_matching_node(np, matches) {
1687 const struct of_device_id *match = of_match_node(matches, np);
1688 of_clk_init_cb_t clk_init_cb = match->data;
1689 clk_init_cb(np);
1690 }
1691}
1692#endif
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index c535cf8c5770..20649b3c88fe 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -19,10 +19,80 @@
19#include <linux/mutex.h> 19#include <linux/mutex.h>
20#include <linux/clk.h> 20#include <linux/clk.h>
21#include <linux/clkdev.h> 21#include <linux/clkdev.h>
22#include <linux/of.h>
22 23
23static LIST_HEAD(clocks); 24static LIST_HEAD(clocks);
24static DEFINE_MUTEX(clocks_mutex); 25static DEFINE_MUTEX(clocks_mutex);
25 26
27#ifdef CONFIG_OF
28struct clk *of_clk_get(struct device_node *np, int index)
29{
30 struct of_phandle_args clkspec;
31 struct clk *clk;
32 int rc;
33
34 if (index < 0)
35 return ERR_PTR(-EINVAL);
36
37 rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
38 &clkspec);
39 if (rc)
40 return ERR_PTR(rc);
41
42 clk = of_clk_get_from_provider(&clkspec);
43 of_node_put(clkspec.np);
44 return clk;
45}
46EXPORT_SYMBOL(of_clk_get);
47
48/**
49 * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node
50 * @np: pointer to clock consumer node
51 * @name: name of consumer's clock input, or NULL for the first clock reference
52 *
53 * This function parses the clocks and clock-names properties,
54 * and uses them to look up the struct clk from the registered list of clock
55 * providers.
56 */
57struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
58{
59 struct clk *clk = ERR_PTR(-ENOENT);
60
61 /* Walk up the tree of devices looking for a clock that matches */
62 while (np) {
63 int index = 0;
64
65 /*
66 * For named clocks, first look up the name in the
67 * "clock-names" property. If it cannot be found, then
68 * index will be an error code, and of_clk_get() will fail.
69 */
70 if (name)
71 index = of_property_match_string(np, "clock-names", name);
72 clk = of_clk_get(np, index);
73 if (!IS_ERR(clk))
74 break;
75 else if (name && index >= 0) {
76 pr_err("ERROR: could not get clock %s:%s(%i)\n",
77 np->full_name, name ? name : "", index);
78 return clk;
79 }
80
81 /*
82 * No matching clock found on this node. If the parent node
83 * has a "clock-ranges" property, then we can try one of its
84 * clocks.
85 */
86 np = np->parent;
87 if (np && !of_get_property(np, "clock-ranges", NULL))
88 break;
89 }
90
91 return clk;
92}
93EXPORT_SYMBOL(of_clk_get_by_name);
94#endif
95
26/* 96/*
27 * Find the correct struct clk for the device and connection ID. 97 * Find the correct struct clk for the device and connection ID.
28 * We do slightly fuzzy matching here: 98 * We do slightly fuzzy matching here:
@@ -83,6 +153,13 @@ EXPORT_SYMBOL(clk_get_sys);
83struct clk *clk_get(struct device *dev, const char *con_id) 153struct clk *clk_get(struct device *dev, const char *con_id)
84{ 154{
85 const char *dev_id = dev ? dev_name(dev) : NULL; 155 const char *dev_id = dev ? dev_name(dev) : NULL;
156 struct clk *clk;
157
158 if (dev) {
159 clk = of_clk_get_by_name(dev->of_node, con_id);
160 if (clk && __clk_get(clk))
161 return clk;
162 }
86 163
87 return clk_get_sys(dev_id, con_id); 164 return clk_get_sys(dev_id, con_id);
88} 165}
diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c
index c14b021c4a68..844043ad0fe4 100644
--- a/drivers/clk/mxs/clk-imx23.c
+++ b/drivers/clk/mxs/clk-imx23.c
@@ -71,7 +71,7 @@ static void __init clk_misc_init(void)
71 __mxs_setl(30 << BP_FRAC_IOFRAC, FRAC); 71 __mxs_setl(30 << BP_FRAC_IOFRAC, FRAC);
72} 72}
73 73
74static struct clk_lookup uart_lookups[] __initdata = { 74static struct clk_lookup uart_lookups[] = {
75 { .dev_id = "duart", }, 75 { .dev_id = "duart", },
76 { .dev_id = "mxs-auart.0", }, 76 { .dev_id = "mxs-auart.0", },
77 { .dev_id = "mxs-auart.1", }, 77 { .dev_id = "mxs-auart.1", },
@@ -80,31 +80,31 @@ static struct clk_lookup uart_lookups[] __initdata = {
80 { .dev_id = "80070000.serial", }, 80 { .dev_id = "80070000.serial", },
81}; 81};
82 82
83static struct clk_lookup hbus_lookups[] __initdata = { 83static struct clk_lookup hbus_lookups[] = {
84 { .dev_id = "imx23-dma-apbh", }, 84 { .dev_id = "imx23-dma-apbh", },
85 { .dev_id = "80004000.dma-apbh", }, 85 { .dev_id = "80004000.dma-apbh", },
86}; 86};
87 87
88static struct clk_lookup xbus_lookups[] __initdata = { 88static struct clk_lookup xbus_lookups[] = {
89 { .dev_id = "duart", .con_id = "apb_pclk"}, 89 { .dev_id = "duart", .con_id = "apb_pclk"},
90 { .dev_id = "80070000.serial", .con_id = "apb_pclk"}, 90 { .dev_id = "80070000.serial", .con_id = "apb_pclk"},
91 { .dev_id = "imx23-dma-apbx", }, 91 { .dev_id = "imx23-dma-apbx", },
92 { .dev_id = "80024000.dma-apbx", }, 92 { .dev_id = "80024000.dma-apbx", },
93}; 93};
94 94
95static struct clk_lookup ssp_lookups[] __initdata = { 95static struct clk_lookup ssp_lookups[] = {
96 { .dev_id = "imx23-mmc.0", }, 96 { .dev_id = "imx23-mmc.0", },
97 { .dev_id = "imx23-mmc.1", }, 97 { .dev_id = "imx23-mmc.1", },
98 { .dev_id = "80010000.ssp", }, 98 { .dev_id = "80010000.ssp", },
99 { .dev_id = "80034000.ssp", }, 99 { .dev_id = "80034000.ssp", },
100}; 100};
101 101
102static struct clk_lookup lcdif_lookups[] __initdata = { 102static struct clk_lookup lcdif_lookups[] = {
103 { .dev_id = "imx23-fb", }, 103 { .dev_id = "imx23-fb", },
104 { .dev_id = "80030000.lcdif", }, 104 { .dev_id = "80030000.lcdif", },
105}; 105};
106 106
107static struct clk_lookup gpmi_lookups[] __initdata = { 107static struct clk_lookup gpmi_lookups[] = {
108 { .dev_id = "imx23-gpmi-nand", }, 108 { .dev_id = "imx23-gpmi-nand", },
109 { .dev_id = "8000c000.gpmi-nand", }, 109 { .dev_id = "8000c000.gpmi-nand", },
110}; 110};
diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
index eb430bb60630..e3aab67b3eb7 100644
--- a/drivers/clk/mxs/clk-imx28.c
+++ b/drivers/clk/mxs/clk-imx28.c
@@ -120,7 +120,7 @@ static void __init clk_misc_init(void)
120 writel_relaxed(val, FRAC0); 120 writel_relaxed(val, FRAC0);
121} 121}
122 122
123static struct clk_lookup uart_lookups[] __initdata = { 123static struct clk_lookup uart_lookups[] = {
124 { .dev_id = "duart", }, 124 { .dev_id = "duart", },
125 { .dev_id = "mxs-auart.0", }, 125 { .dev_id = "mxs-auart.0", },
126 { .dev_id = "mxs-auart.1", }, 126 { .dev_id = "mxs-auart.1", },
@@ -135,71 +135,71 @@ static struct clk_lookup uart_lookups[] __initdata = {
135 { .dev_id = "80074000.serial", }, 135 { .dev_id = "80074000.serial", },
136}; 136};
137 137
138static struct clk_lookup hbus_lookups[] __initdata = { 138static struct clk_lookup hbus_lookups[] = {
139 { .dev_id = "imx28-dma-apbh", }, 139 { .dev_id = "imx28-dma-apbh", },
140 { .dev_id = "80004000.dma-apbh", }, 140 { .dev_id = "80004000.dma-apbh", },
141}; 141};
142 142
143static struct clk_lookup xbus_lookups[] __initdata = { 143static struct clk_lookup xbus_lookups[] = {
144 { .dev_id = "duart", .con_id = "apb_pclk"}, 144 { .dev_id = "duart", .con_id = "apb_pclk"},
145 { .dev_id = "80074000.serial", .con_id = "apb_pclk"}, 145 { .dev_id = "80074000.serial", .con_id = "apb_pclk"},
146 { .dev_id = "imx28-dma-apbx", }, 146 { .dev_id = "imx28-dma-apbx", },
147 { .dev_id = "80024000.dma-apbx", }, 147 { .dev_id = "80024000.dma-apbx", },
148}; 148};
149 149
150static struct clk_lookup ssp0_lookups[] __initdata = { 150static struct clk_lookup ssp0_lookups[] = {
151 { .dev_id = "imx28-mmc.0", }, 151 { .dev_id = "imx28-mmc.0", },
152 { .dev_id = "80010000.ssp", }, 152 { .dev_id = "80010000.ssp", },
153}; 153};
154 154
155static struct clk_lookup ssp1_lookups[] __initdata = { 155static struct clk_lookup ssp1_lookups[] = {
156 { .dev_id = "imx28-mmc.1", }, 156 { .dev_id = "imx28-mmc.1", },
157 { .dev_id = "80012000.ssp", }, 157 { .dev_id = "80012000.ssp", },
158}; 158};
159 159
160static struct clk_lookup ssp2_lookups[] __initdata = { 160static struct clk_lookup ssp2_lookups[] = {
161 { .dev_id = "imx28-mmc.2", }, 161 { .dev_id = "imx28-mmc.2", },
162 { .dev_id = "80014000.ssp", }, 162 { .dev_id = "80014000.ssp", },
163}; 163};
164 164
165static struct clk_lookup ssp3_lookups[] __initdata = { 165static struct clk_lookup ssp3_lookups[] = {
166 { .dev_id = "imx28-mmc.3", }, 166 { .dev_id = "imx28-mmc.3", },
167 { .dev_id = "80016000.ssp", }, 167 { .dev_id = "80016000.ssp", },
168}; 168};
169 169
170static struct clk_lookup lcdif_lookups[] __initdata = { 170static struct clk_lookup lcdif_lookups[] = {
171 { .dev_id = "imx28-fb", }, 171 { .dev_id = "imx28-fb", },
172 { .dev_id = "80030000.lcdif", }, 172 { .dev_id = "80030000.lcdif", },
173}; 173};
174 174
175static struct clk_lookup gpmi_lookups[] __initdata = { 175static struct clk_lookup gpmi_lookups[] = {
176 { .dev_id = "imx28-gpmi-nand", }, 176 { .dev_id = "imx28-gpmi-nand", },
177 { .dev_id = "8000c000.gpmi-nand", }, 177 { .dev_id = "8000c000.gpmi-nand", },
178}; 178};
179 179
180static struct clk_lookup fec_lookups[] __initdata = { 180static struct clk_lookup fec_lookups[] = {
181 { .dev_id = "imx28-fec.0", }, 181 { .dev_id = "imx28-fec.0", },
182 { .dev_id = "imx28-fec.1", }, 182 { .dev_id = "imx28-fec.1", },
183 { .dev_id = "800f0000.ethernet", }, 183 { .dev_id = "800f0000.ethernet", },
184 { .dev_id = "800f4000.ethernet", }, 184 { .dev_id = "800f4000.ethernet", },
185}; 185};
186 186
187static struct clk_lookup can0_lookups[] __initdata = { 187static struct clk_lookup can0_lookups[] = {
188 { .dev_id = "flexcan.0", }, 188 { .dev_id = "flexcan.0", },
189 { .dev_id = "80032000.can", }, 189 { .dev_id = "80032000.can", },
190}; 190};
191 191
192static struct clk_lookup can1_lookups[] __initdata = { 192static struct clk_lookup can1_lookups[] = {
193 { .dev_id = "flexcan.1", }, 193 { .dev_id = "flexcan.1", },
194 { .dev_id = "80034000.can", }, 194 { .dev_id = "80034000.can", },
195}; 195};
196 196
197static struct clk_lookup saif0_lookups[] __initdata = { 197static struct clk_lookup saif0_lookups[] = {
198 { .dev_id = "mxs-saif.0", }, 198 { .dev_id = "mxs-saif.0", },
199 { .dev_id = "80042000.saif", }, 199 { .dev_id = "80042000.saif", },
200}; 200};
201 201
202static struct clk_lookup saif1_lookups[] __initdata = { 202static struct clk_lookup saif1_lookups[] = {
203 { .dev_id = "mxs-saif.1", }, 203 { .dev_id = "mxs-saif.1", },
204 { .dev_id = "80046000.saif", }, 204 { .dev_id = "80046000.saif", },
205}; 205};
@@ -245,8 +245,8 @@ int __init mx28_clocks_init(void)
245 clks[pll2] = mxs_clk_pll("pll2", "ref_xtal", PLL2CTRL0, 23, 50000000); 245 clks[pll2] = mxs_clk_pll("pll2", "ref_xtal", PLL2CTRL0, 23, 50000000);
246 clks[ref_cpu] = mxs_clk_ref("ref_cpu", "pll0", FRAC0, 0); 246 clks[ref_cpu] = mxs_clk_ref("ref_cpu", "pll0", FRAC0, 0);
247 clks[ref_emi] = mxs_clk_ref("ref_emi", "pll0", FRAC0, 1); 247 clks[ref_emi] = mxs_clk_ref("ref_emi", "pll0", FRAC0, 1);
248 clks[ref_io0] = mxs_clk_ref("ref_io0", "pll0", FRAC0, 2); 248 clks[ref_io1] = mxs_clk_ref("ref_io1", "pll0", FRAC0, 2);
249 clks[ref_io1] = mxs_clk_ref("ref_io1", "pll0", FRAC0, 3); 249 clks[ref_io0] = mxs_clk_ref("ref_io0", "pll0", FRAC0, 3);
250 clks[ref_pix] = mxs_clk_ref("ref_pix", "pll0", FRAC1, 0); 250 clks[ref_pix] = mxs_clk_ref("ref_pix", "pll0", FRAC1, 0);
251 clks[ref_hsadc] = mxs_clk_ref("ref_hsadc", "pll0", FRAC1, 1); 251 clks[ref_hsadc] = mxs_clk_ref("ref_hsadc", "pll0", FRAC1, 1);
252 clks[ref_gpmi] = mxs_clk_ref("ref_gpmi", "pll0", FRAC1, 2); 252 clks[ref_gpmi] = mxs_clk_ref("ref_gpmi", "pll0", FRAC1, 2);
diff --git a/drivers/clk/spear/clk-aux-synth.c b/drivers/clk/spear/clk-aux-synth.c
index af34074e702b..6756e7c3bc07 100644
--- a/drivers/clk/spear/clk-aux-synth.c
+++ b/drivers/clk/spear/clk-aux-synth.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * Copyright (C) 2012 ST Microelectronics 2 * Copyright (C) 2012 ST Microelectronics
3 * Viresh Kumar <viresh.kumar@st.com> 3 * Viresh Kumar <viresh.linux@gmail.com>
4 * 4 *
5 * This file is licensed under the terms of the GNU General Public 5 * This file is licensed under the terms of the GNU General Public
6 * License version 2. This program is licensed "as is" without any 6 * License version 2. This program is licensed "as is" without any
diff --git a/drivers/clk/spear/clk-frac-synth.c b/drivers/clk/spear/clk-frac-synth.c
index 4dbdb3fe18e0..958aa3ad1d60 100644
--- a/drivers/clk/spear/clk-frac-synth.c
+++ b/drivers/clk/spear/clk-frac-synth.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * Copyright (C) 2012 ST Microelectronics 2 * Copyright (C) 2012 ST Microelectronics
3 * Viresh Kumar <viresh.kumar@st.com> 3 * Viresh Kumar <viresh.linux@gmail.com>
4 * 4 *
5 * This file is licensed under the terms of the GNU General Public 5 * This file is licensed under the terms of the GNU General Public
6 * License version 2. This program is licensed "as is" without any 6 * License version 2. This program is licensed "as is" without any
diff --git a/drivers/clk/spear/clk-gpt-synth.c b/drivers/clk/spear/clk-gpt-synth.c
index b471c9762a97..1afc18c4effc 100644
--- a/drivers/clk/spear/clk-gpt-synth.c
+++ b/drivers/clk/spear/clk-gpt-synth.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * Copyright (C) 2012 ST Microelectronics 2 * Copyright (C) 2012 ST Microelectronics
3 * Viresh Kumar <viresh.kumar@st.com> 3 * Viresh Kumar <viresh.linux@gmail.com>
4 * 4 *
5 * This file is licensed under the terms of the GNU General Public 5 * This file is licensed under the terms of the GNU General Public
6 * License version 2. This program is licensed "as is" without any 6 * License version 2. This program is licensed "as is" without any
diff --git a/drivers/clk/spear/clk-vco-pll.c b/drivers/clk/spear/clk-vco-pll.c
index dcd4bdf4b0d9..5f1b6badeb15 100644
--- a/drivers/clk/spear/clk-vco-pll.c
+++ b/drivers/clk/spear/clk-vco-pll.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * Copyright (C) 2012 ST Microelectronics 2 * Copyright (C) 2012 ST Microelectronics
3 * Viresh Kumar <viresh.kumar@st.com> 3 * Viresh Kumar <viresh.linux@gmail.com>
4 * 4 *
5 * This file is licensed under the terms of the GNU General Public 5 * This file is licensed under the terms of the GNU General Public
6 * License version 2. This program is licensed "as is" without any 6 * License version 2. This program is licensed "as is" without any
diff --git a/drivers/clk/spear/clk.c b/drivers/clk/spear/clk.c
index 376d4e5ff326..7cd63788d546 100644
--- a/drivers/clk/spear/clk.c
+++ b/drivers/clk/spear/clk.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * Copyright (C) 2012 ST Microelectronics 2 * Copyright (C) 2012 ST Microelectronics
3 * Viresh Kumar <viresh.kumar@st.com> 3 * Viresh Kumar <viresh.linux@gmail.com>
4 * 4 *
5 * This file is licensed under the terms of the GNU General Public 5 * This file is licensed under the terms of the GNU General Public
6 * License version 2. This program is licensed "as is" without any 6 * License version 2. This program is licensed "as is" without any
diff --git a/drivers/clk/spear/clk.h b/drivers/clk/spear/clk.h
index 3321c46a071c..931737677dfa 100644
--- a/drivers/clk/spear/clk.h
+++ b/drivers/clk/spear/clk.h
@@ -2,7 +2,7 @@
2 * Clock framework definitions for SPEAr platform 2 * Clock framework definitions for SPEAr platform
3 * 3 *
4 * Copyright (C) 2012 ST Microelectronics 4 * Copyright (C) 2012 ST Microelectronics
5 * Viresh Kumar <viresh.kumar@st.com> 5 * Viresh Kumar <viresh.linux@gmail.com>
6 * 6 *
7 * This file is licensed under the terms of the GNU General Public 7 * This file is licensed under the terms of the GNU General Public
8 * License version 2. This program is licensed "as is" without any 8 * License version 2. This program is licensed "as is" without any
diff --git a/drivers/clk/spear/spear1310_clock.c b/drivers/clk/spear/spear1310_clock.c
index 42b68df9aeef..8f05652d53e6 100644
--- a/drivers/clk/spear/spear1310_clock.c
+++ b/drivers/clk/spear/spear1310_clock.c
@@ -4,7 +4,7 @@
4 * SPEAr1310 machine clock framework source file 4 * SPEAr1310 machine clock framework source file
5 * 5 *
6 * Copyright (C) 2012 ST Microelectronics 6 * Copyright (C) 2012 ST Microelectronics
7 * Viresh Kumar <viresh.kumar@st.com> 7 * Viresh Kumar <viresh.linux@gmail.com>
8 * 8 *
9 * This file is licensed under the terms of the GNU General Public 9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any 10 * License version 2. This program is licensed "as is" without any
diff --git a/drivers/clk/spear/spear1340_clock.c b/drivers/clk/spear/spear1340_clock.c
index f130919d5bf8..e3ea72162236 100644
--- a/drivers/clk/spear/spear1340_clock.c
+++ b/drivers/clk/spear/spear1340_clock.c
@@ -4,7 +4,7 @@
4 * SPEAr1340 machine clock framework source file 4 * SPEAr1340 machine clock framework source file
5 * 5 *
6 * Copyright (C) 2012 ST Microelectronics 6 * Copyright (C) 2012 ST Microelectronics
7 * Viresh Kumar <viresh.kumar@st.com> 7 * Viresh Kumar <viresh.linux@gmail.com>
8 * 8 *
9 * This file is licensed under the terms of the GNU General Public 9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any 10 * License version 2. This program is licensed "as is" without any
diff --git a/drivers/clk/spear/spear3xx_clock.c b/drivers/clk/spear/spear3xx_clock.c
index 440bb3e4c971..01dd6daff2a1 100644
--- a/drivers/clk/spear/spear3xx_clock.c
+++ b/drivers/clk/spear/spear3xx_clock.c
@@ -2,7 +2,7 @@
2 * SPEAr3xx machines clock framework source file 2 * SPEAr3xx machines clock framework source file
3 * 3 *
4 * Copyright (C) 2012 ST Microelectronics 4 * Copyright (C) 2012 ST Microelectronics
5 * Viresh Kumar <viresh.kumar@st.com> 5 * Viresh Kumar <viresh.linux@gmail.com>
6 * 6 *
7 * This file is licensed under the terms of the GNU General Public 7 * This file is licensed under the terms of the GNU General Public
8 * License version 2. This program is licensed "as is" without any 8 * License version 2. This program is licensed "as is" without any
diff --git a/drivers/clk/spear/spear6xx_clock.c b/drivers/clk/spear/spear6xx_clock.c
index f9a20b382304..61026ae564ab 100644
--- a/drivers/clk/spear/spear6xx_clock.c
+++ b/drivers/clk/spear/spear6xx_clock.c
@@ -2,7 +2,7 @@
2 * SPEAr6xx machines clock framework source file 2 * SPEAr6xx machines clock framework source file
3 * 3 *
4 * Copyright (C) 2012 ST Microelectronics 4 * Copyright (C) 2012 ST Microelectronics
5 * Viresh Kumar <viresh.kumar@st.com> 5 * Viresh Kumar <viresh.linux@gmail.com>
6 * 6 *
7 * This file is licensed under the terms of the GNU General Public 7 * This file is licensed under the terms of the GNU General Public
8 * License version 2. This program is licensed "as is" without any 8 * License version 2. This program is licensed "as is" without any
@@ -298,7 +298,7 @@ void __init spear6xx_clk_init(void)
298 298
299 clk = clk_register_gate(NULL, "gmac_clk", "ahb_clk", 0, PERIP1_CLK_ENB, 299 clk = clk_register_gate(NULL, "gmac_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
300 GMAC_CLK_ENB, 0, &_lock); 300 GMAC_CLK_ENB, 0, &_lock);
301 clk_register_clkdev(clk, NULL, "gmac"); 301 clk_register_clkdev(clk, NULL, "e0800000.ethernet");
302 302
303 clk = clk_register_gate(NULL, "i2c_clk", "ahb_clk", 0, PERIP1_CLK_ENB, 303 clk = clk_register_gate(NULL, "i2c_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
304 I2C_CLK_ENB, 0, &_lock); 304 I2C_CLK_ENB, 0, &_lock);
diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile
new file mode 100644
index 000000000000..50cf6a2ee693
--- /dev/null
+++ b/drivers/clk/versatile/Makefile
@@ -0,0 +1,3 @@
1# Makefile for Versatile-specific clocks
2obj-$(CONFIG_ICST) += clk-icst.o
3obj-$(CONFIG_ARCH_INTEGRATOR) += clk-integrator.o
diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c
new file mode 100644
index 000000000000..f555b50a5fa5
--- /dev/null
+++ b/drivers/clk/versatile/clk-icst.c
@@ -0,0 +1,100 @@
1/*
2 * Driver for the ICST307 VCO clock found in the ARM Reference designs.
3 * We wrap the custom interface from <asm/hardware/icst.h> into the generic
4 * clock framework.
5 *
6 * TODO: when all ARM reference designs are migrated to generic clocks, the
7 * ICST clock code from the ARM tree should probably be merged into this
8 * file.
9 */
10#include <linux/clk.h>
11#include <linux/clkdev.h>
12#include <linux/err.h>
13#include <linux/clk-provider.h>
14
15#include "clk-icst.h"
16
17/**
18 * struct clk_icst - ICST VCO clock wrapper
19 * @hw: corresponding clock hardware entry
20 * @params: parameters for this ICST instance
21 * @rate: current rate
22 * @setvco: function to commit ICST settings to hardware
23 */
24struct clk_icst {
25 struct clk_hw hw;
26 const struct icst_params *params;
27 unsigned long rate;
28 struct icst_vco (*getvco)(void);
29 void (*setvco)(struct icst_vco);
30};
31
32#define to_icst(_hw) container_of(_hw, struct clk_icst, hw)
33
34static unsigned long icst_recalc_rate(struct clk_hw *hw,
35 unsigned long parent_rate)
36{
37 struct clk_icst *icst = to_icst(hw);
38 struct icst_vco vco;
39
40 vco = icst->getvco();
41 icst->rate = icst_hz(icst->params, vco);
42 return icst->rate;
43}
44
45static long icst_round_rate(struct clk_hw *hw, unsigned long rate,
46 unsigned long *prate)
47{
48 struct clk_icst *icst = to_icst(hw);
49 struct icst_vco vco;
50
51 vco = icst_hz_to_vco(icst->params, rate);
52 return icst_hz(icst->params, vco);
53}
54
55static int icst_set_rate(struct clk_hw *hw, unsigned long rate,
56 unsigned long parent_rate)
57{
58 struct clk_icst *icst = to_icst(hw);
59 struct icst_vco vco;
60
61 vco = icst_hz_to_vco(icst->params, rate);
62 icst->rate = icst_hz(icst->params, vco);
63 icst->setvco(vco);
64 return 0;
65}
66
67static const struct clk_ops icst_ops = {
68 .recalc_rate = icst_recalc_rate,
69 .round_rate = icst_round_rate,
70 .set_rate = icst_set_rate,
71};
72
73struct clk * __init icst_clk_register(struct device *dev,
74 const struct clk_icst_desc *desc)
75{
76 struct clk *clk;
77 struct clk_icst *icst;
78 struct clk_init_data init;
79
80 icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL);
81 if (!icst) {
82 pr_err("could not allocate ICST clock!\n");
83 return ERR_PTR(-ENOMEM);
84 }
85 init.name = "icst";
86 init.ops = &icst_ops;
87 init.flags = CLK_IS_ROOT;
88 init.parent_names = NULL;
89 init.num_parents = 0;
90 icst->hw.init = &init;
91 icst->params = desc->params;
92 icst->getvco = desc->getvco;
93 icst->setvco = desc->setvco;
94
95 clk = clk_register(dev, &icst->hw);
96 if (IS_ERR(clk))
97 kfree(icst);
98
99 return clk;
100}
diff --git a/drivers/clk/versatile/clk-icst.h b/drivers/clk/versatile/clk-icst.h
new file mode 100644
index 000000000000..71b4c56c1410
--- /dev/null
+++ b/drivers/clk/versatile/clk-icst.h
@@ -0,0 +1,10 @@
1#include <asm/hardware/icst.h>
2
3struct clk_icst_desc {
4 const struct icst_params *params;
5 struct icst_vco (*getvco)(void);
6 void (*setvco)(struct icst_vco);
7};
8
9struct clk *icst_clk_register(struct device *dev,
10 const struct clk_icst_desc *desc);
diff --git a/drivers/clk/versatile/clk-integrator.c b/drivers/clk/versatile/clk-integrator.c
new file mode 100644
index 000000000000..a5053921bf7f
--- /dev/null
+++ b/drivers/clk/versatile/clk-integrator.c
@@ -0,0 +1,111 @@
1#include <linux/clk.h>
2#include <linux/clkdev.h>
3#include <linux/err.h>
4#include <linux/io.h>
5#include <linux/clk-provider.h>
6
7#include <mach/hardware.h>
8#include <mach/platform.h>
9
10#include "clk-icst.h"
11
12/*
13 * Implementation of the ARM Integrator/AP and Integrator/CP clock tree.
14 * Inspired by portions of:
15 * plat-versatile/clock.c and plat-versatile/include/plat/clock.h
16 */
17#define CM_LOCK (__io_address(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET)
18#define CM_AUXOSC (__io_address(INTEGRATOR_HDR_BASE)+0x1c)
19
20/**
21 * cp_auxvco_get() - get ICST VCO settings for the Integrator/CP
22 * @vco: ICST VCO parameters to update with hardware status
23 */
24static struct icst_vco cp_auxvco_get(void)
25{
26 u32 val;
27 struct icst_vco vco;
28
29 val = readl(CM_AUXOSC);
30 vco.v = val & 0x1ff;
31 vco.r = (val >> 9) & 0x7f;
32 vco.s = (val >> 16) & 03;
33 return vco;
34}
35
36/**
37 * cp_auxvco_set() - commit changes to Integrator/CP ICST VCO
38 * @vco: ICST VCO parameters to commit
39 */
40static void cp_auxvco_set(struct icst_vco vco)
41{
42 u32 val;
43
44 val = readl(CM_AUXOSC) & ~0x7ffff;
45 val |= vco.v | (vco.r << 9) | (vco.s << 16);
46
47 /* This magic unlocks the CM VCO so it can be controlled */
48 writel(0xa05f, CM_LOCK);
49 writel(val, CM_AUXOSC);
50 /* This locks the CM again */
51 writel(0, CM_LOCK);
52}
53
54static const struct icst_params cp_auxvco_params = {
55 .ref = 24000000,
56 .vco_max = ICST525_VCO_MAX_5V,
57 .vco_min = ICST525_VCO_MIN,
58 .vd_min = 8,
59 .vd_max = 263,
60 .rd_min = 3,
61 .rd_max = 65,
62 .s2div = icst525_s2div,
63 .idx2s = icst525_idx2s,
64};
65
66static const struct clk_icst_desc __initdata cp_icst_desc = {
67 .params = &cp_auxvco_params,
68 .getvco = cp_auxvco_get,
69 .setvco = cp_auxvco_set,
70};
71
72/*
73 * integrator_clk_init() - set up the integrator clock tree
74 * @is_cp: pass true if it's the Integrator/CP else AP is assumed
75 */
76void __init integrator_clk_init(bool is_cp)
77{
78 struct clk *clk;
79
80 /* APB clock dummy */
81 clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
82 clk_register_clkdev(clk, "apb_pclk", NULL);
83
84 /* UART reference clock */
85 clk = clk_register_fixed_rate(NULL, "uartclk", NULL, CLK_IS_ROOT,
86 14745600);
87 clk_register_clkdev(clk, NULL, "uart0");
88 clk_register_clkdev(clk, NULL, "uart1");
89 if (is_cp)
90 clk_register_clkdev(clk, NULL, "mmci");
91
92 /* 24 MHz clock */
93 clk = clk_register_fixed_rate(NULL, "clk24mhz", NULL, CLK_IS_ROOT,
94 24000000);
95 clk_register_clkdev(clk, NULL, "kmi0");
96 clk_register_clkdev(clk, NULL, "kmi1");
97 if (!is_cp)
98 clk_register_clkdev(clk, NULL, "ap_timer");
99
100 if (!is_cp)
101 return;
102
103 /* 1 MHz clock */
104 clk = clk_register_fixed_rate(NULL, "clk1mhz", NULL, CLK_IS_ROOT,
105 1000000);
106 clk_register_clkdev(clk, NULL, "sp804");
107
108 /* ICST VCO clock used on the Integrator/CP CLCD */
109 clk = icst_clk_register(NULL, &cp_icst_desc);
110 clk_register_clkdev(clk, NULL, "clcd");
111}