Merge remote-tracking branches 'regulator/fix/constrain' and 'regulator/fix/defer...
[deliverable/linux.git] / drivers / clk / mvebu / kirkwood.c
CommitLineData
e89406c9
SH
1/*
2 * Marvell Kirkwood SoC clocks
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * Gregory CLEMENT <gregory.clement@free-electrons.com>
7 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
8 * Andrew Lunn <andrew@lunn.ch>
9 *
10 * This file is licensed under the terms of the GNU General Public
11 * License version 2. This program is licensed "as is" without any
12 * warranty of any kind, whether express or implied.
13 */
14
15#include <linux/kernel.h>
e8e8a9b0 16#include <linux/slab.h>
e89406c9
SH
17#include <linux/clk-provider.h>
18#include <linux/io.h>
19#include <linux/of.h>
e8e8a9b0 20#include <linux/of_address.h>
e89406c9
SH
21#include "common.h"
22
23/*
24 * Core Clocks
25 *
26 * Kirkwood PLL sample-at-reset configuration
27 * (6180 has different SAR layout than other Kirkwood SoCs)
28 *
29 * SAR0[4:3,22,1] : CPU frequency (6281,6292,6282)
30 * 4 = 600 MHz
31 * 6 = 800 MHz
32 * 7 = 1000 MHz
33 * 9 = 1200 MHz
34 * 12 = 1500 MHz
35 * 13 = 1600 MHz
36 * 14 = 1800 MHz
37 * 15 = 2000 MHz
38 * others reserved.
39 *
40 * SAR0[19,10:9] : CPU to L2 Clock divider ratio (6281,6292,6282)
41 * 1 = (1/2) * CPU
42 * 3 = (1/3) * CPU
43 * 5 = (1/4) * CPU
44 * others reserved.
45 *
46 * SAR0[8:5] : CPU to DDR DRAM Clock divider ratio (6281,6292,6282)
47 * 2 = (1/2) * CPU
48 * 4 = (1/3) * CPU
49 * 6 = (1/4) * CPU
50 * 7 = (2/9) * CPU
51 * 8 = (1/5) * CPU
52 * 9 = (1/6) * CPU
53 * others reserved.
54 *
55 * SAR0[4:2] : Kirkwood 6180 cpu/l2/ddr clock configuration (6180 only)
56 * 5 = [CPU = 600 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/3) * CPU]
57 * 6 = [CPU = 800 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/4) * CPU]
58 * 7 = [CPU = 1000 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/5) * CPU]
59 * others reserved.
60 *
61 * SAR0[21] : TCLK frequency
62 * 0 = 200 MHz
63 * 1 = 166 MHz
64 * others reserved.
65 */
66
67#define SAR_KIRKWOOD_CPU_FREQ(x) \
68 (((x & (1 << 1)) >> 1) | \
69 ((x & (1 << 22)) >> 21) | \
70 ((x & (3 << 3)) >> 1))
71#define SAR_KIRKWOOD_L2_RATIO(x) \
72 (((x & (3 << 9)) >> 9) | \
73 (((x & (1 << 19)) >> 17)))
74#define SAR_KIRKWOOD_DDR_RATIO 5
75#define SAR_KIRKWOOD_DDR_RATIO_MASK 0xf
76#define SAR_MV88F6180_CLK 2
77#define SAR_MV88F6180_CLK_MASK 0x7
78#define SAR_KIRKWOOD_TCLK_FREQ 21
79#define SAR_KIRKWOOD_TCLK_FREQ_MASK 0x1
80
81enum { KIRKWOOD_CPU_TO_L2, KIRKWOOD_CPU_TO_DDR };
82
847b1c00 83static const struct coreclk_ratio kirkwood_coreclk_ratios[] __initconst = {
e89406c9
SH
84 { .id = KIRKWOOD_CPU_TO_L2, .name = "l2clk", },
85 { .id = KIRKWOOD_CPU_TO_DDR, .name = "ddrclk", }
86};
87
88static u32 __init kirkwood_get_tclk_freq(void __iomem *sar)
89{
90 u32 opt = (readl(sar) >> SAR_KIRKWOOD_TCLK_FREQ) &
91 SAR_KIRKWOOD_TCLK_FREQ_MASK;
92 return (opt) ? 166666667 : 200000000;
93}
94
847b1c00 95static const u32 kirkwood_cpu_freqs[] __initconst = {
e89406c9
SH
96 0, 0, 0, 0,
97 600000000,
98 0,
99 800000000,
100 1000000000,
101 0,
102 1200000000,
103 0, 0,
104 1500000000,
105 1600000000,
106 1800000000,
107 2000000000
108};
109
110static u32 __init kirkwood_get_cpu_freq(void __iomem *sar)
111{
112 u32 opt = SAR_KIRKWOOD_CPU_FREQ(readl(sar));
113 return kirkwood_cpu_freqs[opt];
114}
115
847b1c00 116static const int kirkwood_cpu_l2_ratios[8][2] __initconst = {
e89406c9
SH
117 { 0, 1 }, { 1, 2 }, { 0, 1 }, { 1, 3 },
118 { 0, 1 }, { 1, 4 }, { 0, 1 }, { 0, 1 }
119};
120
847b1c00 121static const int kirkwood_cpu_ddr_ratios[16][2] __initconst = {
e89406c9
SH
122 { 0, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 },
123 { 1, 3 }, { 0, 1 }, { 1, 4 }, { 2, 9 },
124 { 1, 5 }, { 1, 6 }, { 0, 1 }, { 0, 1 },
125 { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }
126};
127
128static void __init kirkwood_get_clk_ratio(
129 void __iomem *sar, int id, int *mult, int *div)
130{
131 switch (id) {
132 case KIRKWOOD_CPU_TO_L2:
133 {
134 u32 opt = SAR_KIRKWOOD_L2_RATIO(readl(sar));
135 *mult = kirkwood_cpu_l2_ratios[opt][0];
136 *div = kirkwood_cpu_l2_ratios[opt][1];
137 break;
138 }
139 case KIRKWOOD_CPU_TO_DDR:
140 {
141 u32 opt = (readl(sar) >> SAR_KIRKWOOD_DDR_RATIO) &
142 SAR_KIRKWOOD_DDR_RATIO_MASK;
143 *mult = kirkwood_cpu_ddr_ratios[opt][0];
144 *div = kirkwood_cpu_ddr_ratios[opt][1];
145 break;
146 }
147 }
148}
149
847b1c00 150static const u32 mv88f6180_cpu_freqs[] __initconst = {
e89406c9
SH
151 0, 0, 0, 0, 0,
152 600000000,
153 800000000,
154 1000000000
155};
156
157static u32 __init mv88f6180_get_cpu_freq(void __iomem *sar)
158{
159 u32 opt = (readl(sar) >> SAR_MV88F6180_CLK) & SAR_MV88F6180_CLK_MASK;
160 return mv88f6180_cpu_freqs[opt];
161}
162
847b1c00 163static const int mv88f6180_cpu_ddr_ratios[8][2] __initconst = {
e89406c9
SH
164 { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 },
165 { 0, 1 }, { 1, 3 }, { 1, 4 }, { 1, 5 }
166};
167
168static void __init mv88f6180_get_clk_ratio(
169 void __iomem *sar, int id, int *mult, int *div)
170{
171 switch (id) {
172 case KIRKWOOD_CPU_TO_L2:
173 {
174 /* mv88f6180 has a fixed 1:2 CPU-to-L2 ratio */
175 *mult = 1;
176 *div = 2;
177 break;
178 }
179 case KIRKWOOD_CPU_TO_DDR:
180 {
181 u32 opt = (readl(sar) >> SAR_MV88F6180_CLK) &
182 SAR_MV88F6180_CLK_MASK;
183 *mult = mv88f6180_cpu_ddr_ratios[opt][0];
184 *div = mv88f6180_cpu_ddr_ratios[opt][1];
185 break;
186 }
187 }
188}
189
190static const struct coreclk_soc_desc kirkwood_coreclks = {
191 .get_tclk_freq = kirkwood_get_tclk_freq,
192 .get_cpu_freq = kirkwood_get_cpu_freq,
193 .get_clk_ratio = kirkwood_get_clk_ratio,
194 .ratios = kirkwood_coreclk_ratios,
195 .num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios),
196};
197
e89406c9
SH
198static const struct coreclk_soc_desc mv88f6180_coreclks = {
199 .get_tclk_freq = kirkwood_get_tclk_freq,
200 .get_cpu_freq = mv88f6180_get_cpu_freq,
201 .get_clk_ratio = mv88f6180_get_clk_ratio,
202 .ratios = kirkwood_coreclk_ratios,
203 .num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios),
204};
205
e89406c9
SH
206/*
207 * Clock Gating Control
208 */
209
847b1c00 210static const struct clk_gating_soc_desc kirkwood_gating_desc[] __initconst = {
e89406c9
SH
211 { "ge0", NULL, 0, 0 },
212 { "pex0", NULL, 2, 0 },
213 { "usb0", NULL, 3, 0 },
214 { "sdio", NULL, 4, 0 },
215 { "tsu", NULL, 5, 0 },
216 { "runit", NULL, 7, 0 },
217 { "xor0", NULL, 8, 0 },
218 { "audio", NULL, 9, 0 },
e89406c9
SH
219 { "sata0", NULL, 14, 0 },
220 { "sata1", NULL, 15, 0 },
221 { "xor1", NULL, 16, 0 },
222 { "crypto", NULL, 17, 0 },
223 { "pex1", NULL, 18, 0 },
224 { "ge1", NULL, 19, 0 },
225 { "tdm", NULL, 20, 0 },
226 { }
227};
228
e8e8a9b0
MT
229
230/*
231 * Clock Muxing Control
232 */
233
234struct clk_muxing_soc_desc {
235 const char *name;
236 const char **parents;
237 int num_parents;
238 int shift;
239 int width;
240 unsigned long flags;
241};
242
243struct clk_muxing_ctrl {
244 spinlock_t *lock;
245 struct clk **muxes;
246 int num_muxes;
247};
248
10529938
MT
249static const char *powersave_parents[] = {
250 "cpuclk",
251 "ddrclk",
252};
253
254static const struct clk_muxing_soc_desc kirkwood_mux_desc[] __initconst = {
255 { "powersave", powersave_parents, ARRAY_SIZE(powersave_parents),
256 11, 1, 0 },
257};
258
e8e8a9b0
MT
259static struct clk *clk_muxing_get_src(
260 struct of_phandle_args *clkspec, void *data)
261{
262 struct clk_muxing_ctrl *ctrl = (struct clk_muxing_ctrl *)data;
263 int n;
264
265 if (clkspec->args_count < 1)
266 return ERR_PTR(-EINVAL);
267
268 for (n = 0; n < ctrl->num_muxes; n++) {
269 struct clk_mux *mux =
270 to_clk_mux(__clk_get_hw(ctrl->muxes[n]));
271 if (clkspec->args[0] == mux->shift)
272 return ctrl->muxes[n];
273 }
274 return ERR_PTR(-ENODEV);
275}
276
277static void __init kirkwood_clk_muxing_setup(struct device_node *np,
278 const struct clk_muxing_soc_desc *desc)
279{
280 struct clk_muxing_ctrl *ctrl;
281 void __iomem *base;
282 int n;
283
284 base = of_iomap(np, 0);
285 if (WARN_ON(!base))
286 return;
287
288 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
289 if (WARN_ON(!ctrl))
290 goto ctrl_out;
291
292 /* lock must already be initialized */
293 ctrl->lock = &ctrl_gating_lock;
294
295 /* Count, allocate, and register clock muxes */
296 for (n = 0; desc[n].name;)
297 n++;
298
299 ctrl->num_muxes = n;
300 ctrl->muxes = kcalloc(ctrl->num_muxes, sizeof(struct clk *),
301 GFP_KERNEL);
302 if (WARN_ON(!ctrl->muxes))
303 goto muxes_out;
304
305 for (n = 0; n < ctrl->num_muxes; n++) {
306 ctrl->muxes[n] = clk_register_mux(NULL, desc[n].name,
307 desc[n].parents, desc[n].num_parents,
308 desc[n].flags, base, desc[n].shift,
309 desc[n].width, desc[n].flags, ctrl->lock);
310 WARN_ON(IS_ERR(ctrl->muxes[n]));
311 }
312
313 of_clk_add_provider(np, clk_muxing_get_src, ctrl);
314
315 return;
316muxes_out:
317 kfree(ctrl);
318ctrl_out:
319 iounmap(base);
320}
321
58d516ae 322static void __init kirkwood_clk_init(struct device_node *np)
e89406c9 323{
58d516ae
SH
324 struct device_node *cgnp =
325 of_find_compatible_node(NULL, NULL, "marvell,kirkwood-gating-clock");
326
327
328 if (of_device_is_compatible(np, "marvell,mv88f6180-core-clock"))
329 mvebu_coreclk_setup(np, &mv88f6180_coreclks);
330 else
331 mvebu_coreclk_setup(np, &kirkwood_coreclks);
332
10529938 333 if (cgnp) {
58d516ae 334 mvebu_clk_gating_setup(cgnp, kirkwood_gating_desc);
10529938
MT
335 kirkwood_clk_muxing_setup(cgnp, kirkwood_mux_desc);
336 }
e89406c9 337}
58d516ae
SH
338CLK_OF_DECLARE(kirkwood_clk, "marvell,kirkwood-core-clock",
339 kirkwood_clk_init);
340CLK_OF_DECLARE(mv88f6180_clk, "marvell,mv88f6180-core-clock",
341 kirkwood_clk_init);
This page took 0.152054 seconds and 5 git commands to generate.