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 <zynqmp_firmware.h>
16 #include <asm/arch/sys_proto.h>
18 #include <linux/err.h>
20 static const resource_size_t zynqmp_crf_apb_clkc_base = 0xfd1a0020;
21 static const resource_size_t zynqmp_crl_apb_clkc_base = 0xff5e0020;
23 /* Full power domain clocks */
24 #define CRF_APB_APLL_CTRL (zynqmp_crf_apb_clkc_base + 0x00)
25 #define CRF_APB_DPLL_CTRL (zynqmp_crf_apb_clkc_base + 0x0c)
26 #define CRF_APB_VPLL_CTRL (zynqmp_crf_apb_clkc_base + 0x18)
27 #define CRF_APB_PLL_STATUS (zynqmp_crf_apb_clkc_base + 0x24)
28 #define CRF_APB_APLL_TO_LPD_CTRL (zynqmp_crf_apb_clkc_base + 0x28)
29 #define CRF_APB_DPLL_TO_LPD_CTRL (zynqmp_crf_apb_clkc_base + 0x2c)
30 #define CRF_APB_VPLL_TO_LPD_CTRL (zynqmp_crf_apb_clkc_base + 0x30)
31 /* Peripheral clocks */
32 #define CRF_APB_ACPU_CTRL (zynqmp_crf_apb_clkc_base + 0x40)
33 #define CRF_APB_DBG_TRACE_CTRL (zynqmp_crf_apb_clkc_base + 0x44)
34 #define CRF_APB_DBG_FPD_CTRL (zynqmp_crf_apb_clkc_base + 0x48)
35 #define CRF_APB_DP_VIDEO_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x50)
36 #define CRF_APB_DP_AUDIO_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x54)
37 #define CRF_APB_DP_STC_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x5c)
38 #define CRF_APB_DDR_CTRL (zynqmp_crf_apb_clkc_base + 0x60)
39 #define CRF_APB_GPU_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x64)
40 #define CRF_APB_SATA_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x80)
41 #define CRF_APB_PCIE_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x94)
42 #define CRF_APB_GDMA_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x98)
43 #define CRF_APB_DPDMA_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x9c)
44 #define CRF_APB_TOPSW_MAIN_CTRL (zynqmp_crf_apb_clkc_base + 0xa0)
45 #define CRF_APB_TOPSW_LSBUS_CTRL (zynqmp_crf_apb_clkc_base + 0xa4)
46 #define CRF_APB_GTGREF0_REF_CTRL (zynqmp_crf_apb_clkc_base + 0xa8)
47 #define CRF_APB_DBG_TSTMP_CTRL (zynqmp_crf_apb_clkc_base + 0xd8)
49 /* Low power domain clocks */
50 #define CRL_APB_IOPLL_CTRL (zynqmp_crl_apb_clkc_base + 0x00)
51 #define CRL_APB_RPLL_CTRL (zynqmp_crl_apb_clkc_base + 0x10)
52 #define CRL_APB_PLL_STATUS (zynqmp_crl_apb_clkc_base + 0x20)
53 #define CRL_APB_IOPLL_TO_FPD_CTRL (zynqmp_crl_apb_clkc_base + 0x24)
54 #define CRL_APB_RPLL_TO_FPD_CTRL (zynqmp_crl_apb_clkc_base + 0x28)
55 /* Peripheral clocks */
56 #define CRL_APB_USB3_DUAL_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x2c)
57 #define CRL_APB_GEM0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x30)
58 #define CRL_APB_GEM1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x34)
59 #define CRL_APB_GEM2_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x38)
60 #define CRL_APB_GEM3_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x3c)
61 #define CRL_APB_USB0_BUS_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x40)
62 #define CRL_APB_USB1_BUS_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x44)
63 #define CRL_APB_QSPI_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x48)
64 #define CRL_APB_SDIO0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x4c)
65 #define CRL_APB_SDIO1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x50)
66 #define CRL_APB_UART0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x54)
67 #define CRL_APB_UART1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x58)
68 #define CRL_APB_SPI0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x5c)
69 #define CRL_APB_SPI1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x60)
70 #define CRL_APB_CAN0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x64)
71 #define CRL_APB_CAN1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x68)
72 #define CRL_APB_CPU_R5_CTRL (zynqmp_crl_apb_clkc_base + 0x70)
73 #define CRL_APB_IOU_SWITCH_CTRL (zynqmp_crl_apb_clkc_base + 0x7c)
74 #define CRL_APB_CSU_PLL_CTRL (zynqmp_crl_apb_clkc_base + 0x80)
75 #define CRL_APB_PCAP_CTRL (zynqmp_crl_apb_clkc_base + 0x84)
76 #define CRL_APB_LPD_SWITCH_CTRL (zynqmp_crl_apb_clkc_base + 0x88)
77 #define CRL_APB_LPD_LSBUS_CTRL (zynqmp_crl_apb_clkc_base + 0x8c)
78 #define CRL_APB_DBG_LPD_CTRL (zynqmp_crl_apb_clkc_base + 0x90)
79 #define CRL_APB_NAND_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x94)
80 #define CRL_APB_ADMA_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x98)
81 #define CRL_APB_PL0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xa0)
82 #define CRL_APB_PL1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xa4)
83 #define CRL_APB_PL2_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xa8)
84 #define CRL_APB_PL3_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xac)
85 #define CRL_APB_PL0_THR_CNT (zynqmp_crl_apb_clkc_base + 0xb4)
86 #define CRL_APB_PL1_THR_CNT (zynqmp_crl_apb_clkc_base + 0xbc)
87 #define CRL_APB_PL2_THR_CNT (zynqmp_crl_apb_clkc_base + 0xc4)
88 #define CRL_APB_PL3_THR_CNT (zynqmp_crl_apb_clkc_base + 0xdc)
89 #define CRL_APB_GEM_TSU_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xe0)
90 #define CRL_APB_DLL_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xe4)
91 #define CRL_APB_AMS_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xe8)
92 #define CRL_APB_I2C0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x100)
93 #define CRL_APB_I2C1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x104)
94 #define CRL_APB_TIMESTAMP_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x108)
96 #define ZYNQ_CLK_MAXDIV 0x3f
97 #define CLK_CTRL_DIV1_SHIFT 16
98 #define CLK_CTRL_DIV1_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT)
99 #define CLK_CTRL_DIV0_SHIFT 8
100 #define CLK_CTRL_DIV0_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT)
101 #define CLK_CTRL_SRCSEL_MASK 0x7
102 #define PLLCTRL_FBDIV_MASK 0x7f00
103 #define PLLCTRL_FBDIV_SHIFT 8
104 #define PLLCTRL_RESET_MASK 1
105 #define PLLCTRL_RESET_SHIFT 0
106 #define PLLCTRL_BYPASS_MASK 0x8
107 #define PLLCTRL_BYPASS_SHFT 3
108 #define PLLCTRL_POST_SRC_SHFT 24
109 #define PLLCTRL_POST_SRC_MASK (0x7 << PLLCTRL_POST_SRC_SHFT)
110 #define PLLCTRL_PRE_SRC_SHFT 20
111 #define PLLCTRL_PRE_SRC_MASK (0x7 << PLLCTRL_PRE_SRC_SHFT)
114 #define NUM_MIO_PINS 77
119 iopll_to_fpd, rpll_to_fpd, apll_to_lpd, dpll_to_lpd, vpll_to_lpd,
121 dbg_fpd, dbg_lpd, dbg_trace, dbg_tstmp,
122 dp_video_ref, dp_audio_ref,
123 dp_stc_ref, gdma_ref, dpdma_ref,
124 ddr_ref, sata_ref, pcie_ref,
125 gpu_ref, gpu_pp0_ref, gpu_pp1_ref,
126 topsw_main, topsw_lsbus,
128 lpd_switch, lpd_lsbus,
129 usb0_bus_ref, usb1_bus_ref, usb3_dual_ref, usb0, usb1,
131 csu_spb, csu_pll, pcap,
133 gem_tsu_ref, gem_tsu,
134 gem0_tx, gem1_tx, gem2_tx, gem3_tx,
135 gem0_rx, gem1_rx, gem2_rx, gem3_rx,
137 sdio0_ref, sdio1_ref,
138 uart0_ref, uart1_ref,
141 i2c0_ref, i2c1_ref, can0_ref, can1_ref, can0, can1,
149 gem1_ref, gem2_ref, gem3_ref,
153 static const char * const clk_names[clk_max] = {
154 "iopll", "rpll", "apll", "dpll",
155 "vpll", "iopll_to_fpd", "rpll_to_fpd",
156 "apll_to_lpd", "dpll_to_lpd", "vpll_to_lpd",
157 "acpu", "acpu_half", "dbg_fpd", "dbg_lpd",
158 "dbg_trace", "dbg_tstmp", "dp_video_ref",
159 "dp_audio_ref", "dp_stc_ref", "gdma_ref",
160 "dpdma_ref", "ddr_ref", "sata_ref", "pcie_ref",
161 "gpu_ref", "gpu_pp0_ref", "gpu_pp1_ref",
162 "topsw_main", "topsw_lsbus", "gtgref0_ref",
163 "lpd_switch", "lpd_lsbus", "usb0_bus_ref",
164 "usb1_bus_ref", "usb3_dual_ref", "usb0",
165 "usb1", "cpu_r5", "cpu_r5_core", "csu_spb",
166 "csu_pll", "pcap", "iou_switch", "gem_tsu_ref",
167 "gem_tsu", "gem0_tx", "gem1_tx", "gem2_tx",
168 "gem3_tx", "gem0_rx", "gem1_rx", "gem2_rx",
169 "gem3_rx", "qspi_ref", "sdio0_ref", "sdio1_ref",
170 "uart0_ref", "uart1_ref", "spi0_ref",
171 "spi1_ref", "nand_ref", "i2c0_ref", "i2c1_ref",
172 "can0_ref", "can1_ref", "can0", "can1",
173 "dll_ref", "adma_ref", "timestamp_ref",
174 "ams_ref", "pl0", "pl1", "pl2", "pl3", "wdt",
175 NULL, NULL, NULL, NULL,
176 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
177 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
178 NULL, NULL, NULL, NULL, "gem0_ref", "gem1_ref", "gem2_ref", "gem3_ref",
181 static const u32 pll_src[][4] = {
182 {apll, 0xff, dpll, vpll}, /* acpu */
183 {dpll, vpll, 0xff, 0xff}, /* ddr_ref */
184 {rpll, iopll, 0xff, 0xff}, /* dll_ref */
185 {iopll, 0xff, rpll, dpll_to_lpd}, /* gem_tsu_ref */
186 {iopll, 0xff, rpll, dpll}, /* peripheral */
187 {apll, 0xff, iopll_to_fpd, dpll}, /* wdt */
188 {iopll_to_fpd, 0xff, dpll, apll}, /* dbg_fpd */
189 {iopll, 0xff, rpll, dpll_to_lpd}, /* timestamp_ref */
190 {iopll_to_fpd, 0xff, apll, dpll}, /* sata_ref */
191 {iopll_to_fpd, 0xff, rpll_to_fpd, dpll},/* pcie_ref */
192 {iopll_to_fpd, 0xff, vpll, dpll}, /* gpu_ref */
193 {apll, 0xff, vpll, dpll}, /* topsw_main_ref */
194 {rpll, 0xff, iopll, dpll_to_lpd}, /* cpu_r5_ref */
197 enum zynqmp_clk_pll_src {
213 struct zynqmp_clk_priv {
214 unsigned long ps_clk_freq;
215 unsigned long video_clk;
216 unsigned long pss_alt_ref_clk;
217 unsigned long gt_crx_ref_clk;
218 unsigned long aux_ref_clk;
221 static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
225 return CRL_APB_IOPLL_CTRL;
227 return CRL_APB_RPLL_CTRL;
229 return CRF_APB_APLL_CTRL;
231 return CRF_APB_DPLL_CTRL;
233 return CRF_APB_VPLL_CTRL;
235 return CRF_APB_ACPU_CTRL;
237 return CRF_APB_DBG_FPD_CTRL;
239 return CRF_APB_DBG_TRACE_CTRL;
241 return CRF_APB_DBG_TSTMP_CTRL;
243 return CRF_APB_DP_VIDEO_REF_CTRL;
245 return CRF_APB_DP_AUDIO_REF_CTRL;
247 return CRF_APB_DP_STC_REF_CTRL;
248 case gpu_ref ... gpu_pp1_ref:
249 return CRF_APB_GPU_REF_CTRL;
251 return CRF_APB_DDR_CTRL;
253 return CRF_APB_SATA_REF_CTRL;
255 return CRF_APB_PCIE_REF_CTRL;
257 return CRF_APB_GDMA_REF_CTRL;
259 return CRF_APB_DPDMA_REF_CTRL;
261 return CRF_APB_TOPSW_MAIN_CTRL;
263 return CRF_APB_TOPSW_LSBUS_CTRL;
265 return CRL_APB_LPD_SWITCH_CTRL;
267 return CRL_APB_LPD_LSBUS_CTRL;
269 return CRL_APB_QSPI_REF_CTRL;
271 return CRL_APB_USB3_DUAL_REF_CTRL;
274 return CRL_APB_GEM_TSU_REF_CTRL;
278 return CRL_APB_GEM0_REF_CTRL;
282 return CRL_APB_GEM1_REF_CTRL;
286 return CRL_APB_GEM2_REF_CTRL;
290 return CRL_APB_GEM3_REF_CTRL;
292 return CRL_APB_USB0_BUS_REF_CTRL;
294 return CRL_APB_USB1_BUS_REF_CTRL;
296 return CRL_APB_CPU_R5_CTRL;
298 return CRL_APB_UART0_REF_CTRL;
300 return CRL_APB_UART1_REF_CTRL;
302 return CRL_APB_SDIO0_REF_CTRL;
304 return CRL_APB_SDIO1_REF_CTRL;
306 return CRL_APB_SPI0_REF_CTRL;
308 return CRL_APB_SPI1_REF_CTRL;
310 return CRL_APB_NAND_REF_CTRL;
312 return CRL_APB_I2C0_REF_CTRL;
314 return CRL_APB_I2C1_REF_CTRL;
316 return CRL_APB_CAN0_REF_CTRL;
318 return CRL_APB_CAN1_REF_CTRL;
320 return CRL_APB_DLL_REF_CTRL;
322 return CRL_APB_ADMA_REF_CTRL;
324 return CRL_APB_TIMESTAMP_REF_CTRL;
326 return CRL_APB_AMS_REF_CTRL;
328 return CRL_APB_PL0_REF_CTRL;
330 return CRL_APB_PL1_REF_CTRL;
332 return CRL_APB_PL2_REF_CTRL;
334 return CRL_APB_PL3_REF_CTRL;
336 return CRF_APB_TOPSW_LSBUS_CTRL;
338 return CRL_APB_IOPLL_TO_FPD_CTRL;
340 debug("Invalid clk id%d\n", id);
345 static ulong zynqmp_clk_get_pll_src(ulong clk_ctrl,
346 struct zynqmp_clk_priv *priv,
352 src_sel = (clk_ctrl & PLLCTRL_PRE_SRC_MASK) >>
353 PLLCTRL_PRE_SRC_SHFT;
355 src_sel = (clk_ctrl & PLLCTRL_POST_SRC_MASK) >>
356 PLLCTRL_POST_SRC_SHFT;
360 return priv->video_clk;
362 return priv->pss_alt_ref_clk;
364 return priv->aux_ref_clk;
366 return priv->gt_crx_ref_clk;
369 return priv->ps_clk_freq;
373 static ulong zynqmp_clk_get_pll_rate(struct zynqmp_clk_priv *priv,
376 u32 clk_ctrl, reset, mul;
380 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
382 printf("%s mio read fail\n", __func__);
386 if (clk_ctrl & PLLCTRL_BYPASS_MASK)
387 freq = zynqmp_clk_get_pll_src(clk_ctrl, priv, 0);
389 freq = zynqmp_clk_get_pll_src(clk_ctrl, priv, 1);
391 reset = (clk_ctrl & PLLCTRL_RESET_MASK) >> PLLCTRL_RESET_SHIFT;
392 if (reset && !(clk_ctrl & PLLCTRL_BYPASS_MASK))
395 mul = (clk_ctrl & PLLCTRL_FBDIV_MASK) >> PLLCTRL_FBDIV_SHIFT;
399 if (clk_ctrl & (1 << 16))
405 static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
408 u32 clk_ctrl, div, srcsel;
411 unsigned long pllrate;
413 ret = zynqmp_mmio_read(CRF_APB_ACPU_CTRL, &clk_ctrl);
415 printf("%s mio read fail\n", __func__);
419 div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
421 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
422 pll = pll_src[ACPU_CLK_SRC][srcsel];
423 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
424 if (IS_ERR_VALUE(pllrate))
427 return DIV_ROUND_CLOSEST(pllrate, div);
430 static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
432 u32 clk_ctrl, div, srcsel;
437 ret = zynqmp_mmio_read(CRF_APB_DDR_CTRL, &clk_ctrl);
439 printf("%s mio read fail\n", __func__);
443 div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
445 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
446 pll = pll_src[DDR_CLK_SRC][srcsel];
447 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
448 if (IS_ERR_VALUE(pllrate))
451 return DIV_ROUND_CLOSEST(pllrate, div);
454 static ulong zynqmp_clk_get_dll_rate(struct zynqmp_clk_priv *priv)
456 u32 clk_ctrl, srcsel;
461 ret = zynqmp_mmio_read(CRL_APB_DLL_REF_CTRL, &clk_ctrl);
463 printf("%s mio read fail\n", __func__);
467 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
468 pll = pll_src[DLL_CLK_SRC][srcsel];
469 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
470 if (IS_ERR_VALUE(pllrate))
476 static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv,
477 enum zynqmp_clk id, bool two_divs)
480 u32 clk_ctrl, div0, srcsel;
485 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
487 printf("%s mio read fail\n", __func__);
491 div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
496 div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
500 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
502 if (id == gem_tsu_ref)
503 pll = pll_src[GEM_TSU_CLK_SRC][srcsel];
505 pll = pll_src[PERI_CLK_SRC][srcsel];
507 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
508 if (IS_ERR_VALUE(pllrate))
513 DIV_ROUND_CLOSEST(pllrate, div0), div1);
516 static ulong zynqmp_clk_get_crf_crl_rate(struct zynqmp_clk_priv *priv,
517 enum zynqmp_clk id, bool two_divs)
520 u32 clk_ctrl, div0, srcsel;
525 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
527 printf("%d %s mio read fail\n", __LINE__, __func__);
531 div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
534 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
540 pll = pll_src[WDT_CLK_SRC][srcsel];
544 pll = pll_src[DBG_FPD_CLK_SRC][srcsel];
547 pll = pll_src[TIMESTAMP_CLK_SRC][srcsel];
550 pll = pll_src[SATA_CLK_SRC][srcsel];
553 pll = pll_src[PCIE_CLK_SRC][srcsel];
555 case gpu_ref ... gpu_pp1_ref:
556 pll = pll_src[GPU_CLK_SRC][srcsel];
561 pll = pll_src[TOPSW_MAIN_CLK_SRC][srcsel];
568 pll = pll_src[CPU_R5_CLK_SRC][srcsel];
574 ret = zynqmp_mmio_read(zynqmp_clk_get_register(pll), &clk_ctrl);
576 printf("%d %s mio read fail\n", __LINE__, __func__);
579 div1 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
584 if (pll == iopll_to_fpd)
587 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
588 if (IS_ERR_VALUE(pllrate))
593 DIV_ROUND_CLOSEST(pllrate, div0), div1);
596 static unsigned long zynqmp_clk_calc_peripheral_two_divs(ulong rate,
598 u32 *div0, u32 *div1)
600 long new_err, best_err = (long)(~0UL >> 1);
601 ulong new_rate, best_rate = 0;
604 for (d0 = 1; d0 <= ZYNQ_CLK_MAXDIV; d0++) {
605 for (d1 = 1; d1 <= ZYNQ_CLK_MAXDIV >> 1; d1++) {
606 new_rate = DIV_ROUND_CLOSEST(
607 DIV_ROUND_CLOSEST(pll_rate, d0), d1);
608 new_err = abs(new_rate - rate);
610 if (new_err < best_err) {
614 best_rate = new_rate;
622 static ulong zynqmp_clk_set_peripheral_rate(struct zynqmp_clk_priv *priv,
623 enum zynqmp_clk id, ulong rate,
627 u32 clk_ctrl, div0 = 0, div1 = 0;
628 ulong pll_rate, new_rate;
633 reg = zynqmp_clk_get_register(id);
634 ret = zynqmp_mmio_read(reg, &clk_ctrl);
636 printf("%s mio read fail\n", __func__);
640 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
641 pll = pll_src[PERI_CLK_SRC][srcsel];
642 pll_rate = zynqmp_clk_get_pll_rate(priv, pll);
643 if (IS_ERR_VALUE(pll_rate))
646 clk_ctrl &= ~CLK_CTRL_DIV0_MASK;
648 clk_ctrl &= ~CLK_CTRL_DIV1_MASK;
649 new_rate = zynqmp_clk_calc_peripheral_two_divs(rate, pll_rate,
651 clk_ctrl |= div1 << CLK_CTRL_DIV1_SHIFT;
653 div0 = DIV_ROUND_CLOSEST(pll_rate, rate);
654 if (div0 > ZYNQ_CLK_MAXDIV)
655 div0 = ZYNQ_CLK_MAXDIV;
656 new_rate = DIV_ROUND_CLOSEST(rate, div0);
658 clk_ctrl |= div0 << CLK_CTRL_DIV0_SHIFT;
660 mask = (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT) |
661 (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT);
663 ret = zynqmp_mmio_write(reg, mask, clk_ctrl);
665 printf("%s mio write fail\n", __func__);
672 static ulong zynqmp_clk_get_rate(struct clk *clk)
674 struct zynqmp_clk_priv *priv = dev_get_priv(clk->dev);
675 enum zynqmp_clk id = clk->id;
676 bool two_divs = false;
680 return zynqmp_clk_get_pll_rate(priv, id);
682 return zynqmp_clk_get_cpu_rate(priv, id);
684 return zynqmp_clk_get_ddr_rate(priv);
686 return zynqmp_clk_get_dll_rate(priv);
688 case dp_video_ref ... dp_stc_ref:
690 case gem0_ref ... gem3_ref:
691 case gem0_tx ... gem3_tx:
692 case qspi_ref ... can1_ref:
693 case usb0_bus_ref ... usb3_dual_ref:
695 return zynqmp_clk_get_peripheral_rate(priv, id, two_divs);
698 case sata_ref ... gpu_pp1_ref:
711 case gdma_ref ... dpdma_ref:
712 return zynqmp_clk_get_crf_crl_rate(priv, id, two_divs);
718 static ulong zynqmp_clk_set_rate(struct clk *clk, ulong rate)
720 struct zynqmp_clk_priv *priv = dev_get_priv(clk->dev);
721 enum zynqmp_clk id = clk->id;
722 bool two_divs = true;
725 case gem0_ref ... gem3_ref:
726 case gem0_tx ... gem3_tx:
727 case gem0_rx ... gem3_rx:
729 case qspi_ref ... can1_ref:
730 case usb0_bus_ref ... usb3_dual_ref:
731 return zynqmp_clk_set_peripheral_rate(priv, id,
738 int soc_clk_dump(void)
743 ret = uclass_get_device_by_driver(UCLASS_CLK,
744 DM_DRIVER_GET(zynqmp_clk), &dev);
748 printf("clk\t\tfrequency\n");
749 for (i = 0; i < clk_max; i++) {
750 const char *name = clk_names[i];
756 ret = clk_request(dev, &clk);
760 rate = clk_get_rate(&clk);
764 if ((rate == (unsigned long)-ENOSYS) ||
765 (rate == (unsigned long)-ENXIO) ||
766 (rate == (unsigned long)-EIO))
767 printf("%10s%20s\n", name, "unknown");
769 printf("%10s%20lu\n", name, rate);
776 static int zynqmp_get_freq_by_name(char *name, struct udevice *dev, ulong *freq)
781 ret = clk_get_by_name(dev, name, &clk);
783 dev_err(dev, "failed to get %s\n", name);
787 *freq = clk_get_rate(&clk);
788 if (IS_ERR_VALUE(*freq)) {
789 dev_err(dev, "failed to get rate %s\n", name);
795 static int zynqmp_clk_probe(struct udevice *dev)
798 struct zynqmp_clk_priv *priv = dev_get_priv(dev);
800 debug("%s\n", __func__);
801 ret = zynqmp_get_freq_by_name("pss_ref_clk", dev, &priv->ps_clk_freq);
805 ret = zynqmp_get_freq_by_name("video_clk", dev, &priv->video_clk);
809 ret = zynqmp_get_freq_by_name("pss_alt_ref_clk", dev,
810 &priv->pss_alt_ref_clk);
814 ret = zynqmp_get_freq_by_name("aux_ref_clk", dev, &priv->aux_ref_clk);
818 ret = zynqmp_get_freq_by_name("gt_crx_ref_clk", dev,
819 &priv->gt_crx_ref_clk);
826 static int zynqmp_clk_enable(struct clk *clk)
828 enum zynqmp_clk id = clk->id;
829 u32 reg, clk_ctrl, clkact_shift, mask;
832 reg = zynqmp_clk_get_register(id);
833 debug("%s, clk_id:%x, clk_base:0x%x\n", __func__, id, reg);
836 case usb0_bus_ref ... usb1:
840 case gem0_tx ... gem3_tx:
841 case gem0_ref ... gem3_ref:
845 case qspi_ref ... can1_ref:
854 ret = zynqmp_mmio_read(reg, &clk_ctrl);
856 printf("%s mio read fail\n", __func__);
860 clk_ctrl |= (mask << clkact_shift);
861 ret = zynqmp_mmio_write(reg, mask << clkact_shift, clk_ctrl);
863 printf("%s mio write fail\n", __func__);
870 static struct clk_ops zynqmp_clk_ops = {
871 .set_rate = zynqmp_clk_set_rate,
872 .get_rate = zynqmp_clk_get_rate,
873 .enable = zynqmp_clk_enable,
876 static const struct udevice_id zynqmp_clk_ids[] = {
877 { .compatible = "xlnx,zynqmp-clk" },
881 U_BOOT_DRIVER(zynqmp_clk) = {
882 .name = "zynqmp_clk",
884 .of_match = zynqmp_clk_ids,
885 .probe = zynqmp_clk_probe,
886 .ops = &zynqmp_clk_ops,
887 .priv_auto = sizeof(struct zynqmp_clk_priv),