167f3f75a19cf6a593a97093e358a151bc83ef21
[oweals/u-boot.git] / drivers / clk / clk_zynqmp.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * ZynqMP clock driver
4  *
5  * Copyright (C) 2016 Xilinx, Inc.
6  */
7
8 #include <common.h>
9 #include <linux/bitops.h>
10 #include <clk-uclass.h>
11 #include <clk.h>
12 #include <asm/arch/sys_proto.h>
13 #include <dm.h>
14
15 static const resource_size_t zynqmp_crf_apb_clkc_base = 0xfd1a0020;
16 static const resource_size_t zynqmp_crl_apb_clkc_base = 0xff5e0020;
17
18 /* Full power domain clocks */
19 #define CRF_APB_APLL_CTRL               (zynqmp_crf_apb_clkc_base + 0x00)
20 #define CRF_APB_DPLL_CTRL               (zynqmp_crf_apb_clkc_base + 0x0c)
21 #define CRF_APB_VPLL_CTRL               (zynqmp_crf_apb_clkc_base + 0x18)
22 #define CRF_APB_PLL_STATUS              (zynqmp_crf_apb_clkc_base + 0x24)
23 #define CRF_APB_APLL_TO_LPD_CTRL        (zynqmp_crf_apb_clkc_base + 0x28)
24 #define CRF_APB_DPLL_TO_LPD_CTRL        (zynqmp_crf_apb_clkc_base + 0x2c)
25 #define CRF_APB_VPLL_TO_LPD_CTRL        (zynqmp_crf_apb_clkc_base + 0x30)
26 /* Peripheral clocks */
27 #define CRF_APB_ACPU_CTRL               (zynqmp_crf_apb_clkc_base + 0x40)
28 #define CRF_APB_DBG_TRACE_CTRL          (zynqmp_crf_apb_clkc_base + 0x44)
29 #define CRF_APB_DBG_FPD_CTRL            (zynqmp_crf_apb_clkc_base + 0x48)
30 #define CRF_APB_DP_VIDEO_REF_CTRL       (zynqmp_crf_apb_clkc_base + 0x50)
31 #define CRF_APB_DP_AUDIO_REF_CTRL       (zynqmp_crf_apb_clkc_base + 0x54)
32 #define CRF_APB_DP_STC_REF_CTRL         (zynqmp_crf_apb_clkc_base + 0x5c)
33 #define CRF_APB_DDR_CTRL                (zynqmp_crf_apb_clkc_base + 0x60)
34 #define CRF_APB_GPU_REF_CTRL            (zynqmp_crf_apb_clkc_base + 0x64)
35 #define CRF_APB_SATA_REF_CTRL           (zynqmp_crf_apb_clkc_base + 0x80)
36 #define CRF_APB_PCIE_REF_CTRL           (zynqmp_crf_apb_clkc_base + 0x94)
37 #define CRF_APB_GDMA_REF_CTRL           (zynqmp_crf_apb_clkc_base + 0x98)
38 #define CRF_APB_DPDMA_REF_CTRL          (zynqmp_crf_apb_clkc_base + 0x9c)
39 #define CRF_APB_TOPSW_MAIN_CTRL         (zynqmp_crf_apb_clkc_base + 0xa0)
40 #define CRF_APB_TOPSW_LSBUS_CTRL        (zynqmp_crf_apb_clkc_base + 0xa4)
41 #define CRF_APB_GTGREF0_REF_CTRL        (zynqmp_crf_apb_clkc_base + 0xa8)
42 #define CRF_APB_DBG_TSTMP_CTRL          (zynqmp_crf_apb_clkc_base + 0xd8)
43
44 /* Low power domain clocks */
45 #define CRL_APB_IOPLL_CTRL              (zynqmp_crl_apb_clkc_base + 0x00)
46 #define CRL_APB_RPLL_CTRL               (zynqmp_crl_apb_clkc_base + 0x10)
47 #define CRL_APB_PLL_STATUS              (zynqmp_crl_apb_clkc_base + 0x20)
48 #define CRL_APB_IOPLL_TO_FPD_CTRL       (zynqmp_crl_apb_clkc_base + 0x24)
49 #define CRL_APB_RPLL_TO_FPD_CTRL        (zynqmp_crl_apb_clkc_base + 0x28)
50 /* Peripheral clocks */
51 #define CRL_APB_USB3_DUAL_REF_CTRL      (zynqmp_crl_apb_clkc_base + 0x2c)
52 #define CRL_APB_GEM0_REF_CTRL           (zynqmp_crl_apb_clkc_base + 0x30)
53 #define CRL_APB_GEM1_REF_CTRL           (zynqmp_crl_apb_clkc_base + 0x34)
54 #define CRL_APB_GEM2_REF_CTRL           (zynqmp_crl_apb_clkc_base + 0x38)
55 #define CRL_APB_GEM3_REF_CTRL           (zynqmp_crl_apb_clkc_base + 0x3c)
56 #define CRL_APB_USB0_BUS_REF_CTRL       (zynqmp_crl_apb_clkc_base + 0x40)
57 #define CRL_APB_USB1_BUS_REF_CTRL       (zynqmp_crl_apb_clkc_base + 0x44)
58 #define CRL_APB_QSPI_REF_CTRL           (zynqmp_crl_apb_clkc_base + 0x48)
59 #define CRL_APB_SDIO0_REF_CTRL          (zynqmp_crl_apb_clkc_base + 0x4c)
60 #define CRL_APB_SDIO1_REF_CTRL          (zynqmp_crl_apb_clkc_base + 0x50)
61 #define CRL_APB_UART0_REF_CTRL          (zynqmp_crl_apb_clkc_base + 0x54)
62 #define CRL_APB_UART1_REF_CTRL          (zynqmp_crl_apb_clkc_base + 0x58)
63 #define CRL_APB_SPI0_REF_CTRL           (zynqmp_crl_apb_clkc_base + 0x5c)
64 #define CRL_APB_SPI1_REF_CTRL           (zynqmp_crl_apb_clkc_base + 0x60)
65 #define CRL_APB_CAN0_REF_CTRL           (zynqmp_crl_apb_clkc_base + 0x64)
66 #define CRL_APB_CAN1_REF_CTRL           (zynqmp_crl_apb_clkc_base + 0x68)
67 #define CRL_APB_CPU_R5_CTRL             (zynqmp_crl_apb_clkc_base + 0x70)
68 #define CRL_APB_IOU_SWITCH_CTRL         (zynqmp_crl_apb_clkc_base + 0x7c)
69 #define CRL_APB_CSU_PLL_CTRL            (zynqmp_crl_apb_clkc_base + 0x80)
70 #define CRL_APB_PCAP_CTRL               (zynqmp_crl_apb_clkc_base + 0x84)
71 #define CRL_APB_LPD_SWITCH_CTRL         (zynqmp_crl_apb_clkc_base + 0x88)
72 #define CRL_APB_LPD_LSBUS_CTRL          (zynqmp_crl_apb_clkc_base + 0x8c)
73 #define CRL_APB_DBG_LPD_CTRL            (zynqmp_crl_apb_clkc_base + 0x90)
74 #define CRL_APB_NAND_REF_CTRL           (zynqmp_crl_apb_clkc_base + 0x94)
75 #define CRL_APB_ADMA_REF_CTRL           (zynqmp_crl_apb_clkc_base + 0x98)
76 #define CRL_APB_PL0_REF_CTRL            (zynqmp_crl_apb_clkc_base + 0xa0)
77 #define CRL_APB_PL1_REF_CTRL            (zynqmp_crl_apb_clkc_base + 0xa4)
78 #define CRL_APB_PL2_REF_CTRL            (zynqmp_crl_apb_clkc_base + 0xa8)
79 #define CRL_APB_PL3_REF_CTRL            (zynqmp_crl_apb_clkc_base + 0xac)
80 #define CRL_APB_PL0_THR_CNT             (zynqmp_crl_apb_clkc_base + 0xb4)
81 #define CRL_APB_PL1_THR_CNT             (zynqmp_crl_apb_clkc_base + 0xbc)
82 #define CRL_APB_PL2_THR_CNT             (zynqmp_crl_apb_clkc_base + 0xc4)
83 #define CRL_APB_PL3_THR_CNT             (zynqmp_crl_apb_clkc_base + 0xdc)
84 #define CRL_APB_GEM_TSU_REF_CTRL        (zynqmp_crl_apb_clkc_base + 0xe0)
85 #define CRL_APB_DLL_REF_CTRL            (zynqmp_crl_apb_clkc_base + 0xe4)
86 #define CRL_APB_AMS_REF_CTRL            (zynqmp_crl_apb_clkc_base + 0xe8)
87 #define CRL_APB_I2C0_REF_CTRL           (zynqmp_crl_apb_clkc_base + 0x100)
88 #define CRL_APB_I2C1_REF_CTRL           (zynqmp_crl_apb_clkc_base + 0x104)
89 #define CRL_APB_TIMESTAMP_REF_CTRL      (zynqmp_crl_apb_clkc_base + 0x108)
90
91 #define ZYNQ_CLK_MAXDIV         0x3f
92 #define CLK_CTRL_DIV1_SHIFT     16
93 #define CLK_CTRL_DIV1_MASK      (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT)
94 #define CLK_CTRL_DIV0_SHIFT     8
95 #define CLK_CTRL_DIV0_MASK      (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT)
96 #define CLK_CTRL_SRCSEL_SHIFT   0
97 #define CLK_CTRL_SRCSEL_MASK    (0x3 << CLK_CTRL_SRCSEL_SHIFT)
98 #define PLLCTRL_FBDIV_MASK      0x7f00
99 #define PLLCTRL_FBDIV_SHIFT     8
100 #define PLLCTRL_RESET_MASK      1
101 #define PLLCTRL_RESET_SHIFT     0
102 #define PLLCTRL_BYPASS_MASK     0x8
103 #define PLLCTRL_BYPASS_SHFT     3
104 #define PLLCTRL_POST_SRC_SHFT   24
105 #define PLLCTRL_POST_SRC_MASK   (0x7 << PLLCTRL_POST_SRC_SHFT)
106 #define PLLCTRL_PRE_SRC_SHFT    20
107 #define PLLCTRL_PRE_SRC_MASK    (0x7 << PLLCTRL_PRE_SRC_SHFT)
108
109
110 #define NUM_MIO_PINS    77
111
112 enum zynqmp_clk {
113         iopll, rpll,
114         apll, dpll, vpll,
115         iopll_to_fpd, rpll_to_fpd, apll_to_lpd, dpll_to_lpd, vpll_to_lpd,
116         acpu, acpu_half,
117         dbg_fpd, dbg_lpd, dbg_trace, dbg_tstmp,
118         dp_video_ref, dp_audio_ref,
119         dp_stc_ref, gdma_ref, dpdma_ref,
120         ddr_ref, sata_ref, pcie_ref,
121         gpu_ref, gpu_pp0_ref, gpu_pp1_ref,
122         topsw_main, topsw_lsbus,
123         gtgref0_ref,
124         lpd_switch, lpd_lsbus,
125         usb0_bus_ref, usb1_bus_ref, usb3_dual_ref, usb0, usb1,
126         cpu_r5, cpu_r5_core,
127         csu_spb, csu_pll, pcap,
128         iou_switch,
129         gem_tsu_ref, gem_tsu,
130         gem0_ref, gem1_ref, gem2_ref, gem3_ref,
131         gem0_rx, gem1_rx, gem2_rx, gem3_rx,
132         qspi_ref,
133         sdio0_ref, sdio1_ref,
134         uart0_ref, uart1_ref,
135         spi0_ref, spi1_ref,
136         nand_ref,
137         i2c0_ref, i2c1_ref, can0_ref, can1_ref, can0, can1,
138         dll_ref,
139         adma_ref,
140         timestamp_ref,
141         ams_ref,
142         pl0, pl1, pl2, pl3,
143         wdt,
144         clk_max,
145 };
146
147 static const char * const clk_names[clk_max] = {
148         "iopll", "rpll", "apll", "dpll",
149         "vpll", "iopll_to_fpd", "rpll_to_fpd",
150         "apll_to_lpd", "dpll_to_lpd", "vpll_to_lpd",
151         "acpu", "acpu_half", "dbf_fpd", "dbf_lpd",
152         "dbg_trace", "dbg_tstmp", "dp_video_ref",
153         "dp_audio_ref", "dp_stc_ref", "gdma_ref",
154         "dpdma_ref", "ddr_ref", "sata_ref", "pcie_ref",
155         "gpu_ref", "gpu_pp0_ref", "gpu_pp1_ref",
156         "topsw_main", "topsw_lsbus", "gtgref0_ref",
157         "lpd_switch", "lpd_lsbus", "usb0_bus_ref",
158         "usb1_bus_ref", "usb3_dual_ref", "usb0",
159         "usb1", "cpu_r5", "cpu_r5_core", "csu_spb",
160         "csu_pll", "pcap", "iou_switch", "gem_tsu_ref",
161         "gem_tsu", "gem0_ref", "gem1_ref", "gem2_ref",
162         "gem3_ref", "gem0_tx", "gem1_tx", "gem2_tx",
163         "gem3_tx", "qspi_ref", "sdio0_ref", "sdio1_ref",
164         "uart0_ref", "uart1_ref", "spi0_ref",
165         "spi1_ref", "nand_ref", "i2c0_ref", "i2c1_ref",
166         "can0_ref", "can1_ref", "can0", "can1",
167         "dll_ref", "adma_ref", "timestamp_ref",
168         "ams_ref", "pl0", "pl1", "pl2", "pl3", "wdt"
169 };
170
171 struct zynqmp_clk_priv {
172         unsigned long ps_clk_freq;
173         unsigned long video_clk;
174         unsigned long pss_alt_ref_clk;
175         unsigned long gt_crx_ref_clk;
176         unsigned long aux_ref_clk;
177 };
178
179 static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
180 {
181         switch (id) {
182         case iopll:
183                 return CRL_APB_IOPLL_CTRL;
184         case rpll:
185                 return CRL_APB_RPLL_CTRL;
186         case apll:
187                 return CRF_APB_APLL_CTRL;
188         case dpll:
189                 return CRF_APB_DPLL_CTRL;
190         case vpll:
191                 return CRF_APB_VPLL_CTRL;
192         case acpu:
193                 return CRF_APB_ACPU_CTRL;
194         case ddr_ref:
195                 return CRF_APB_DDR_CTRL;
196         case qspi_ref:
197                 return CRL_APB_QSPI_REF_CTRL;
198         case gem0_ref:
199                 return CRL_APB_GEM0_REF_CTRL;
200         case gem1_ref:
201                 return CRL_APB_GEM1_REF_CTRL;
202         case gem2_ref:
203                 return CRL_APB_GEM2_REF_CTRL;
204         case gem3_ref:
205                 return CRL_APB_GEM3_REF_CTRL;
206         case uart0_ref:
207                 return CRL_APB_UART0_REF_CTRL;
208         case uart1_ref:
209                 return CRL_APB_UART1_REF_CTRL;
210         case sdio0_ref:
211                 return CRL_APB_SDIO0_REF_CTRL;
212         case sdio1_ref:
213                 return CRL_APB_SDIO1_REF_CTRL;
214         case spi0_ref:
215                 return CRL_APB_SPI0_REF_CTRL;
216         case spi1_ref:
217                 return CRL_APB_SPI1_REF_CTRL;
218         case nand_ref:
219                 return CRL_APB_NAND_REF_CTRL;
220         case i2c0_ref:
221                 return CRL_APB_I2C0_REF_CTRL;
222         case i2c1_ref:
223                 return CRL_APB_I2C1_REF_CTRL;
224         case can0_ref:
225                 return CRL_APB_CAN0_REF_CTRL;
226         case can1_ref:
227                 return CRL_APB_CAN1_REF_CTRL;
228         case pl0:
229                 return CRL_APB_PL0_REF_CTRL;
230         case pl1:
231                 return CRL_APB_PL1_REF_CTRL;
232         case pl2:
233                 return CRL_APB_PL2_REF_CTRL;
234         case pl3:
235                 return CRL_APB_PL3_REF_CTRL;
236         case wdt:
237                 return CRF_APB_TOPSW_LSBUS_CTRL;
238         case iopll_to_fpd:
239                 return CRL_APB_IOPLL_TO_FPD_CTRL;
240         default:
241                 debug("Invalid clk id%d\n", id);
242         }
243         return 0;
244 }
245
246 static enum zynqmp_clk zynqmp_clk_get_cpu_pll(u32 clk_ctrl)
247 {
248         u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
249                       CLK_CTRL_SRCSEL_SHIFT;
250
251         switch (srcsel) {
252         case 2:
253                 return dpll;
254         case 3:
255                 return vpll;
256         case 0 ... 1:
257         default:
258                 return apll;
259         }
260 }
261
262 static enum zynqmp_clk zynqmp_clk_get_ddr_pll(u32 clk_ctrl)
263 {
264         u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
265                       CLK_CTRL_SRCSEL_SHIFT;
266
267         switch (srcsel) {
268         case 1:
269                 return vpll;
270         case 0:
271         default:
272                 return dpll;
273         }
274 }
275
276 static enum zynqmp_clk zynqmp_clk_get_peripheral_pll(u32 clk_ctrl)
277 {
278         u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
279                       CLK_CTRL_SRCSEL_SHIFT;
280
281         switch (srcsel) {
282         case 2:
283                 return rpll;
284         case 3:
285                 return dpll;
286         case 0 ... 1:
287         default:
288                 return iopll;
289         }
290 }
291
292 static enum zynqmp_clk zynqmp_clk_get_wdt_pll(u32 clk_ctrl)
293 {
294         u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
295                       CLK_CTRL_SRCSEL_SHIFT;
296
297         switch (srcsel) {
298         case 2:
299                 return iopll_to_fpd;
300         case 3:
301                 return dpll;
302         case 0 ... 1:
303         default:
304                 return apll;
305         }
306 }
307
308 static ulong zynqmp_clk_get_pll_src(ulong clk_ctrl,
309                                     struct zynqmp_clk_priv *priv,
310                                     bool is_pre_src)
311 {
312         u32 src_sel;
313
314         if (is_pre_src)
315                 src_sel = (clk_ctrl & PLLCTRL_PRE_SRC_MASK) >>
316                            PLLCTRL_PRE_SRC_SHFT;
317         else
318                 src_sel = (clk_ctrl & PLLCTRL_POST_SRC_MASK) >>
319                            PLLCTRL_POST_SRC_SHFT;
320
321         switch (src_sel) {
322         case 4:
323                 return priv->video_clk;
324         case 5:
325                 return priv->pss_alt_ref_clk;
326         case 6:
327                 return priv->aux_ref_clk;
328         case 7:
329                 return priv->gt_crx_ref_clk;
330         case 0 ... 3:
331         default:
332         return priv->ps_clk_freq;
333         }
334 }
335
336 static ulong zynqmp_clk_get_pll_rate(struct zynqmp_clk_priv *priv,
337                                      enum zynqmp_clk id)
338 {
339         u32 clk_ctrl, reset, mul;
340         ulong freq;
341         int ret;
342
343         ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
344         if (ret) {
345                 printf("%s mio read fail\n", __func__);
346                 return -EIO;
347         }
348
349         if (clk_ctrl & PLLCTRL_BYPASS_MASK)
350                 freq = zynqmp_clk_get_pll_src(clk_ctrl, priv, 0);
351         else
352                 freq = zynqmp_clk_get_pll_src(clk_ctrl, priv, 1);
353
354         reset = (clk_ctrl & PLLCTRL_RESET_MASK) >> PLLCTRL_RESET_SHIFT;
355         if (reset && !(clk_ctrl & PLLCTRL_BYPASS_MASK))
356                 return 0;
357
358         mul = (clk_ctrl & PLLCTRL_FBDIV_MASK) >> PLLCTRL_FBDIV_SHIFT;
359
360         freq *= mul;
361
362         if (clk_ctrl & (1 << 16))
363                 freq /= 2;
364
365         return freq;
366 }
367
368 static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
369                                      enum zynqmp_clk id)
370 {
371         u32 clk_ctrl, div;
372         enum zynqmp_clk pll;
373         int ret;
374         unsigned long pllrate;
375
376         ret = zynqmp_mmio_read(CRF_APB_ACPU_CTRL, &clk_ctrl);
377         if (ret) {
378                 printf("%s mio read fail\n", __func__);
379                 return -EIO;
380         }
381
382         div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
383
384         pll = zynqmp_clk_get_cpu_pll(clk_ctrl);
385         pllrate = zynqmp_clk_get_pll_rate(priv, pll);
386         if (IS_ERR_VALUE(pllrate))
387                 return pllrate;
388
389         return DIV_ROUND_CLOSEST(pllrate, div);
390 }
391
392 static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
393 {
394         u32 clk_ctrl, div;
395         enum zynqmp_clk pll;
396         int ret;
397         ulong pllrate;
398
399         ret = zynqmp_mmio_read(CRF_APB_DDR_CTRL, &clk_ctrl);
400         if (ret) {
401                 printf("%s mio read fail\n", __func__);
402                 return -EIO;
403         }
404
405         div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
406
407         pll = zynqmp_clk_get_ddr_pll(clk_ctrl);
408         pllrate = zynqmp_clk_get_pll_rate(priv, pll);
409         if (IS_ERR_VALUE(pllrate))
410                 return pllrate;
411
412         return DIV_ROUND_CLOSEST(pllrate, div);
413 }
414
415 static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv,
416                                           enum zynqmp_clk id, bool two_divs)
417 {
418         enum zynqmp_clk pll;
419         u32 clk_ctrl, div0;
420         u32 div1 = 1;
421         int ret;
422         ulong pllrate;
423
424         ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
425         if (ret) {
426                 printf("%s mio read fail\n", __func__);
427                 return -EIO;
428         }
429
430         div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
431         if (!div0)
432                 div0 = 1;
433
434         if (two_divs) {
435                 div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
436                 if (!div1)
437                         div1 = 1;
438         }
439
440         pll = zynqmp_clk_get_peripheral_pll(clk_ctrl);
441         pllrate = zynqmp_clk_get_pll_rate(priv, pll);
442         if (IS_ERR_VALUE(pllrate))
443                 return pllrate;
444
445         return
446                 DIV_ROUND_CLOSEST(
447                         DIV_ROUND_CLOSEST(pllrate, div0), div1);
448 }
449
450 static ulong zynqmp_clk_get_wdt_rate(struct zynqmp_clk_priv *priv,
451                                      enum zynqmp_clk id, bool two_divs)
452 {
453         enum zynqmp_clk pll;
454         u32 clk_ctrl, div0;
455         u32 div1 = 1;
456         int ret;
457         ulong pllrate;
458
459         ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
460         if (ret) {
461                 printf("%d %s mio read fail\n", __LINE__, __func__);
462                 return -EIO;
463         }
464
465         div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
466         if (!div0)
467                 div0 = 1;
468
469         pll = zynqmp_clk_get_wdt_pll(clk_ctrl);
470         if (two_divs) {
471                 ret = zynqmp_mmio_read(zynqmp_clk_get_register(pll), &clk_ctrl);
472                 if (ret) {
473                         printf("%d %s mio read fail\n", __LINE__, __func__);
474                         return -EIO;
475                 }
476                 div1 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
477                 if (!div1)
478                         div1 = 1;
479         }
480
481         if (pll == iopll_to_fpd)
482                 pll = iopll;
483
484         pllrate = zynqmp_clk_get_pll_rate(priv, pll);
485         if (IS_ERR_VALUE(pllrate))
486                 return pllrate;
487
488         return
489                 DIV_ROUND_CLOSEST(
490                         DIV_ROUND_CLOSEST(pllrate, div0), div1);
491 }
492
493 static unsigned long zynqmp_clk_calc_peripheral_two_divs(ulong rate,
494                                                        ulong pll_rate,
495                                                        u32 *div0, u32 *div1)
496 {
497         long new_err, best_err = (long)(~0UL >> 1);
498         ulong new_rate, best_rate = 0;
499         u32 d0, d1;
500
501         for (d0 = 1; d0 <= ZYNQ_CLK_MAXDIV; d0++) {
502                 for (d1 = 1; d1 <= ZYNQ_CLK_MAXDIV >> 1; d1++) {
503                         new_rate = DIV_ROUND_CLOSEST(
504                                         DIV_ROUND_CLOSEST(pll_rate, d0), d1);
505                         new_err = abs(new_rate - rate);
506
507                         if (new_err < best_err) {
508                                 *div0 = d0;
509                                 *div1 = d1;
510                                 best_err = new_err;
511                                 best_rate = new_rate;
512                         }
513                 }
514         }
515
516         return best_rate;
517 }
518
519 static ulong zynqmp_clk_set_peripheral_rate(struct zynqmp_clk_priv *priv,
520                                           enum zynqmp_clk id, ulong rate,
521                                           bool two_divs)
522 {
523         enum zynqmp_clk pll;
524         u32 clk_ctrl, div0 = 0, div1 = 0;
525         ulong pll_rate, new_rate;
526         u32 reg;
527         int ret;
528         u32 mask;
529
530         reg = zynqmp_clk_get_register(id);
531         ret = zynqmp_mmio_read(reg, &clk_ctrl);
532         if (ret) {
533                 printf("%s mio read fail\n", __func__);
534                 return -EIO;
535         }
536
537         pll = zynqmp_clk_get_peripheral_pll(clk_ctrl);
538         pll_rate = zynqmp_clk_get_pll_rate(priv, pll);
539         if (IS_ERR_VALUE(pll_rate))
540                 return pll_rate;
541
542         clk_ctrl &= ~CLK_CTRL_DIV0_MASK;
543         if (two_divs) {
544                 clk_ctrl &= ~CLK_CTRL_DIV1_MASK;
545                 new_rate = zynqmp_clk_calc_peripheral_two_divs(rate, pll_rate,
546                                 &div0, &div1);
547                 clk_ctrl |= div1 << CLK_CTRL_DIV1_SHIFT;
548         } else {
549                 div0 = DIV_ROUND_CLOSEST(pll_rate, rate);
550                 if (div0 > ZYNQ_CLK_MAXDIV)
551                         div0 = ZYNQ_CLK_MAXDIV;
552                 new_rate = DIV_ROUND_CLOSEST(rate, div0);
553         }
554         clk_ctrl |= div0 << CLK_CTRL_DIV0_SHIFT;
555
556         mask = (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT) |
557                (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT);
558
559         ret = zynqmp_mmio_write(reg, mask, clk_ctrl);
560         if (ret) {
561                 printf("%s mio write fail\n", __func__);
562                 return -EIO;
563         }
564
565         return new_rate;
566 }
567
568 static ulong zynqmp_clk_get_rate(struct clk *clk)
569 {
570         struct zynqmp_clk_priv *priv = dev_get_priv(clk->dev);
571         enum zynqmp_clk id = clk->id;
572         bool two_divs = false;
573
574         switch (id) {
575         case iopll ... vpll:
576                 return zynqmp_clk_get_pll_rate(priv, id);
577         case acpu:
578                 return zynqmp_clk_get_cpu_rate(priv, id);
579         case ddr_ref:
580                 return zynqmp_clk_get_ddr_rate(priv);
581         case gem0_ref ... gem3_ref:
582         case qspi_ref ... can1_ref:
583         case pl0 ... pl3:
584                 two_divs = true;
585                 return zynqmp_clk_get_peripheral_rate(priv, id, two_divs);
586         case wdt:
587                 two_divs = true;
588                 return zynqmp_clk_get_wdt_rate(priv, id, two_divs);
589         default:
590                 return -ENXIO;
591         }
592 }
593
594 static ulong zynqmp_clk_set_rate(struct clk *clk, ulong rate)
595 {
596         struct zynqmp_clk_priv *priv = dev_get_priv(clk->dev);
597         enum zynqmp_clk id = clk->id;
598         bool two_divs = true;
599
600         switch (id) {
601         case gem0_ref ... gem3_ref:
602         case qspi_ref ... can1_ref:
603                 return zynqmp_clk_set_peripheral_rate(priv, id,
604                                                       rate, two_divs);
605         default:
606                 return -ENXIO;
607         }
608 }
609
610 int soc_clk_dump(void)
611 {
612         struct udevice *dev;
613         int i, ret;
614
615         ret = uclass_get_device_by_driver(UCLASS_CLK,
616                 DM_GET_DRIVER(zynqmp_clk), &dev);
617         if (ret)
618                 return ret;
619
620         printf("clk\t\tfrequency\n");
621         for (i = 0; i < clk_max; i++) {
622                 const char *name = clk_names[i];
623                 if (name) {
624                         struct clk clk;
625                         unsigned long rate;
626
627                         clk.id = i;
628                         ret = clk_request(dev, &clk);
629                         if (ret < 0)
630                                 return ret;
631
632                         rate = clk_get_rate(&clk);
633
634                         clk_free(&clk);
635
636                         if ((rate == (unsigned long)-ENOSYS) ||
637                             (rate == (unsigned long)-ENXIO) ||
638                             (rate == (unsigned long)-EIO))
639                                 printf("%10s%20s\n", name, "unknown");
640                         else
641                                 printf("%10s%20lu\n", name, rate);
642                 }
643         }
644
645         return 0;
646 }
647
648 static int zynqmp_get_freq_by_name(char *name, struct udevice *dev, ulong *freq)
649 {
650         struct clk clk;
651         int ret;
652
653         ret = clk_get_by_name(dev, name, &clk);
654         if (ret < 0) {
655                 dev_err(dev, "failed to get %s\n", name);
656                 return ret;
657         }
658
659         *freq = clk_get_rate(&clk);
660         if (IS_ERR_VALUE(*freq)) {
661                 dev_err(dev, "failed to get rate %s\n", name);
662                 return -EINVAL;
663         }
664
665         return 0;
666 }
667 static int zynqmp_clk_probe(struct udevice *dev)
668 {
669         int ret;
670         struct zynqmp_clk_priv *priv = dev_get_priv(dev);
671
672         debug("%s\n", __func__);
673         ret = zynqmp_get_freq_by_name("pss_ref_clk", dev, &priv->ps_clk_freq);
674         if (ret < 0)
675                 return -EINVAL;
676
677         ret = zynqmp_get_freq_by_name("video_clk", dev, &priv->video_clk);
678         if (ret < 0)
679                 return -EINVAL;
680
681         ret = zynqmp_get_freq_by_name("pss_alt_ref_clk", dev,
682                                       &priv->pss_alt_ref_clk);
683         if (ret < 0)
684                 return -EINVAL;
685
686         ret = zynqmp_get_freq_by_name("aux_ref_clk", dev, &priv->aux_ref_clk);
687         if (ret < 0)
688                 return -EINVAL;
689
690         ret = zynqmp_get_freq_by_name("gt_crx_ref_clk", dev,
691                                       &priv->gt_crx_ref_clk);
692         if (ret < 0)
693                 return -EINVAL;
694
695         return 0;
696 }
697
698 static struct clk_ops zynqmp_clk_ops = {
699         .set_rate = zynqmp_clk_set_rate,
700         .get_rate = zynqmp_clk_get_rate,
701 };
702
703 static const struct udevice_id zynqmp_clk_ids[] = {
704         { .compatible = "xlnx,zynqmp-clk" },
705         { .compatible = "xlnx,zynqmp-clkc" },
706         { }
707 };
708
709 U_BOOT_DRIVER(zynqmp_clk) = {
710         .name = "zynqmp-clk",
711         .id = UCLASS_CLK,
712         .of_match = zynqmp_clk_ids,
713         .probe = zynqmp_clk_probe,
714         .ops = &zynqmp_clk_ops,
715         .priv_auto_alloc_size = sizeof(struct zynqmp_clk_priv),
716 };