1 // SPDX-License-Identifier: GPL-2.0+
5 * Copyright (C) 2016 Xilinx, Inc.
11 #include <dm/device_compat.h>
12 #include <linux/bitops.h>
13 #include <clk-uclass.h>
15 #include <asm/arch/sys_proto.h>
17 #include <linux/err.h>
19 static const resource_size_t zynqmp_crf_apb_clkc_base = 0xfd1a0020;
20 static const resource_size_t zynqmp_crl_apb_clkc_base = 0xff5e0020;
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)
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)
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)
113 #define NUM_MIO_PINS 77
118 iopll_to_fpd, rpll_to_fpd, apll_to_lpd, dpll_to_lpd, vpll_to_lpd,
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,
127 lpd_switch, lpd_lsbus,
128 usb0_bus_ref, usb1_bus_ref, usb3_dual_ref, usb0, usb1,
130 csu_spb, csu_pll, pcap,
132 gem_tsu_ref, gem_tsu,
133 gem0_tx, gem1_tx, gem2_tx, gem3_tx,
134 gem0_rx, gem1_rx, gem2_rx, gem3_rx,
136 sdio0_ref, sdio1_ref,
137 uart0_ref, uart1_ref,
140 i2c0_ref, i2c1_ref, can0_ref, can1_ref, can0, can1,
148 gem1_ref, gem2_ref, gem3_ref,
152 static const char * const clk_names[clk_max] = {
153 "iopll", "rpll", "apll", "dpll",
154 "vpll", "iopll_to_fpd", "rpll_to_fpd",
155 "apll_to_lpd", "dpll_to_lpd", "vpll_to_lpd",
156 "acpu", "acpu_half", "dbg_fpd", "dbg_lpd",
157 "dbg_trace", "dbg_tstmp", "dp_video_ref",
158 "dp_audio_ref", "dp_stc_ref", "gdma_ref",
159 "dpdma_ref", "ddr_ref", "sata_ref", "pcie_ref",
160 "gpu_ref", "gpu_pp0_ref", "gpu_pp1_ref",
161 "topsw_main", "topsw_lsbus", "gtgref0_ref",
162 "lpd_switch", "lpd_lsbus", "usb0_bus_ref",
163 "usb1_bus_ref", "usb3_dual_ref", "usb0",
164 "usb1", "cpu_r5", "cpu_r5_core", "csu_spb",
165 "csu_pll", "pcap", "iou_switch", "gem_tsu_ref",
166 "gem_tsu", "gem0_tx", "gem1_tx", "gem2_tx",
167 "gem3_tx", "gem0_rx", "gem1_rx", "gem2_rx",
168 "gem3_rx", "qspi_ref", "sdio0_ref", "sdio1_ref",
169 "uart0_ref", "uart1_ref", "spi0_ref",
170 "spi1_ref", "nand_ref", "i2c0_ref", "i2c1_ref",
171 "can0_ref", "can1_ref", "can0", "can1",
172 "dll_ref", "adma_ref", "timestamp_ref",
173 "ams_ref", "pl0", "pl1", "pl2", "pl3", "wdt",
174 NULL, NULL, NULL, NULL,
175 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
176 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
177 NULL, NULL, NULL, NULL, "gem0_ref", "gem1_ref", "gem2_ref", "gem3_ref",
180 static const u32 pll_src[][4] = {
181 {apll, 0xff, dpll, vpll}, /* acpu */
182 {dpll, vpll, 0xff, 0xff}, /* ddr_ref */
183 {rpll, iopll, 0xff, 0xff}, /* dll_ref */
184 {iopll, 0xff, rpll, dpll_to_lpd}, /* gem_tsu_ref */
185 {iopll, 0xff, rpll, dpll}, /* peripheral */
186 {apll, 0xff, iopll_to_fpd, dpll}, /* wdt */
187 {iopll_to_fpd, 0xff, dpll, apll}, /* dbg_fpd */
188 {iopll, 0xff, rpll, dpll_to_lpd}, /* timestamp_ref */
189 {iopll_to_fpd, 0xff, apll, dpll}, /* sata_ref */
190 {iopll_to_fpd, 0xff, rpll_to_fpd, dpll},/* pcie_ref */
191 {iopll_to_fpd, 0xff, vpll, dpll}, /* gpu_ref */
192 {apll, 0xff, vpll, dpll}, /* topsw_main_ref */
193 {rpll, 0xff, iopll, dpll_to_lpd}, /* cpu_r5_ref */
196 enum zynqmp_clk_pll_src {
212 struct zynqmp_clk_priv {
213 unsigned long ps_clk_freq;
214 unsigned long video_clk;
215 unsigned long pss_alt_ref_clk;
216 unsigned long gt_crx_ref_clk;
217 unsigned long aux_ref_clk;
220 static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
224 return CRL_APB_IOPLL_CTRL;
226 return CRL_APB_RPLL_CTRL;
228 return CRF_APB_APLL_CTRL;
230 return CRF_APB_DPLL_CTRL;
232 return CRF_APB_VPLL_CTRL;
234 return CRF_APB_ACPU_CTRL;
236 return CRF_APB_DBG_FPD_CTRL;
238 return CRF_APB_DBG_TRACE_CTRL;
240 return CRF_APB_DBG_TSTMP_CTRL;
242 return CRF_APB_DP_VIDEO_REF_CTRL;
244 return CRF_APB_DP_AUDIO_REF_CTRL;
246 return CRF_APB_DP_STC_REF_CTRL;
247 case gpu_ref ... gpu_pp1_ref:
248 return CRF_APB_GPU_REF_CTRL;
250 return CRF_APB_DDR_CTRL;
252 return CRF_APB_SATA_REF_CTRL;
254 return CRF_APB_PCIE_REF_CTRL;
256 return CRF_APB_GDMA_REF_CTRL;
258 return CRF_APB_DPDMA_REF_CTRL;
260 return CRF_APB_TOPSW_MAIN_CTRL;
262 return CRF_APB_TOPSW_LSBUS_CTRL;
264 return CRL_APB_LPD_SWITCH_CTRL;
266 return CRL_APB_LPD_LSBUS_CTRL;
268 return CRL_APB_QSPI_REF_CTRL;
270 return CRL_APB_USB3_DUAL_REF_CTRL;
272 return CRL_APB_GEM_TSU_REF_CTRL;
275 return CRL_APB_GEM0_REF_CTRL;
278 return CRL_APB_GEM1_REF_CTRL;
281 return CRL_APB_GEM2_REF_CTRL;
284 return CRL_APB_GEM3_REF_CTRL;
286 return CRL_APB_USB0_BUS_REF_CTRL;
288 return CRL_APB_USB1_BUS_REF_CTRL;
290 return CRL_APB_CPU_R5_CTRL;
292 return CRL_APB_UART0_REF_CTRL;
294 return CRL_APB_UART1_REF_CTRL;
296 return CRL_APB_SDIO0_REF_CTRL;
298 return CRL_APB_SDIO1_REF_CTRL;
300 return CRL_APB_SPI0_REF_CTRL;
302 return CRL_APB_SPI1_REF_CTRL;
304 return CRL_APB_NAND_REF_CTRL;
306 return CRL_APB_I2C0_REF_CTRL;
308 return CRL_APB_I2C1_REF_CTRL;
310 return CRL_APB_CAN0_REF_CTRL;
312 return CRL_APB_CAN1_REF_CTRL;
314 return CRL_APB_DLL_REF_CTRL;
316 return CRL_APB_ADMA_REF_CTRL;
318 return CRL_APB_TIMESTAMP_REF_CTRL;
320 return CRL_APB_AMS_REF_CTRL;
322 return CRL_APB_PL0_REF_CTRL;
324 return CRL_APB_PL1_REF_CTRL;
326 return CRL_APB_PL2_REF_CTRL;
328 return CRL_APB_PL3_REF_CTRL;
330 return CRF_APB_TOPSW_LSBUS_CTRL;
332 return CRL_APB_IOPLL_TO_FPD_CTRL;
334 debug("Invalid clk id%d\n", id);
339 static ulong zynqmp_clk_get_pll_src(ulong clk_ctrl,
340 struct zynqmp_clk_priv *priv,
346 src_sel = (clk_ctrl & PLLCTRL_PRE_SRC_MASK) >>
347 PLLCTRL_PRE_SRC_SHFT;
349 src_sel = (clk_ctrl & PLLCTRL_POST_SRC_MASK) >>
350 PLLCTRL_POST_SRC_SHFT;
354 return priv->video_clk;
356 return priv->pss_alt_ref_clk;
358 return priv->aux_ref_clk;
360 return priv->gt_crx_ref_clk;
363 return priv->ps_clk_freq;
367 static ulong zynqmp_clk_get_pll_rate(struct zynqmp_clk_priv *priv,
370 u32 clk_ctrl, reset, mul;
374 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
376 printf("%s mio read fail\n", __func__);
380 if (clk_ctrl & PLLCTRL_BYPASS_MASK)
381 freq = zynqmp_clk_get_pll_src(clk_ctrl, priv, 0);
383 freq = zynqmp_clk_get_pll_src(clk_ctrl, priv, 1);
385 reset = (clk_ctrl & PLLCTRL_RESET_MASK) >> PLLCTRL_RESET_SHIFT;
386 if (reset && !(clk_ctrl & PLLCTRL_BYPASS_MASK))
389 mul = (clk_ctrl & PLLCTRL_FBDIV_MASK) >> PLLCTRL_FBDIV_SHIFT;
393 if (clk_ctrl & (1 << 16))
399 static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
402 u32 clk_ctrl, div, srcsel;
405 unsigned long pllrate;
407 ret = zynqmp_mmio_read(CRF_APB_ACPU_CTRL, &clk_ctrl);
409 printf("%s mio read fail\n", __func__);
413 div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
415 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
416 pll = pll_src[ACPU_CLK_SRC][srcsel];
417 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
418 if (IS_ERR_VALUE(pllrate))
421 return DIV_ROUND_CLOSEST(pllrate, div);
424 static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
426 u32 clk_ctrl, div, srcsel;
431 ret = zynqmp_mmio_read(CRF_APB_DDR_CTRL, &clk_ctrl);
433 printf("%s mio read fail\n", __func__);
437 div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
439 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
440 pll = pll_src[DDR_CLK_SRC][srcsel];
441 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
442 if (IS_ERR_VALUE(pllrate))
445 return DIV_ROUND_CLOSEST(pllrate, div);
448 static ulong zynqmp_clk_get_dll_rate(struct zynqmp_clk_priv *priv)
450 u32 clk_ctrl, srcsel;
455 ret = zynqmp_mmio_read(CRL_APB_DLL_REF_CTRL, &clk_ctrl);
457 printf("%s mio read fail\n", __func__);
461 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
462 pll = pll_src[DLL_CLK_SRC][srcsel];
463 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
464 if (IS_ERR_VALUE(pllrate))
470 static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv,
471 enum zynqmp_clk id, bool two_divs)
474 u32 clk_ctrl, div0, srcsel;
479 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
481 printf("%s mio read fail\n", __func__);
485 div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
490 div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
494 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
496 if (id == gem_tsu_ref)
497 pll = pll_src[GEM_TSU_CLK_SRC][srcsel];
499 pll = pll_src[PERI_CLK_SRC][srcsel];
501 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
502 if (IS_ERR_VALUE(pllrate))
507 DIV_ROUND_CLOSEST(pllrate, div0), div1);
510 static ulong zynqmp_clk_get_crf_crl_rate(struct zynqmp_clk_priv *priv,
511 enum zynqmp_clk id, bool two_divs)
514 u32 clk_ctrl, div0, srcsel;
519 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
521 printf("%d %s mio read fail\n", __LINE__, __func__);
525 div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
528 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
534 pll = pll_src[WDT_CLK_SRC][srcsel];
538 pll = pll_src[DBG_FPD_CLK_SRC][srcsel];
541 pll = pll_src[TIMESTAMP_CLK_SRC][srcsel];
544 pll = pll_src[SATA_CLK_SRC][srcsel];
547 pll = pll_src[PCIE_CLK_SRC][srcsel];
549 case gpu_ref ... gpu_pp1_ref:
550 pll = pll_src[GPU_CLK_SRC][srcsel];
555 pll = pll_src[TOPSW_MAIN_CLK_SRC][srcsel];
562 pll = pll_src[CPU_R5_CLK_SRC][srcsel];
568 ret = zynqmp_mmio_read(zynqmp_clk_get_register(pll), &clk_ctrl);
570 printf("%d %s mio read fail\n", __LINE__, __func__);
573 div1 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
578 if (pll == iopll_to_fpd)
581 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
582 if (IS_ERR_VALUE(pllrate))
587 DIV_ROUND_CLOSEST(pllrate, div0), div1);
590 static unsigned long zynqmp_clk_calc_peripheral_two_divs(ulong rate,
592 u32 *div0, u32 *div1)
594 long new_err, best_err = (long)(~0UL >> 1);
595 ulong new_rate, best_rate = 0;
598 for (d0 = 1; d0 <= ZYNQ_CLK_MAXDIV; d0++) {
599 for (d1 = 1; d1 <= ZYNQ_CLK_MAXDIV >> 1; d1++) {
600 new_rate = DIV_ROUND_CLOSEST(
601 DIV_ROUND_CLOSEST(pll_rate, d0), d1);
602 new_err = abs(new_rate - rate);
604 if (new_err < best_err) {
608 best_rate = new_rate;
616 static ulong zynqmp_clk_set_peripheral_rate(struct zynqmp_clk_priv *priv,
617 enum zynqmp_clk id, ulong rate,
621 u32 clk_ctrl, div0 = 0, div1 = 0;
622 ulong pll_rate, new_rate;
627 reg = zynqmp_clk_get_register(id);
628 ret = zynqmp_mmio_read(reg, &clk_ctrl);
630 printf("%s mio read fail\n", __func__);
634 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
635 pll = pll_src[PERI_CLK_SRC][srcsel];
636 pll_rate = zynqmp_clk_get_pll_rate(priv, pll);
637 if (IS_ERR_VALUE(pll_rate))
640 clk_ctrl &= ~CLK_CTRL_DIV0_MASK;
642 clk_ctrl &= ~CLK_CTRL_DIV1_MASK;
643 new_rate = zynqmp_clk_calc_peripheral_two_divs(rate, pll_rate,
645 clk_ctrl |= div1 << CLK_CTRL_DIV1_SHIFT;
647 div0 = DIV_ROUND_CLOSEST(pll_rate, rate);
648 if (div0 > ZYNQ_CLK_MAXDIV)
649 div0 = ZYNQ_CLK_MAXDIV;
650 new_rate = DIV_ROUND_CLOSEST(rate, div0);
652 clk_ctrl |= div0 << CLK_CTRL_DIV0_SHIFT;
654 mask = (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT) |
655 (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT);
657 ret = zynqmp_mmio_write(reg, mask, clk_ctrl);
659 printf("%s mio write fail\n", __func__);
666 static ulong zynqmp_clk_get_rate(struct clk *clk)
668 struct zynqmp_clk_priv *priv = dev_get_priv(clk->dev);
669 enum zynqmp_clk id = clk->id;
670 bool two_divs = false;
674 return zynqmp_clk_get_pll_rate(priv, id);
676 return zynqmp_clk_get_cpu_rate(priv, id);
678 return zynqmp_clk_get_ddr_rate(priv);
680 return zynqmp_clk_get_dll_rate(priv);
682 case dp_video_ref ... dp_stc_ref:
684 case gem0_ref ... gem3_ref:
685 case gem0_tx ... gem3_tx:
686 case qspi_ref ... can1_ref:
687 case usb0_bus_ref ... usb3_dual_ref:
689 return zynqmp_clk_get_peripheral_rate(priv, id, two_divs);
692 case sata_ref ... gpu_pp1_ref:
704 case gdma_ref ... dpdma_ref:
705 return zynqmp_clk_get_crf_crl_rate(priv, id, two_divs);
711 static ulong zynqmp_clk_set_rate(struct clk *clk, ulong rate)
713 struct zynqmp_clk_priv *priv = dev_get_priv(clk->dev);
714 enum zynqmp_clk id = clk->id;
715 bool two_divs = true;
718 case gem0_ref ... gem3_ref:
719 case gem0_tx ... gem3_tx:
720 case qspi_ref ... can1_ref:
721 case usb0_bus_ref ... usb3_dual_ref:
722 return zynqmp_clk_set_peripheral_rate(priv, id,
729 int soc_clk_dump(void)
734 ret = uclass_get_device_by_driver(UCLASS_CLK,
735 DM_DRIVER_GET(zynqmp_clk), &dev);
739 printf("clk\t\tfrequency\n");
740 for (i = 0; i < clk_max; i++) {
741 const char *name = clk_names[i];
747 ret = clk_request(dev, &clk);
751 rate = clk_get_rate(&clk);
755 if ((rate == (unsigned long)-ENOSYS) ||
756 (rate == (unsigned long)-ENXIO) ||
757 (rate == (unsigned long)-EIO))
758 printf("%10s%20s\n", name, "unknown");
760 printf("%10s%20lu\n", name, rate);
767 static int zynqmp_get_freq_by_name(char *name, struct udevice *dev, ulong *freq)
772 ret = clk_get_by_name(dev, name, &clk);
774 dev_err(dev, "failed to get %s\n", name);
778 *freq = clk_get_rate(&clk);
779 if (IS_ERR_VALUE(*freq)) {
780 dev_err(dev, "failed to get rate %s\n", name);
786 static int zynqmp_clk_probe(struct udevice *dev)
789 struct zynqmp_clk_priv *priv = dev_get_priv(dev);
791 debug("%s\n", __func__);
792 ret = zynqmp_get_freq_by_name("pss_ref_clk", dev, &priv->ps_clk_freq);
796 ret = zynqmp_get_freq_by_name("video_clk", dev, &priv->video_clk);
800 ret = zynqmp_get_freq_by_name("pss_alt_ref_clk", dev,
801 &priv->pss_alt_ref_clk);
805 ret = zynqmp_get_freq_by_name("aux_ref_clk", dev, &priv->aux_ref_clk);
809 ret = zynqmp_get_freq_by_name("gt_crx_ref_clk", dev,
810 &priv->gt_crx_ref_clk);
817 static int zynqmp_clk_enable(struct clk *clk)
819 enum zynqmp_clk id = clk->id;
820 u32 reg, clk_ctrl, clkact_shift, mask;
823 reg = zynqmp_clk_get_register(id);
824 debug("%s, clk_id:%x, clk_base:0x%x\n", __func__, id, reg);
827 case usb0_bus_ref ... usb1:
831 case gem0_tx ... gem3_tx:
832 case gem0_ref ... gem3_ref:
836 case qspi_ref ... can1_ref:
845 ret = zynqmp_mmio_read(reg, &clk_ctrl);
847 printf("%s mio read fail\n", __func__);
851 clk_ctrl |= (mask << clkact_shift);
852 ret = zynqmp_mmio_write(reg, mask << clkact_shift, clk_ctrl);
854 printf("%s mio write fail\n", __func__);
861 static struct clk_ops zynqmp_clk_ops = {
862 .set_rate = zynqmp_clk_set_rate,
863 .get_rate = zynqmp_clk_get_rate,
864 .enable = zynqmp_clk_enable,
867 static const struct udevice_id zynqmp_clk_ids[] = {
868 { .compatible = "xlnx,zynqmp-clk" },
872 U_BOOT_DRIVER(zynqmp_clk) = {
873 .name = "zynqmp_clk",
875 .of_match = zynqmp_clk_ids,
876 .probe = zynqmp_clk_probe,
877 .ops = &zynqmp_clk_ops,
878 .priv_auto = sizeof(struct zynqmp_clk_priv),