This source file includes following definitions.
- kirkwood_get_tclk_freq
- kirkwood_get_cpu_freq
- kirkwood_get_clk_ratio
- mv88f6180_get_cpu_freq
- mv88f6180_get_clk_ratio
- mv98dx1135_get_tclk_freq
- clk_muxing_get_src
- kirkwood_clk_muxing_setup
- kirkwood_clk_init
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <linux/kernel.h>
14 #include <linux/slab.h>
15 #include <linux/clk-provider.h>
16 #include <linux/io.h>
17 #include <linux/of.h>
18 #include <linux/of_address.h>
19 #include "common.h"
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 #define SAR_KIRKWOOD_CPU_FREQ(x) \
66 (((x & (1 << 1)) >> 1) | \
67 ((x & (1 << 22)) >> 21) | \
68 ((x & (3 << 3)) >> 1))
69 #define SAR_KIRKWOOD_L2_RATIO(x) \
70 (((x & (3 << 9)) >> 9) | \
71 (((x & (1 << 19)) >> 17)))
72 #define SAR_KIRKWOOD_DDR_RATIO 5
73 #define SAR_KIRKWOOD_DDR_RATIO_MASK 0xf
74 #define SAR_MV88F6180_CLK 2
75 #define SAR_MV88F6180_CLK_MASK 0x7
76 #define SAR_KIRKWOOD_TCLK_FREQ 21
77 #define SAR_KIRKWOOD_TCLK_FREQ_MASK 0x1
78
79 enum { KIRKWOOD_CPU_TO_L2, KIRKWOOD_CPU_TO_DDR };
80
81 static const struct coreclk_ratio kirkwood_coreclk_ratios[] __initconst = {
82 { .id = KIRKWOOD_CPU_TO_L2, .name = "l2clk", },
83 { .id = KIRKWOOD_CPU_TO_DDR, .name = "ddrclk", }
84 };
85
86 static u32 __init kirkwood_get_tclk_freq(void __iomem *sar)
87 {
88 u32 opt = (readl(sar) >> SAR_KIRKWOOD_TCLK_FREQ) &
89 SAR_KIRKWOOD_TCLK_FREQ_MASK;
90 return (opt) ? 166666667 : 200000000;
91 }
92
93 static const u32 kirkwood_cpu_freqs[] __initconst = {
94 0, 0, 0, 0,
95 600000000,
96 0,
97 800000000,
98 1000000000,
99 0,
100 1200000000,
101 0, 0,
102 1500000000,
103 1600000000,
104 1800000000,
105 2000000000
106 };
107
108 static u32 __init kirkwood_get_cpu_freq(void __iomem *sar)
109 {
110 u32 opt = SAR_KIRKWOOD_CPU_FREQ(readl(sar));
111 return kirkwood_cpu_freqs[opt];
112 }
113
114 static const int kirkwood_cpu_l2_ratios[8][2] __initconst = {
115 { 0, 1 }, { 1, 2 }, { 0, 1 }, { 1, 3 },
116 { 0, 1 }, { 1, 4 }, { 0, 1 }, { 0, 1 }
117 };
118
119 static const int kirkwood_cpu_ddr_ratios[16][2] __initconst = {
120 { 0, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 },
121 { 1, 3 }, { 0, 1 }, { 1, 4 }, { 2, 9 },
122 { 1, 5 }, { 1, 6 }, { 0, 1 }, { 0, 1 },
123 { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }
124 };
125
126 static void __init kirkwood_get_clk_ratio(
127 void __iomem *sar, int id, int *mult, int *div)
128 {
129 switch (id) {
130 case KIRKWOOD_CPU_TO_L2:
131 {
132 u32 opt = SAR_KIRKWOOD_L2_RATIO(readl(sar));
133 *mult = kirkwood_cpu_l2_ratios[opt][0];
134 *div = kirkwood_cpu_l2_ratios[opt][1];
135 break;
136 }
137 case KIRKWOOD_CPU_TO_DDR:
138 {
139 u32 opt = (readl(sar) >> SAR_KIRKWOOD_DDR_RATIO) &
140 SAR_KIRKWOOD_DDR_RATIO_MASK;
141 *mult = kirkwood_cpu_ddr_ratios[opt][0];
142 *div = kirkwood_cpu_ddr_ratios[opt][1];
143 break;
144 }
145 }
146 }
147
148 static const u32 mv88f6180_cpu_freqs[] __initconst = {
149 0, 0, 0, 0, 0,
150 600000000,
151 800000000,
152 1000000000
153 };
154
155 static u32 __init mv88f6180_get_cpu_freq(void __iomem *sar)
156 {
157 u32 opt = (readl(sar) >> SAR_MV88F6180_CLK) & SAR_MV88F6180_CLK_MASK;
158 return mv88f6180_cpu_freqs[opt];
159 }
160
161 static const int mv88f6180_cpu_ddr_ratios[8][2] __initconst = {
162 { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 },
163 { 0, 1 }, { 1, 3 }, { 1, 4 }, { 1, 5 }
164 };
165
166 static void __init mv88f6180_get_clk_ratio(
167 void __iomem *sar, int id, int *mult, int *div)
168 {
169 switch (id) {
170 case KIRKWOOD_CPU_TO_L2:
171 {
172
173 *mult = 1;
174 *div = 2;
175 break;
176 }
177 case KIRKWOOD_CPU_TO_DDR:
178 {
179 u32 opt = (readl(sar) >> SAR_MV88F6180_CLK) &
180 SAR_MV88F6180_CLK_MASK;
181 *mult = mv88f6180_cpu_ddr_ratios[opt][0];
182 *div = mv88f6180_cpu_ddr_ratios[opt][1];
183 break;
184 }
185 }
186 }
187
188 static u32 __init mv98dx1135_get_tclk_freq(void __iomem *sar)
189 {
190 return 166666667;
191 }
192
193 static const struct coreclk_soc_desc kirkwood_coreclks = {
194 .get_tclk_freq = kirkwood_get_tclk_freq,
195 .get_cpu_freq = kirkwood_get_cpu_freq,
196 .get_clk_ratio = kirkwood_get_clk_ratio,
197 .ratios = kirkwood_coreclk_ratios,
198 .num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios),
199 };
200
201 static const struct coreclk_soc_desc mv88f6180_coreclks = {
202 .get_tclk_freq = kirkwood_get_tclk_freq,
203 .get_cpu_freq = mv88f6180_get_cpu_freq,
204 .get_clk_ratio = mv88f6180_get_clk_ratio,
205 .ratios = kirkwood_coreclk_ratios,
206 .num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios),
207 };
208
209 static const struct coreclk_soc_desc mv98dx1135_coreclks = {
210 .get_tclk_freq = mv98dx1135_get_tclk_freq,
211 .get_cpu_freq = kirkwood_get_cpu_freq,
212 .get_clk_ratio = kirkwood_get_clk_ratio,
213 .ratios = kirkwood_coreclk_ratios,
214 .num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios),
215 };
216
217
218
219
220
221 static const struct clk_gating_soc_desc kirkwood_gating_desc[] __initconst = {
222 { "ge0", NULL, 0, 0 },
223 { "pex0", NULL, 2, 0 },
224 { "usb0", NULL, 3, 0 },
225 { "sdio", NULL, 4, 0 },
226 { "tsu", NULL, 5, 0 },
227 { "runit", NULL, 7, 0 },
228 { "xor0", NULL, 8, 0 },
229 { "audio", NULL, 9, 0 },
230 { "sata0", NULL, 14, 0 },
231 { "sata1", NULL, 15, 0 },
232 { "xor1", NULL, 16, 0 },
233 { "crypto", NULL, 17, 0 },
234 { "pex1", NULL, 18, 0 },
235 { "ge1", NULL, 19, 0 },
236 { "tdm", NULL, 20, 0 },
237 { }
238 };
239
240
241
242
243
244
245 struct clk_muxing_soc_desc {
246 const char *name;
247 const char **parents;
248 int num_parents;
249 int shift;
250 int width;
251 unsigned long flags;
252 };
253
254 struct clk_muxing_ctrl {
255 spinlock_t *lock;
256 struct clk **muxes;
257 int num_muxes;
258 };
259
260 static const char *powersave_parents[] = {
261 "cpuclk",
262 "ddrclk",
263 };
264
265 static const struct clk_muxing_soc_desc kirkwood_mux_desc[] __initconst = {
266 { "powersave", powersave_parents, ARRAY_SIZE(powersave_parents),
267 11, 1, 0 },
268 };
269
270 static struct clk *clk_muxing_get_src(
271 struct of_phandle_args *clkspec, void *data)
272 {
273 struct clk_muxing_ctrl *ctrl = (struct clk_muxing_ctrl *)data;
274 int n;
275
276 if (clkspec->args_count < 1)
277 return ERR_PTR(-EINVAL);
278
279 for (n = 0; n < ctrl->num_muxes; n++) {
280 struct clk_mux *mux =
281 to_clk_mux(__clk_get_hw(ctrl->muxes[n]));
282 if (clkspec->args[0] == mux->shift)
283 return ctrl->muxes[n];
284 }
285 return ERR_PTR(-ENODEV);
286 }
287
288 static void __init kirkwood_clk_muxing_setup(struct device_node *np,
289 const struct clk_muxing_soc_desc *desc)
290 {
291 struct clk_muxing_ctrl *ctrl;
292 void __iomem *base;
293 int n;
294
295 base = of_iomap(np, 0);
296 if (WARN_ON(!base))
297 return;
298
299 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
300 if (WARN_ON(!ctrl))
301 goto ctrl_out;
302
303
304 ctrl->lock = &ctrl_gating_lock;
305
306
307 for (n = 0; desc[n].name;)
308 n++;
309
310 ctrl->num_muxes = n;
311 ctrl->muxes = kcalloc(ctrl->num_muxes, sizeof(struct clk *),
312 GFP_KERNEL);
313 if (WARN_ON(!ctrl->muxes))
314 goto muxes_out;
315
316 for (n = 0; n < ctrl->num_muxes; n++) {
317 ctrl->muxes[n] = clk_register_mux(NULL, desc[n].name,
318 desc[n].parents, desc[n].num_parents,
319 desc[n].flags, base, desc[n].shift,
320 desc[n].width, desc[n].flags, ctrl->lock);
321 WARN_ON(IS_ERR(ctrl->muxes[n]));
322 }
323
324 of_clk_add_provider(np, clk_muxing_get_src, ctrl);
325
326 return;
327 muxes_out:
328 kfree(ctrl);
329 ctrl_out:
330 iounmap(base);
331 }
332
333 static void __init kirkwood_clk_init(struct device_node *np)
334 {
335 struct device_node *cgnp =
336 of_find_compatible_node(NULL, NULL, "marvell,kirkwood-gating-clock");
337
338
339 if (of_device_is_compatible(np, "marvell,mv88f6180-core-clock"))
340 mvebu_coreclk_setup(np, &mv88f6180_coreclks);
341 else if (of_device_is_compatible(np, "marvell,mv98dx1135-core-clock"))
342 mvebu_coreclk_setup(np, &mv98dx1135_coreclks);
343 else
344 mvebu_coreclk_setup(np, &kirkwood_coreclks);
345
346 if (cgnp) {
347 mvebu_clk_gating_setup(cgnp, kirkwood_gating_desc);
348 kirkwood_clk_muxing_setup(cgnp, kirkwood_mux_desc);
349
350 of_node_put(cgnp);
351 }
352 }
353 CLK_OF_DECLARE(kirkwood_clk, "marvell,kirkwood-core-clock",
354 kirkwood_clk_init);
355 CLK_OF_DECLARE(mv88f6180_clk, "marvell,mv88f6180-core-clock",
356 kirkwood_clk_init);
357 CLK_OF_DECLARE(98dx1135_clk, "marvell,mv98dx1135-core-clock",
358 kirkwood_clk_init);