]>
Commit | Line | Data |
---|---|---|
6c3e61de SB |
1 | /* |
2 | * Copyright (C) 2013 Soren Brinkmann <soren.brinkmann@xilinx.com> | |
3 | * Copyright (C) 2013 Xilinx, Inc. All rights reserved. | |
4 | * | |
5 | * SPDX-License-Identifier: GPL-2.0+ | |
6 | */ | |
7 | #include <common.h> | |
8 | #include <errno.h> | |
9 | #include <asm/io.h> | |
10 | #include <asm/arch/hardware.h> | |
11 | #include <asm/arch/clk.h> | |
12 | ||
13 | /* Board oscillator frequency */ | |
14 | #ifndef CONFIG_ZYNQ_PS_CLK_FREQ | |
15 | # define CONFIG_ZYNQ_PS_CLK_FREQ 33333333UL | |
16 | #endif | |
17 | ||
18 | /* Register bitfield defines */ | |
19 | #define PLLCTRL_FBDIV_MASK 0x7f000 | |
20 | #define PLLCTRL_FBDIV_SHIFT 12 | |
21 | #define PLLCTRL_BPFORCE_MASK (1 << 4) | |
22 | #define PLLCTRL_PWRDWN_MASK 2 | |
23 | #define PLLCTRL_PWRDWN_SHIFT 1 | |
24 | #define PLLCTRL_RESET_MASK 1 | |
25 | #define PLLCTRL_RESET_SHIFT 0 | |
26 | ||
27 | #define ZYNQ_CLK_MAXDIV 0x3f | |
28 | #define CLK_CTRL_DIV1_SHIFT 20 | |
29 | #define CLK_CTRL_DIV1_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT) | |
30 | #define CLK_CTRL_DIV0_SHIFT 8 | |
31 | #define CLK_CTRL_DIV0_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT) | |
32 | #define CLK_CTRL_SRCSEL_SHIFT 4 | |
33 | #define CLK_CTRL_SRCSEL_MASK (0x3 << CLK_CTRL_SRCSEL_SHIFT) | |
34 | ||
35 | #define CLK_CTRL_DIV2X_SHIFT 26 | |
36 | #define CLK_CTRL_DIV2X_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV2X_SHIFT) | |
37 | #define CLK_CTRL_DIV3X_SHIFT 20 | |
38 | #define CLK_CTRL_DIV3X_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV3X_SHIFT) | |
39 | ||
40 | #define ZYNQ_CLKMUX_SEL_0 0 | |
41 | #define ZYNQ_CLKMUX_SEL_1 1 | |
42 | #define ZYNQ_CLKMUX_SEL_2 2 | |
43 | #define ZYNQ_CLKMUX_SEL_3 3 | |
44 | ||
45 | DECLARE_GLOBAL_DATA_PTR; | |
46 | ||
47 | struct clk; | |
48 | ||
49 | /** | |
30db9187 | 50 | * struct zynq_clk_ops: |
6c3e61de SB |
51 | * @set_rate: Function pointer to set_rate() implementation |
52 | * @get_rate: Function pointer to get_rate() implementation | |
53 | */ | |
30db9187 | 54 | struct zynq_clk_ops { |
6c3e61de SB |
55 | int (*set_rate)(struct clk *clk, unsigned long rate); |
56 | unsigned long (*get_rate)(struct clk *clk); | |
57 | }; | |
58 | ||
59 | /** | |
60 | * struct clk: | |
61 | * @name: Clock name | |
62 | * @frequency: Currenct frequency | |
63 | * @parent: Parent clock | |
64 | * @flags: Clock flags | |
65 | * @reg: Clock control register | |
66 | * @ops: Clock operations | |
67 | */ | |
68 | struct clk { | |
69 | char *name; | |
70 | unsigned long frequency; | |
71 | enum zynq_clk parent; | |
72 | unsigned int flags; | |
73 | u32 *reg; | |
30db9187 | 74 | struct zynq_clk_ops ops; |
6c3e61de SB |
75 | }; |
76 | #define ZYNQ_CLK_FLAGS_HAS_2_DIVS 1 | |
77 | ||
78 | static struct clk clks[clk_max]; | |
79 | ||
80 | /** | |
81 | * __zynq_clk_cpu_get_parent() - Decode clock multiplexer | |
82 | * @srcsel: Mux select value | |
83 | * Returns the clock identifier associated with the selected mux input. | |
84 | */ | |
85 | static int __zynq_clk_cpu_get_parent(unsigned int srcsel) | |
86 | { | |
87 | unsigned int ret; | |
88 | ||
89 | switch (srcsel) { | |
90 | case ZYNQ_CLKMUX_SEL_0: | |
91 | case ZYNQ_CLKMUX_SEL_1: | |
92 | ret = armpll_clk; | |
93 | break; | |
94 | case ZYNQ_CLKMUX_SEL_2: | |
95 | ret = ddrpll_clk; | |
96 | break; | |
97 | case ZYNQ_CLKMUX_SEL_3: | |
98 | ret = iopll_clk; | |
99 | break; | |
100 | default: | |
101 | ret = armpll_clk; | |
102 | break; | |
103 | } | |
104 | ||
105 | return ret; | |
106 | } | |
107 | ||
108 | /** | |
109 | * ddr2x_get_rate() - Get clock rate of DDR2x clock | |
110 | * @clk: Clock handle | |
111 | * Returns the current clock rate of @clk. | |
112 | */ | |
113 | static unsigned long ddr2x_get_rate(struct clk *clk) | |
114 | { | |
115 | u32 clk_ctrl = readl(clk->reg); | |
116 | u32 div = (clk_ctrl & CLK_CTRL_DIV2X_MASK) >> CLK_CTRL_DIV2X_SHIFT; | |
117 | ||
118 | return DIV_ROUND_CLOSEST(zynq_clk_get_rate(clk->parent), div); | |
119 | } | |
120 | ||
121 | /** | |
122 | * ddr3x_get_rate() - Get clock rate of DDR3x clock | |
123 | * @clk: Clock handle | |
124 | * Returns the current clock rate of @clk. | |
125 | */ | |
126 | static unsigned long ddr3x_get_rate(struct clk *clk) | |
127 | { | |
128 | u32 clk_ctrl = readl(clk->reg); | |
129 | u32 div = (clk_ctrl & CLK_CTRL_DIV3X_MASK) >> CLK_CTRL_DIV3X_SHIFT; | |
130 | ||
131 | return DIV_ROUND_CLOSEST(zynq_clk_get_rate(clk->parent), div); | |
132 | } | |
133 | ||
134 | static void init_ddr_clocks(void) | |
135 | { | |
136 | u32 div0, div1; | |
137 | unsigned long prate = zynq_clk_get_rate(ddrpll_clk); | |
138 | u32 clk_ctrl = readl(&slcr_base->ddr_clk_ctrl); | |
139 | ||
140 | /* DDR2x */ | |
141 | clks[ddr2x_clk].reg = &slcr_base->ddr_clk_ctrl; | |
142 | clks[ddr2x_clk].parent = ddrpll_clk; | |
143 | clks[ddr2x_clk].name = "ddr_2x"; | |
144 | clks[ddr2x_clk].frequency = ddr2x_get_rate(&clks[ddr2x_clk]); | |
145 | clks[ddr2x_clk].ops.get_rate = ddr2x_get_rate; | |
146 | ||
147 | /* DDR3x */ | |
148 | clks[ddr3x_clk].reg = &slcr_base->ddr_clk_ctrl; | |
149 | clks[ddr3x_clk].parent = ddrpll_clk; | |
150 | clks[ddr3x_clk].name = "ddr_3x"; | |
151 | clks[ddr3x_clk].frequency = ddr3x_get_rate(&clks[ddr3x_clk]); | |
152 | clks[ddr3x_clk].ops.get_rate = ddr3x_get_rate; | |
153 | ||
154 | /* DCI */ | |
155 | clk_ctrl = readl(&slcr_base->dci_clk_ctrl); | |
156 | div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT; | |
157 | div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT; | |
158 | clks[dci_clk].reg = &slcr_base->dci_clk_ctrl; | |
159 | clks[dci_clk].parent = ddrpll_clk; | |
160 | clks[dci_clk].frequency = DIV_ROUND_CLOSEST( | |
161 | DIV_ROUND_CLOSEST(prate, div0), div1); | |
162 | clks[dci_clk].name = "dci"; | |
96a5d4dc MS |
163 | |
164 | gd->bd->bi_ddr_freq = clks[ddr3x_clk].frequency / 1000000; | |
6c3e61de SB |
165 | } |
166 | ||
167 | static void init_cpu_clocks(void) | |
168 | { | |
169 | int clk_621; | |
170 | u32 reg, div, srcsel; | |
171 | enum zynq_clk parent; | |
172 | ||
173 | reg = readl(&slcr_base->arm_clk_ctrl); | |
174 | clk_621 = readl(&slcr_base->clk_621_true) & 1; | |
175 | div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT; | |
176 | srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT; | |
177 | parent = __zynq_clk_cpu_get_parent(srcsel); | |
178 | ||
179 | /* cpu clocks */ | |
180 | clks[cpu_6or4x_clk].reg = &slcr_base->arm_clk_ctrl; | |
181 | clks[cpu_6or4x_clk].parent = parent; | |
182 | clks[cpu_6or4x_clk].frequency = DIV_ROUND_CLOSEST( | |
183 | zynq_clk_get_rate(parent), div); | |
184 | clks[cpu_6or4x_clk].name = "cpu_6or4x"; | |
185 | ||
186 | clks[cpu_3or2x_clk].reg = &slcr_base->arm_clk_ctrl; | |
187 | clks[cpu_3or2x_clk].parent = cpu_6or4x_clk; | |
188 | clks[cpu_3or2x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) / 2; | |
189 | clks[cpu_3or2x_clk].name = "cpu_3or2x"; | |
190 | ||
191 | clks[cpu_2x_clk].reg = &slcr_base->arm_clk_ctrl; | |
192 | clks[cpu_2x_clk].parent = cpu_6or4x_clk; | |
193 | clks[cpu_2x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) / | |
194 | (2 + clk_621); | |
195 | clks[cpu_2x_clk].name = "cpu_2x"; | |
196 | ||
197 | clks[cpu_1x_clk].reg = &slcr_base->arm_clk_ctrl; | |
198 | clks[cpu_1x_clk].parent = cpu_6or4x_clk; | |
199 | clks[cpu_1x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) / | |
200 | (4 + 2 * clk_621); | |
201 | clks[cpu_1x_clk].name = "cpu_1x"; | |
202 | } | |
203 | ||
204 | /** | |
205 | * periph_calc_two_divs() - Calculate clock dividers | |
206 | * @cur_rate: Current clock rate | |
207 | * @tgt_rate: Target clock rate | |
208 | * @prate: Parent clock rate | |
209 | * @div0: First divider (output) | |
210 | * @div1: Second divider (output) | |
211 | * Returns the actual clock rate possible. | |
212 | * | |
213 | * Calculates clock dividers for clocks with two 6-bit dividers. | |
214 | */ | |
215 | static unsigned long periph_calc_two_divs(unsigned long cur_rate, | |
216 | unsigned long tgt_rate, unsigned long prate, u32 *div0, | |
217 | u32 *div1) | |
218 | { | |
219 | long err, best_err = (long)(~0UL >> 1); | |
220 | unsigned long rate, best_rate = 0; | |
221 | u32 d0, d1; | |
222 | ||
223 | for (d0 = 1; d0 <= ZYNQ_CLK_MAXDIV; d0++) { | |
224 | for (d1 = 1; d1 <= ZYNQ_CLK_MAXDIV >> 1; d1++) { | |
225 | rate = DIV_ROUND_CLOSEST(DIV_ROUND_CLOSEST(prate, d0), | |
226 | d1); | |
227 | err = abs(rate - tgt_rate); | |
228 | ||
229 | if (err < best_err) { | |
230 | *div0 = d0; | |
231 | *div1 = d1; | |
232 | best_err = err; | |
233 | best_rate = rate; | |
234 | } | |
235 | } | |
236 | } | |
237 | ||
238 | return best_rate; | |
239 | } | |
240 | ||
241 | /** | |
242 | * zynq_clk_periph_set_rate() - Set clock rate | |
243 | * @clk: Handle of the peripheral clock | |
244 | * @rate: New clock rate | |
245 | * Sets the clock frequency of @clk to @rate. Returns zero on success. | |
246 | */ | |
247 | static int zynq_clk_periph_set_rate(struct clk *clk, | |
248 | unsigned long rate) | |
249 | { | |
250 | u32 ctrl, div0 = 0, div1 = 0; | |
251 | unsigned long prate, new_rate, cur_rate = clk->frequency; | |
252 | ||
253 | ctrl = readl(clk->reg); | |
254 | prate = zynq_clk_get_rate(clk->parent); | |
255 | ctrl &= ~CLK_CTRL_DIV0_MASK; | |
256 | ||
257 | if (clk->flags & ZYNQ_CLK_FLAGS_HAS_2_DIVS) { | |
258 | ctrl &= ~CLK_CTRL_DIV1_MASK; | |
259 | new_rate = periph_calc_two_divs(cur_rate, rate, prate, &div0, | |
260 | &div1); | |
261 | ctrl |= div1 << CLK_CTRL_DIV1_SHIFT; | |
262 | } else { | |
263 | div0 = DIV_ROUND_CLOSEST(prate, rate); | |
264 | div0 &= ZYNQ_CLK_MAXDIV; | |
265 | new_rate = DIV_ROUND_CLOSEST(rate, div0); | |
266 | } | |
267 | ||
268 | /* write new divs to hardware */ | |
269 | ctrl |= div0 << CLK_CTRL_DIV0_SHIFT; | |
270 | writel(ctrl, clk->reg); | |
271 | ||
272 | /* update frequency in clk framework */ | |
273 | clk->frequency = new_rate; | |
274 | ||
275 | return 0; | |
276 | } | |
277 | ||
278 | /** | |
279 | * zynq_clk_periph_get_rate() - Get clock rate | |
280 | * @clk: Handle of the peripheral clock | |
281 | * Returns the current clock rate of @clk. | |
282 | */ | |
283 | static unsigned long zynq_clk_periph_get_rate(struct clk *clk) | |
284 | { | |
285 | u32 clk_ctrl = readl(clk->reg); | |
286 | u32 div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT; | |
287 | u32 div1 = 1; | |
288 | ||
289 | if (clk->flags & ZYNQ_CLK_FLAGS_HAS_2_DIVS) | |
290 | div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT; | |
291 | ||
292 | /* a register value of zero == division by 1 */ | |
293 | if (!div0) | |
294 | div0 = 1; | |
295 | if (!div1) | |
296 | div1 = 1; | |
297 | ||
298 | return | |
299 | DIV_ROUND_CLOSEST( | |
300 | DIV_ROUND_CLOSEST(zynq_clk_get_rate(clk->parent), div0), | |
301 | div1); | |
302 | } | |
303 | ||
304 | /** | |
305 | * __zynq_clk_periph_get_parent() - Decode clock multiplexer | |
306 | * @srcsel: Mux select value | |
307 | * Returns the clock identifier associated with the selected mux input. | |
308 | */ | |
309 | static enum zynq_clk __zynq_clk_periph_get_parent(u32 srcsel) | |
310 | { | |
311 | switch (srcsel) { | |
312 | case ZYNQ_CLKMUX_SEL_0: | |
313 | case ZYNQ_CLKMUX_SEL_1: | |
314 | return iopll_clk; | |
315 | case ZYNQ_CLKMUX_SEL_2: | |
316 | return armpll_clk; | |
317 | case ZYNQ_CLKMUX_SEL_3: | |
318 | return ddrpll_clk; | |
319 | default: | |
320 | return 0; | |
321 | } | |
322 | } | |
323 | ||
324 | /** | |
325 | * zynq_clk_periph_get_parent() - Decode clock multiplexer | |
326 | * @clk: Clock handle | |
327 | * Returns the clock identifier associated with the selected mux input. | |
328 | */ | |
329 | static enum zynq_clk zynq_clk_periph_get_parent(struct clk *clk) | |
330 | { | |
331 | u32 clk_ctrl = readl(clk->reg); | |
332 | u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT; | |
333 | ||
334 | return __zynq_clk_periph_get_parent(srcsel); | |
335 | } | |
336 | ||
337 | /** | |
338 | * zynq_clk_register_periph_clk() - Set up a peripheral clock with the framework | |
339 | * @clk: Pointer to struct clk for the clock | |
340 | * @ctrl: Clock control register | |
341 | * @name: PLL name | |
342 | * @two_divs: Indicates whether the clock features one or two dividers | |
343 | */ | |
344 | static int zynq_clk_register_periph_clk(struct clk *clk, u32 *ctrl, char *name, | |
345 | bool two_divs) | |
346 | { | |
347 | clk->name = name; | |
348 | clk->reg = ctrl; | |
349 | if (two_divs) | |
350 | clk->flags = ZYNQ_CLK_FLAGS_HAS_2_DIVS; | |
351 | clk->parent = zynq_clk_periph_get_parent(clk); | |
352 | clk->frequency = zynq_clk_periph_get_rate(clk); | |
353 | clk->ops.get_rate = zynq_clk_periph_get_rate; | |
354 | clk->ops.set_rate = zynq_clk_periph_set_rate; | |
355 | ||
356 | return 0; | |
357 | } | |
358 | ||
359 | static void init_periph_clocks(void) | |
360 | { | |
361 | zynq_clk_register_periph_clk(&clks[gem0_clk], &slcr_base->gem0_clk_ctrl, | |
362 | "gem0", 1); | |
363 | zynq_clk_register_periph_clk(&clks[gem1_clk], &slcr_base->gem1_clk_ctrl, | |
364 | "gem1", 1); | |
365 | ||
366 | zynq_clk_register_periph_clk(&clks[smc_clk], &slcr_base->smc_clk_ctrl, | |
367 | "smc", 0); | |
368 | ||
369 | zynq_clk_register_periph_clk(&clks[lqspi_clk], | |
370 | &slcr_base->lqspi_clk_ctrl, "lqspi", 0); | |
371 | ||
372 | zynq_clk_register_periph_clk(&clks[sdio0_clk], | |
373 | &slcr_base->sdio_clk_ctrl, "sdio0", 0); | |
374 | zynq_clk_register_periph_clk(&clks[sdio1_clk], | |
375 | &slcr_base->sdio_clk_ctrl, "sdio1", 0); | |
376 | ||
377 | zynq_clk_register_periph_clk(&clks[spi0_clk], &slcr_base->spi_clk_ctrl, | |
378 | "spi0", 0); | |
379 | zynq_clk_register_periph_clk(&clks[spi1_clk], &slcr_base->spi_clk_ctrl, | |
380 | "spi1", 0); | |
381 | ||
382 | zynq_clk_register_periph_clk(&clks[uart0_clk], | |
383 | &slcr_base->uart_clk_ctrl, "uart0", 0); | |
384 | zynq_clk_register_periph_clk(&clks[uart1_clk], | |
385 | &slcr_base->uart_clk_ctrl, "uart1", 0); | |
386 | ||
387 | zynq_clk_register_periph_clk(&clks[dbg_trc_clk], | |
388 | &slcr_base->dbg_clk_ctrl, "dbg_trc", 0); | |
389 | zynq_clk_register_periph_clk(&clks[dbg_apb_clk], | |
390 | &slcr_base->dbg_clk_ctrl, "dbg_apb", 0); | |
391 | ||
392 | zynq_clk_register_periph_clk(&clks[pcap_clk], | |
393 | &slcr_base->pcap_clk_ctrl, "pcap", 0); | |
394 | ||
395 | zynq_clk_register_periph_clk(&clks[fclk0_clk], | |
396 | &slcr_base->fpga0_clk_ctrl, "fclk0", 1); | |
397 | zynq_clk_register_periph_clk(&clks[fclk1_clk], | |
398 | &slcr_base->fpga1_clk_ctrl, "fclk1", 1); | |
399 | zynq_clk_register_periph_clk(&clks[fclk2_clk], | |
400 | &slcr_base->fpga2_clk_ctrl, "fclk2", 1); | |
401 | zynq_clk_register_periph_clk(&clks[fclk3_clk], | |
402 | &slcr_base->fpga3_clk_ctrl, "fclk3", 1); | |
403 | } | |
404 | ||
405 | /** | |
406 | * zynq_clk_register_aper_clk() - Set up a APER clock with the framework | |
407 | * @clk: Pointer to struct clk for the clock | |
408 | * @ctrl: Clock control register | |
409 | * @name: PLL name | |
410 | */ | |
411 | static void zynq_clk_register_aper_clk(struct clk *clk, u32 *ctrl, char *name) | |
412 | { | |
413 | clk->name = name; | |
414 | clk->reg = ctrl; | |
415 | clk->parent = cpu_1x_clk; | |
416 | clk->frequency = zynq_clk_get_rate(clk->parent); | |
417 | } | |
418 | ||
419 | static void init_aper_clocks(void) | |
420 | { | |
421 | zynq_clk_register_aper_clk(&clks[usb0_aper_clk], | |
422 | &slcr_base->aper_clk_ctrl, "usb0_aper"); | |
423 | zynq_clk_register_aper_clk(&clks[usb1_aper_clk], | |
424 | &slcr_base->aper_clk_ctrl, "usb1_aper"); | |
425 | ||
426 | zynq_clk_register_aper_clk(&clks[gem0_aper_clk], | |
427 | &slcr_base->aper_clk_ctrl, "gem0_aper"); | |
428 | zynq_clk_register_aper_clk(&clks[gem1_aper_clk], | |
429 | &slcr_base->aper_clk_ctrl, "gem1_aper"); | |
430 | ||
431 | zynq_clk_register_aper_clk(&clks[sdio0_aper_clk], | |
432 | &slcr_base->aper_clk_ctrl, "sdio0_aper"); | |
433 | zynq_clk_register_aper_clk(&clks[sdio1_aper_clk], | |
434 | &slcr_base->aper_clk_ctrl, "sdio1_aper"); | |
435 | ||
436 | zynq_clk_register_aper_clk(&clks[spi0_aper_clk], | |
437 | &slcr_base->aper_clk_ctrl, "spi0_aper"); | |
438 | zynq_clk_register_aper_clk(&clks[spi1_aper_clk], | |
439 | &slcr_base->aper_clk_ctrl, "spi1_aper"); | |
440 | ||
441 | zynq_clk_register_aper_clk(&clks[can0_aper_clk], | |
442 | &slcr_base->aper_clk_ctrl, "can0_aper"); | |
443 | zynq_clk_register_aper_clk(&clks[can1_aper_clk], | |
444 | &slcr_base->aper_clk_ctrl, "can1_aper"); | |
445 | ||
446 | zynq_clk_register_aper_clk(&clks[i2c0_aper_clk], | |
447 | &slcr_base->aper_clk_ctrl, "i2c0_aper"); | |
448 | zynq_clk_register_aper_clk(&clks[i2c1_aper_clk], | |
449 | &slcr_base->aper_clk_ctrl, "i2c1_aper"); | |
450 | ||
451 | zynq_clk_register_aper_clk(&clks[uart0_aper_clk], | |
452 | &slcr_base->aper_clk_ctrl, "uart0_aper"); | |
453 | zynq_clk_register_aper_clk(&clks[uart1_aper_clk], | |
454 | &slcr_base->aper_clk_ctrl, "uart1_aper"); | |
455 | ||
456 | zynq_clk_register_aper_clk(&clks[gpio_aper_clk], | |
457 | &slcr_base->aper_clk_ctrl, "gpio_aper"); | |
458 | ||
459 | zynq_clk_register_aper_clk(&clks[lqspi_aper_clk], | |
460 | &slcr_base->aper_clk_ctrl, "lqspi_aper"); | |
461 | ||
462 | zynq_clk_register_aper_clk(&clks[smc_aper_clk], | |
463 | &slcr_base->aper_clk_ctrl, "smc_aper"); | |
464 | } | |
465 | ||
466 | /** | |
467 | * __zynq_clk_pll_get_rate() - Get PLL rate | |
468 | * @addr: Address of the PLL's control register | |
469 | * Returns the current PLL output rate. | |
470 | */ | |
471 | static unsigned long __zynq_clk_pll_get_rate(u32 *addr) | |
472 | { | |
473 | u32 reg, mul, bypass; | |
474 | ||
475 | reg = readl(addr); | |
476 | bypass = reg & PLLCTRL_BPFORCE_MASK; | |
477 | if (bypass) | |
478 | mul = 1; | |
479 | else | |
480 | mul = (reg & PLLCTRL_FBDIV_MASK) >> PLLCTRL_FBDIV_SHIFT; | |
481 | ||
482 | return CONFIG_ZYNQ_PS_CLK_FREQ * mul; | |
483 | } | |
484 | ||
485 | /** | |
486 | * zynq_clk_pll_get_rate() - Get PLL rate | |
487 | * @pll: Handle of the PLL | |
488 | * Returns the current clock rate of @pll. | |
489 | */ | |
490 | static unsigned long zynq_clk_pll_get_rate(struct clk *pll) | |
491 | { | |
492 | return __zynq_clk_pll_get_rate(pll->reg); | |
493 | } | |
494 | ||
495 | /** | |
496 | * zynq_clk_register_pll() - Set up a PLL with the framework | |
497 | * @clk: Pointer to struct clk for the PLL | |
498 | * @ctrl: PLL control register | |
499 | * @name: PLL name | |
500 | * @prate: PLL input clock rate | |
501 | */ | |
502 | static void zynq_clk_register_pll(struct clk *clk, u32 *ctrl, char *name, | |
503 | unsigned long prate) | |
504 | { | |
505 | clk->name = name; | |
506 | clk->reg = ctrl; | |
507 | clk->frequency = zynq_clk_pll_get_rate(clk); | |
508 | clk->ops.get_rate = zynq_clk_pll_get_rate; | |
509 | } | |
510 | ||
511 | /** | |
512 | * clkid_2_register() - Get clock control register | |
513 | * @id: Clock identifier of one of the PLLs | |
514 | * Returns the address of the requested PLL's control register. | |
515 | */ | |
516 | static u32 *clkid_2_register(enum zynq_clk id) | |
517 | { | |
518 | switch (id) { | |
519 | case armpll_clk: | |
520 | return &slcr_base->arm_pll_ctrl; | |
521 | case ddrpll_clk: | |
522 | return &slcr_base->ddr_pll_ctrl; | |
523 | case iopll_clk: | |
524 | return &slcr_base->io_pll_ctrl; | |
525 | default: | |
526 | return &slcr_base->io_pll_ctrl; | |
527 | } | |
528 | } | |
529 | ||
530 | /* API */ | |
531 | /** | |
532 | * zynq_clk_early_init() - Early init for the clock framework | |
533 | * | |
534 | * This function is called from before relocation and sets up the CPU clock | |
535 | * frequency in the global data struct. | |
536 | */ | |
537 | void zynq_clk_early_init(void) | |
538 | { | |
539 | u32 reg = readl(&slcr_base->arm_clk_ctrl); | |
540 | u32 div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT; | |
541 | u32 srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT; | |
542 | enum zynq_clk parent = __zynq_clk_cpu_get_parent(srcsel); | |
543 | u32 *pllreg = clkid_2_register(parent); | |
544 | unsigned long prate = __zynq_clk_pll_get_rate(pllreg); | |
545 | ||
546 | if (!div) | |
547 | div = 1; | |
548 | ||
549 | gd->cpu_clk = DIV_ROUND_CLOSEST(prate, div); | |
550 | } | |
551 | ||
552 | /** | |
553 | * get_uart_clk() - Get UART input frequency | |
554 | * @dev_index: UART ID | |
555 | * Returns UART input clock frequency in Hz. | |
556 | * | |
557 | * Compared to zynq_clk_get_rate() this function is designed to work before | |
558 | * relocation and can be called when the serial UART is set up. | |
559 | */ | |
560 | unsigned long get_uart_clk(int dev_index) | |
561 | { | |
562 | u32 reg = readl(&slcr_base->uart_clk_ctrl); | |
563 | u32 div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT; | |
564 | u32 srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT; | |
565 | enum zynq_clk parent = __zynq_clk_periph_get_parent(srcsel); | |
566 | u32 *pllreg = clkid_2_register(parent); | |
567 | unsigned long prate = __zynq_clk_pll_get_rate(pllreg); | |
568 | ||
569 | if (!div) | |
570 | div = 1; | |
571 | ||
572 | return DIV_ROUND_CLOSEST(prate, div); | |
573 | } | |
574 | ||
575 | /** | |
576 | * set_cpu_clk_info() - Initialize clock framework | |
577 | * Always returns zero. | |
578 | * | |
579 | * This function is called from common code after relocation and sets up the | |
580 | * clock framework. The framework must not be used before this function had been | |
581 | * called. | |
582 | */ | |
583 | int set_cpu_clk_info(void) | |
584 | { | |
585 | zynq_clk_register_pll(&clks[armpll_clk], &slcr_base->arm_pll_ctrl, | |
586 | "armpll", CONFIG_ZYNQ_PS_CLK_FREQ); | |
587 | zynq_clk_register_pll(&clks[ddrpll_clk], &slcr_base->ddr_pll_ctrl, | |
588 | "ddrpll", CONFIG_ZYNQ_PS_CLK_FREQ); | |
589 | zynq_clk_register_pll(&clks[iopll_clk], &slcr_base->io_pll_ctrl, | |
590 | "iopll", CONFIG_ZYNQ_PS_CLK_FREQ); | |
591 | ||
592 | init_ddr_clocks(); | |
593 | init_cpu_clocks(); | |
594 | init_periph_clocks(); | |
595 | init_aper_clocks(); | |
596 | ||
96a5d4dc MS |
597 | gd->bd->bi_arm_freq = gd->cpu_clk / 1000000; |
598 | gd->bd->bi_dsp_freq = 0; | |
599 | ||
6c3e61de SB |
600 | return 0; |
601 | } | |
602 | ||
603 | /** | |
604 | * zynq_clk_get_rate() - Get clock rate | |
605 | * @clk: Clock identifier | |
606 | * Returns the current clock rate of @clk on success or zero for an invalid | |
607 | * clock id. | |
608 | */ | |
609 | unsigned long zynq_clk_get_rate(enum zynq_clk clk) | |
610 | { | |
611 | if (clk < 0 || clk >= clk_max) | |
612 | return 0; | |
613 | ||
614 | return clks[clk].frequency; | |
615 | } | |
616 | ||
617 | /** | |
618 | * zynq_clk_set_rate() - Set clock rate | |
619 | * @clk: Clock identifier | |
620 | * @rate: Requested clock rate | |
621 | * Passes on the return value from the clock's set_rate() function or negative | |
622 | * errno. | |
623 | */ | |
624 | int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate) | |
625 | { | |
626 | if (clk < 0 || clk >= clk_max) | |
627 | return -ENODEV; | |
628 | ||
629 | if (clks[clk].ops.set_rate) | |
630 | return clks[clk].ops.set_rate(&clks[clk], rate); | |
631 | ||
632 | return -ENXIO; | |
633 | } | |
634 | ||
635 | /** | |
636 | * zynq_clk_get_name() - Get clock name | |
637 | * @clk: Clock identifier | |
638 | * Returns the name of @clk. | |
639 | */ | |
640 | const char *zynq_clk_get_name(enum zynq_clk clk) | |
641 | { | |
642 | return clks[clk].name; | |
643 | } | |
d6c9bbaa SB |
644 | |
645 | /** | |
646 | * soc_clk_dump() - Print clock frequencies | |
647 | * Returns zero on success | |
648 | * | |
649 | * Implementation for the clk dump command. | |
650 | */ | |
651 | int soc_clk_dump(void) | |
652 | { | |
653 | int i; | |
654 | ||
655 | printf("clk\t\tfrequency\n"); | |
656 | for (i = 0; i < clk_max; i++) { | |
657 | const char *name = zynq_clk_get_name(i); | |
658 | if (name) | |
659 | printf("%10s%20lu\n", name, zynq_clk_get_rate(i)); | |
660 | } | |
661 | ||
662 | return 0; | |
663 | } |