]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - drivers/clk/mvebu/kirkwood.c
Merge branch 'hugepage-fallbacks' (hugepatch patches from David Rientjes)
[mirror_ubuntu-focal-kernel.git] / drivers / clk / mvebu / kirkwood.c
CommitLineData
c3828949 1// SPDX-License-Identifier: GPL-2.0
e89406c9
SH
2/*
3 * Marvell Kirkwood SoC clocks
4 *
5 * Copyright (C) 2012 Marvell
6 *
7 * Gregory CLEMENT <gregory.clement@free-electrons.com>
8 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
9 * Andrew Lunn <andrew@lunn.ch>
10 *
e89406c9
SH
11 */
12
13#include <linux/kernel.h>
e8e8a9b0 14#include <linux/slab.h>
e89406c9
SH
15#include <linux/clk-provider.h>
16#include <linux/io.h>
17#include <linux/of.h>
e8e8a9b0 18#include <linux/of_address.h>
e89406c9
SH
19#include "common.h"
20
21/*
22 * Core Clocks
23 *
24 * Kirkwood PLL sample-at-reset configuration
25 * (6180 has different SAR layout than other Kirkwood SoCs)
26 *
27 * SAR0[4:3,22,1] : CPU frequency (6281,6292,6282)
28 * 4 = 600 MHz
29 * 6 = 800 MHz
30 * 7 = 1000 MHz
31 * 9 = 1200 MHz
32 * 12 = 1500 MHz
33 * 13 = 1600 MHz
34 * 14 = 1800 MHz
35 * 15 = 2000 MHz
36 * others reserved.
37 *
38 * SAR0[19,10:9] : CPU to L2 Clock divider ratio (6281,6292,6282)
39 * 1 = (1/2) * CPU
40 * 3 = (1/3) * CPU
41 * 5 = (1/4) * CPU
42 * others reserved.
43 *
44 * SAR0[8:5] : CPU to DDR DRAM Clock divider ratio (6281,6292,6282)
45 * 2 = (1/2) * CPU
46 * 4 = (1/3) * CPU
47 * 6 = (1/4) * CPU
48 * 7 = (2/9) * CPU
49 * 8 = (1/5) * CPU
50 * 9 = (1/6) * CPU
51 * others reserved.
52 *
53 * SAR0[4:2] : Kirkwood 6180 cpu/l2/ddr clock configuration (6180 only)
54 * 5 = [CPU = 600 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/3) * CPU]
55 * 6 = [CPU = 800 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/4) * CPU]
56 * 7 = [CPU = 1000 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/5) * CPU]
57 * others reserved.
58 *
59 * SAR0[21] : TCLK frequency
60 * 0 = 200 MHz
61 * 1 = 166 MHz
62 * others reserved.
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
79enum { KIRKWOOD_CPU_TO_L2, KIRKWOOD_CPU_TO_DDR };
80
847b1c00 81static const struct coreclk_ratio kirkwood_coreclk_ratios[] __initconst = {
e89406c9
SH
82 { .id = KIRKWOOD_CPU_TO_L2, .name = "l2clk", },
83 { .id = KIRKWOOD_CPU_TO_DDR, .name = "ddrclk", }
84};
85
86static 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
847b1c00 93static const u32 kirkwood_cpu_freqs[] __initconst = {
e89406c9
SH
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
108static 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
847b1c00 114static const int kirkwood_cpu_l2_ratios[8][2] __initconst = {
e89406c9
SH
115 { 0, 1 }, { 1, 2 }, { 0, 1 }, { 1, 3 },
116 { 0, 1 }, { 1, 4 }, { 0, 1 }, { 0, 1 }
117};
118
847b1c00 119static const int kirkwood_cpu_ddr_ratios[16][2] __initconst = {
e89406c9
SH
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
126static 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
847b1c00 148static const u32 mv88f6180_cpu_freqs[] __initconst = {
e89406c9
SH
149 0, 0, 0, 0, 0,
150 600000000,
151 800000000,
152 1000000000
153};
154
155static 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
847b1c00 161static const int mv88f6180_cpu_ddr_ratios[8][2] __initconst = {
e89406c9
SH
162 { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 },
163 { 0, 1 }, { 1, 3 }, { 1, 4 }, { 1, 5 }
164};
165
166static 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 /* mv88f6180 has a fixed 1:2 CPU-to-L2 ratio */
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
88aa7af9
CP
188static u32 __init mv98dx1135_get_tclk_freq(void __iomem *sar)
189{
190 return 166666667;
191}
192
e89406c9
SH
193static 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
e89406c9
SH
201static 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
88aa7af9
CP
209static 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
e89406c9
SH
217/*
218 * Clock Gating Control
219 */
220
847b1c00 221static const struct clk_gating_soc_desc kirkwood_gating_desc[] __initconst = {
e89406c9
SH
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 },
e89406c9
SH
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
e8e8a9b0
MT
240
241/*
242 * Clock Muxing Control
243 */
244
245struct 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
254struct clk_muxing_ctrl {
255 spinlock_t *lock;
256 struct clk **muxes;
257 int num_muxes;
258};
259
10529938
MT
260static const char *powersave_parents[] = {
261 "cpuclk",
262 "ddrclk",
263};
264
265static const struct clk_muxing_soc_desc kirkwood_mux_desc[] __initconst = {
266 { "powersave", powersave_parents, ARRAY_SIZE(powersave_parents),
267 11, 1, 0 },
268};
269
e8e8a9b0
MT
270static 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
288static 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 /* lock must already be initialized */
304 ctrl->lock = &ctrl_gating_lock;
305
306 /* Count, allocate, and register clock muxes */
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;
327muxes_out:
328 kfree(ctrl);
329ctrl_out:
330 iounmap(base);
331}
332
58d516ae 333static void __init kirkwood_clk_init(struct device_node *np)
e89406c9 334{
58d516ae
SH
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);
88aa7af9
CP
341 else if (of_device_is_compatible(np, "marvell,mv98dx1135-core-clock"))
342 mvebu_coreclk_setup(np, &mv98dx1135_coreclks);
58d516ae
SH
343 else
344 mvebu_coreclk_setup(np, &kirkwood_coreclks);
345
10529938 346 if (cgnp) {
58d516ae 347 mvebu_clk_gating_setup(cgnp, kirkwood_gating_desc);
10529938 348 kirkwood_clk_muxing_setup(cgnp, kirkwood_mux_desc);
e7beeab9
YL
349
350 of_node_put(cgnp);
10529938 351 }
e89406c9 352}
58d516ae
SH
353CLK_OF_DECLARE(kirkwood_clk, "marvell,kirkwood-core-clock",
354 kirkwood_clk_init);
355CLK_OF_DECLARE(mv88f6180_clk, "marvell,mv88f6180-core-clock",
356 kirkwood_clk_init);
88aa7af9
CP
357CLK_OF_DECLARE(98dx1135_clk, "marvell,mv98dx1135-core-clock",
358 kirkwood_clk_init);