1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Marvell Orion SoC clocks |
4 | * |
5 | * Copyright (C) 2014 Thomas Petazzoni |
6 | * |
7 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> |
8 | * |
9 | */ |
10 | |
11 | #include <linux/kernel.h> |
12 | #include <linux/clk-provider.h> |
13 | #include <linux/io.h> |
14 | #include <linux/of.h> |
15 | #include "common.h" |
16 | |
17 | static const struct coreclk_ratio orion_coreclk_ratios[] __initconst = { |
18 | { .id = 0, .name = "ddrclk" , } |
19 | }; |
20 | |
21 | /* |
22 | * Orion 5181 |
23 | */ |
24 | |
25 | #define SAR_MV88F5181_TCLK_FREQ 8 |
26 | #define SAR_MV88F5181_TCLK_FREQ_MASK 0x3 |
27 | |
28 | static u32 __init mv88f5181_get_tclk_freq(void __iomem *sar) |
29 | { |
30 | u32 opt = (readl(addr: sar) >> SAR_MV88F5181_TCLK_FREQ) & |
31 | SAR_MV88F5181_TCLK_FREQ_MASK; |
32 | if (opt == 0) |
33 | return 133333333; |
34 | else if (opt == 1) |
35 | return 150000000; |
36 | else if (opt == 2) |
37 | return 166666667; |
38 | else |
39 | return 0; |
40 | } |
41 | |
42 | #define SAR_MV88F5181_CPU_FREQ 4 |
43 | #define SAR_MV88F5181_CPU_FREQ_MASK 0xf |
44 | |
45 | static u32 __init mv88f5181_get_cpu_freq(void __iomem *sar) |
46 | { |
47 | u32 opt = (readl(addr: sar) >> SAR_MV88F5181_CPU_FREQ) & |
48 | SAR_MV88F5181_CPU_FREQ_MASK; |
49 | if (opt == 0) |
50 | return 333333333; |
51 | else if (opt == 1 || opt == 2) |
52 | return 400000000; |
53 | else if (opt == 3) |
54 | return 500000000; |
55 | else |
56 | return 0; |
57 | } |
58 | |
59 | static void __init mv88f5181_get_clk_ratio(void __iomem *sar, int id, |
60 | int *mult, int *div) |
61 | { |
62 | u32 opt = (readl(addr: sar) >> SAR_MV88F5181_CPU_FREQ) & |
63 | SAR_MV88F5181_CPU_FREQ_MASK; |
64 | if (opt == 0 || opt == 1) { |
65 | *mult = 1; |
66 | *div = 2; |
67 | } else if (opt == 2 || opt == 3) { |
68 | *mult = 1; |
69 | *div = 3; |
70 | } else { |
71 | *mult = 0; |
72 | *div = 1; |
73 | } |
74 | } |
75 | |
76 | static const struct coreclk_soc_desc mv88f5181_coreclks = { |
77 | .get_tclk_freq = mv88f5181_get_tclk_freq, |
78 | .get_cpu_freq = mv88f5181_get_cpu_freq, |
79 | .get_clk_ratio = mv88f5181_get_clk_ratio, |
80 | .ratios = orion_coreclk_ratios, |
81 | .num_ratios = ARRAY_SIZE(orion_coreclk_ratios), |
82 | }; |
83 | |
84 | static void __init mv88f5181_clk_init(struct device_node *np) |
85 | { |
86 | return mvebu_coreclk_setup(np, desc: &mv88f5181_coreclks); |
87 | } |
88 | |
89 | CLK_OF_DECLARE(mv88f5181_clk, "marvell,mv88f5181-core-clock" , mv88f5181_clk_init); |
90 | |
91 | /* |
92 | * Orion 5182 |
93 | */ |
94 | |
95 | #define SAR_MV88F5182_TCLK_FREQ 8 |
96 | #define SAR_MV88F5182_TCLK_FREQ_MASK 0x3 |
97 | |
98 | static u32 __init mv88f5182_get_tclk_freq(void __iomem *sar) |
99 | { |
100 | u32 opt = (readl(addr: sar) >> SAR_MV88F5182_TCLK_FREQ) & |
101 | SAR_MV88F5182_TCLK_FREQ_MASK; |
102 | if (opt == 1) |
103 | return 150000000; |
104 | else if (opt == 2) |
105 | return 166666667; |
106 | else |
107 | return 0; |
108 | } |
109 | |
110 | #define SAR_MV88F5182_CPU_FREQ 4 |
111 | #define SAR_MV88F5182_CPU_FREQ_MASK 0xf |
112 | |
113 | static u32 __init mv88f5182_get_cpu_freq(void __iomem *sar) |
114 | { |
115 | u32 opt = (readl(addr: sar) >> SAR_MV88F5182_CPU_FREQ) & |
116 | SAR_MV88F5182_CPU_FREQ_MASK; |
117 | if (opt == 0) |
118 | return 333333333; |
119 | else if (opt == 1 || opt == 2) |
120 | return 400000000; |
121 | else if (opt == 3) |
122 | return 500000000; |
123 | else |
124 | return 0; |
125 | } |
126 | |
127 | static void __init mv88f5182_get_clk_ratio(void __iomem *sar, int id, |
128 | int *mult, int *div) |
129 | { |
130 | u32 opt = (readl(addr: sar) >> SAR_MV88F5182_CPU_FREQ) & |
131 | SAR_MV88F5182_CPU_FREQ_MASK; |
132 | if (opt == 0 || opt == 1) { |
133 | *mult = 1; |
134 | *div = 2; |
135 | } else if (opt == 2 || opt == 3) { |
136 | *mult = 1; |
137 | *div = 3; |
138 | } else { |
139 | *mult = 0; |
140 | *div = 1; |
141 | } |
142 | } |
143 | |
144 | static const struct coreclk_soc_desc mv88f5182_coreclks = { |
145 | .get_tclk_freq = mv88f5182_get_tclk_freq, |
146 | .get_cpu_freq = mv88f5182_get_cpu_freq, |
147 | .get_clk_ratio = mv88f5182_get_clk_ratio, |
148 | .ratios = orion_coreclk_ratios, |
149 | .num_ratios = ARRAY_SIZE(orion_coreclk_ratios), |
150 | }; |
151 | |
152 | static void __init mv88f5182_clk_init(struct device_node *np) |
153 | { |
154 | return mvebu_coreclk_setup(np, desc: &mv88f5182_coreclks); |
155 | } |
156 | |
157 | CLK_OF_DECLARE(mv88f5182_clk, "marvell,mv88f5182-core-clock" , mv88f5182_clk_init); |
158 | |
159 | /* |
160 | * Orion 5281 |
161 | */ |
162 | |
163 | static u32 __init mv88f5281_get_tclk_freq(void __iomem *sar) |
164 | { |
165 | /* On 5281, tclk is always 166 Mhz */ |
166 | return 166666667; |
167 | } |
168 | |
169 | #define SAR_MV88F5281_CPU_FREQ 4 |
170 | #define SAR_MV88F5281_CPU_FREQ_MASK 0xf |
171 | |
172 | static u32 __init mv88f5281_get_cpu_freq(void __iomem *sar) |
173 | { |
174 | u32 opt = (readl(addr: sar) >> SAR_MV88F5281_CPU_FREQ) & |
175 | SAR_MV88F5281_CPU_FREQ_MASK; |
176 | if (opt == 1 || opt == 2) |
177 | return 400000000; |
178 | else if (opt == 3) |
179 | return 500000000; |
180 | else |
181 | return 0; |
182 | } |
183 | |
184 | static void __init mv88f5281_get_clk_ratio(void __iomem *sar, int id, |
185 | int *mult, int *div) |
186 | { |
187 | u32 opt = (readl(addr: sar) >> SAR_MV88F5281_CPU_FREQ) & |
188 | SAR_MV88F5281_CPU_FREQ_MASK; |
189 | if (opt == 1) { |
190 | *mult = 1; |
191 | *div = 2; |
192 | } else if (opt == 2 || opt == 3) { |
193 | *mult = 1; |
194 | *div = 3; |
195 | } else { |
196 | *mult = 0; |
197 | *div = 1; |
198 | } |
199 | } |
200 | |
201 | static const struct coreclk_soc_desc mv88f5281_coreclks = { |
202 | .get_tclk_freq = mv88f5281_get_tclk_freq, |
203 | .get_cpu_freq = mv88f5281_get_cpu_freq, |
204 | .get_clk_ratio = mv88f5281_get_clk_ratio, |
205 | .ratios = orion_coreclk_ratios, |
206 | .num_ratios = ARRAY_SIZE(orion_coreclk_ratios), |
207 | }; |
208 | |
209 | static void __init mv88f5281_clk_init(struct device_node *np) |
210 | { |
211 | return mvebu_coreclk_setup(np, desc: &mv88f5281_coreclks); |
212 | } |
213 | |
214 | CLK_OF_DECLARE(mv88f5281_clk, "marvell,mv88f5281-core-clock" , mv88f5281_clk_init); |
215 | |
216 | /* |
217 | * Orion 6183 |
218 | */ |
219 | |
220 | #define SAR_MV88F6183_TCLK_FREQ 9 |
221 | #define SAR_MV88F6183_TCLK_FREQ_MASK 0x1 |
222 | |
223 | static u32 __init mv88f6183_get_tclk_freq(void __iomem *sar) |
224 | { |
225 | u32 opt = (readl(addr: sar) >> SAR_MV88F6183_TCLK_FREQ) & |
226 | SAR_MV88F6183_TCLK_FREQ_MASK; |
227 | if (opt == 0) |
228 | return 133333333; |
229 | else if (opt == 1) |
230 | return 166666667; |
231 | else |
232 | return 0; |
233 | } |
234 | |
235 | #define SAR_MV88F6183_CPU_FREQ 1 |
236 | #define SAR_MV88F6183_CPU_FREQ_MASK 0x3f |
237 | |
238 | static u32 __init mv88f6183_get_cpu_freq(void __iomem *sar) |
239 | { |
240 | u32 opt = (readl(addr: sar) >> SAR_MV88F6183_CPU_FREQ) & |
241 | SAR_MV88F6183_CPU_FREQ_MASK; |
242 | if (opt == 9) |
243 | return 333333333; |
244 | else if (opt == 17) |
245 | return 400000000; |
246 | else |
247 | return 0; |
248 | } |
249 | |
250 | static void __init mv88f6183_get_clk_ratio(void __iomem *sar, int id, |
251 | int *mult, int *div) |
252 | { |
253 | u32 opt = (readl(addr: sar) >> SAR_MV88F6183_CPU_FREQ) & |
254 | SAR_MV88F6183_CPU_FREQ_MASK; |
255 | if (opt == 9 || opt == 17) { |
256 | *mult = 1; |
257 | *div = 2; |
258 | } else { |
259 | *mult = 0; |
260 | *div = 1; |
261 | } |
262 | } |
263 | |
264 | static const struct coreclk_soc_desc mv88f6183_coreclks = { |
265 | .get_tclk_freq = mv88f6183_get_tclk_freq, |
266 | .get_cpu_freq = mv88f6183_get_cpu_freq, |
267 | .get_clk_ratio = mv88f6183_get_clk_ratio, |
268 | .ratios = orion_coreclk_ratios, |
269 | .num_ratios = ARRAY_SIZE(orion_coreclk_ratios), |
270 | }; |
271 | |
272 | |
273 | static void __init mv88f6183_clk_init(struct device_node *np) |
274 | { |
275 | return mvebu_coreclk_setup(np, desc: &mv88f6183_coreclks); |
276 | } |
277 | |
278 | CLK_OF_DECLARE(mv88f6183_clk, "marvell,mv88f6183-core-clock" , mv88f6183_clk_init); |
279 | |