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