1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * ZynqMP clock driver
4 *
5 * Copyright (C) 2016 Xilinx, Inc.
6 */
7
8 #include <log.h>
9 #include <malloc.h>
10 #include <dm/device_compat.h>
11 #include <linux/bitops.h>
12 #include <clk-uclass.h>
13 #include <clk.h>
14 #include <zynqmp_firmware.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 #define PLL_TO_LPD_DIV_SHIFT 8
112 #define PLL_TO_LPD_DIV_MASK (0x3f << PLL_TO_LPD_DIV_SHIFT)
113
114 #define NUM_MIO_PINS 77
115
116 enum zynqmp_clk {
117 iopll, rpll,
118 apll, dpll, vpll,
119 iopll_to_fpd, rpll_to_fpd, apll_to_lpd, dpll_to_lpd, vpll_to_lpd,
120 acpu, acpu_half,
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,
127 gtgref0_ref,
128 lpd_switch, lpd_lsbus,
129 usb0_bus_ref, usb1_bus_ref, usb3_dual_ref, usb0, usb1,
130 cpu_r5, cpu_r5_core,
131 csu_spb, csu_pll, pcap,
132 iou_switch,
133 gem_tsu_ref, gem_tsu,
134 gem0_tx, gem1_tx, gem2_tx, gem3_tx,
135 gem0_rx, gem1_rx, gem2_rx, gem3_rx,
136 qspi_ref,
137 sdio0_ref, sdio1_ref,
138 uart0_ref, uart1_ref,
139 spi0_ref, spi1_ref,
140 nand_ref,
141 i2c0_ref, i2c1_ref, can0_ref, can1_ref, can0, can1,
142 dll_ref,
143 adma_ref,
144 timestamp_ref,
145 ams_ref,
146 pl0, pl1, pl2, pl3,
147 wdt,
148 gem0_ref = 104,
149 gem1_ref, gem2_ref, gem3_ref,
150 clk_max,
151 };
152
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",
179 };
180
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 */
195 };
196
197 enum zynqmp_clk_pll_src {
198 ACPU_CLK_SRC = 0,
199 DDR_CLK_SRC,
200 DLL_CLK_SRC,
201 GEM_TSU_CLK_SRC,
202 PERI_CLK_SRC,
203 WDT_CLK_SRC,
204 DBG_FPD_CLK_SRC,
205 TIMESTAMP_CLK_SRC,
206 SATA_CLK_SRC,
207 PCIE_CLK_SRC,
208 GPU_CLK_SRC,
209 TOPSW_MAIN_CLK_SRC,
210 CPU_R5_CLK_SRC
211 };
212
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;
219 };
220
zynqmp_clk_get_register(enum zynqmp_clk id)221 static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
222 {
223 switch (id) {
224 case iopll:
225 return CRL_APB_IOPLL_CTRL;
226 case rpll:
227 return CRL_APB_RPLL_CTRL;
228 case apll:
229 return CRF_APB_APLL_CTRL;
230 case dpll:
231 return CRF_APB_DPLL_CTRL;
232 case vpll:
233 return CRF_APB_VPLL_CTRL;
234 case acpu:
235 return CRF_APB_ACPU_CTRL;
236 case dbg_fpd:
237 return CRF_APB_DBG_FPD_CTRL;
238 case dbg_trace:
239 return CRF_APB_DBG_TRACE_CTRL;
240 case dbg_tstmp:
241 return CRF_APB_DBG_TSTMP_CTRL;
242 case dp_video_ref:
243 return CRF_APB_DP_VIDEO_REF_CTRL;
244 case dp_audio_ref:
245 return CRF_APB_DP_AUDIO_REF_CTRL;
246 case dp_stc_ref:
247 return CRF_APB_DP_STC_REF_CTRL;
248 case gpu_ref ... gpu_pp1_ref:
249 return CRF_APB_GPU_REF_CTRL;
250 case ddr_ref:
251 return CRF_APB_DDR_CTRL;
252 case sata_ref:
253 return CRF_APB_SATA_REF_CTRL;
254 case pcie_ref:
255 return CRF_APB_PCIE_REF_CTRL;
256 case gdma_ref:
257 return CRF_APB_GDMA_REF_CTRL;
258 case dpdma_ref:
259 return CRF_APB_DPDMA_REF_CTRL;
260 case topsw_main:
261 return CRF_APB_TOPSW_MAIN_CTRL;
262 case topsw_lsbus:
263 return CRF_APB_TOPSW_LSBUS_CTRL;
264 case lpd_switch:
265 return CRL_APB_LPD_SWITCH_CTRL;
266 case lpd_lsbus:
267 return CRL_APB_LPD_LSBUS_CTRL;
268 case qspi_ref:
269 return CRL_APB_QSPI_REF_CTRL;
270 case usb3_dual_ref:
271 return CRL_APB_USB3_DUAL_REF_CTRL;
272 case gem_tsu_ref:
273 case gem_tsu:
274 return CRL_APB_GEM_TSU_REF_CTRL;
275 case gem0_tx:
276 case gem0_rx:
277 case gem0_ref:
278 return CRL_APB_GEM0_REF_CTRL;
279 case gem1_tx:
280 case gem1_rx:
281 case gem1_ref:
282 return CRL_APB_GEM1_REF_CTRL;
283 case gem2_tx:
284 case gem2_rx:
285 case gem2_ref:
286 return CRL_APB_GEM2_REF_CTRL;
287 case gem3_tx:
288 case gem3_rx:
289 case gem3_ref:
290 return CRL_APB_GEM3_REF_CTRL;
291 case usb0_bus_ref:
292 return CRL_APB_USB0_BUS_REF_CTRL;
293 case usb1_bus_ref:
294 return CRL_APB_USB1_BUS_REF_CTRL;
295 case cpu_r5:
296 return CRL_APB_CPU_R5_CTRL;
297 case uart0_ref:
298 return CRL_APB_UART0_REF_CTRL;
299 case uart1_ref:
300 return CRL_APB_UART1_REF_CTRL;
301 case sdio0_ref:
302 return CRL_APB_SDIO0_REF_CTRL;
303 case sdio1_ref:
304 return CRL_APB_SDIO1_REF_CTRL;
305 case spi0_ref:
306 return CRL_APB_SPI0_REF_CTRL;
307 case spi1_ref:
308 return CRL_APB_SPI1_REF_CTRL;
309 case nand_ref:
310 return CRL_APB_NAND_REF_CTRL;
311 case i2c0_ref:
312 return CRL_APB_I2C0_REF_CTRL;
313 case i2c1_ref:
314 return CRL_APB_I2C1_REF_CTRL;
315 case can0_ref:
316 return CRL_APB_CAN0_REF_CTRL;
317 case can1_ref:
318 return CRL_APB_CAN1_REF_CTRL;
319 case dll_ref:
320 return CRL_APB_DLL_REF_CTRL;
321 case adma_ref:
322 return CRL_APB_ADMA_REF_CTRL;
323 case timestamp_ref:
324 return CRL_APB_TIMESTAMP_REF_CTRL;
325 case ams_ref:
326 return CRL_APB_AMS_REF_CTRL;
327 case pl0:
328 return CRL_APB_PL0_REF_CTRL;
329 case pl1:
330 return CRL_APB_PL1_REF_CTRL;
331 case pl2:
332 return CRL_APB_PL2_REF_CTRL;
333 case pl3:
334 return CRL_APB_PL3_REF_CTRL;
335 case wdt:
336 return CRF_APB_TOPSW_LSBUS_CTRL;
337 case iopll_to_fpd:
338 return CRL_APB_IOPLL_TO_FPD_CTRL;
339 case dpll_to_lpd:
340 return CRF_APB_DPLL_TO_LPD_CTRL;
341 default:
342 debug("Invalid clk id%d\n", id);
343 }
344 return 0;
345 }
346
zynqmp_clk_get_pll_src(ulong clk_ctrl,struct zynqmp_clk_priv * priv,bool is_pre_src)347 static ulong zynqmp_clk_get_pll_src(ulong clk_ctrl,
348 struct zynqmp_clk_priv *priv,
349 bool is_pre_src)
350 {
351 u32 src_sel;
352
353 if (is_pre_src)
354 src_sel = (clk_ctrl & PLLCTRL_PRE_SRC_MASK) >>
355 PLLCTRL_PRE_SRC_SHFT;
356 else
357 src_sel = (clk_ctrl & PLLCTRL_POST_SRC_MASK) >>
358 PLLCTRL_POST_SRC_SHFT;
359
360 switch (src_sel) {
361 case 4:
362 return priv->video_clk;
363 case 5:
364 return priv->pss_alt_ref_clk;
365 case 6:
366 return priv->aux_ref_clk;
367 case 7:
368 return priv->gt_crx_ref_clk;
369 case 0 ... 3:
370 default:
371 return priv->ps_clk_freq;
372 }
373 }
374
zynqmp_clk_get_pll_rate(struct zynqmp_clk_priv * priv,enum zynqmp_clk id)375 static ulong zynqmp_clk_get_pll_rate(struct zynqmp_clk_priv *priv,
376 enum zynqmp_clk id)
377 {
378 u32 clk_ctrl, reset, mul;
379 ulong freq;
380 int ret;
381
382 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
383 if (ret) {
384 printf("%s mio read fail\n", __func__);
385 return -EIO;
386 }
387
388 if (clk_ctrl & PLLCTRL_BYPASS_MASK)
389 freq = zynqmp_clk_get_pll_src(clk_ctrl, priv, 0);
390 else
391 freq = zynqmp_clk_get_pll_src(clk_ctrl, priv, 1);
392
393 reset = (clk_ctrl & PLLCTRL_RESET_MASK) >> PLLCTRL_RESET_SHIFT;
394 if (reset && !(clk_ctrl & PLLCTRL_BYPASS_MASK))
395 return 0;
396
397 mul = (clk_ctrl & PLLCTRL_FBDIV_MASK) >> PLLCTRL_FBDIV_SHIFT;
398
399 freq *= mul;
400
401 if (clk_ctrl & (1 << 16))
402 freq /= 2;
403
404 if (id == dpll) {
405 u32 dpll_lpd_reg, cross_div;
406
407 dpll_lpd_reg = zynqmp_clk_get_register(dpll_to_lpd);
408
409 ret = zynqmp_mmio_read(dpll_lpd_reg, &cross_div);
410 if (ret) {
411 printf("%s mio read fail\n", __func__);
412 return -EIO;
413 }
414
415 cross_div = (cross_div & PLL_TO_LPD_DIV_MASK) >>
416 PLL_TO_LPD_DIV_SHIFT;
417 freq /= cross_div;
418 }
419
420 return freq;
421 }
422
zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv * priv,enum zynqmp_clk id)423 static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
424 enum zynqmp_clk id)
425 {
426 u32 clk_ctrl, div, srcsel;
427 enum zynqmp_clk pll;
428 int ret;
429 unsigned long pllrate;
430
431 ret = zynqmp_mmio_read(CRF_APB_ACPU_CTRL, &clk_ctrl);
432 if (ret) {
433 printf("%s mio read fail\n", __func__);
434 return -EIO;
435 }
436
437 div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
438
439 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
440 pll = pll_src[ACPU_CLK_SRC][srcsel];
441 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
442 if (IS_ERR_VALUE(pllrate))
443 return pllrate;
444
445 return DIV_ROUND_CLOSEST(pllrate, div);
446 }
447
zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv * priv)448 static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
449 {
450 u32 clk_ctrl, div, srcsel;
451 enum zynqmp_clk pll;
452 int ret;
453 ulong pllrate;
454
455 ret = zynqmp_mmio_read(CRF_APB_DDR_CTRL, &clk_ctrl);
456 if (ret) {
457 printf("%s mio read fail\n", __func__);
458 return -EIO;
459 }
460
461 div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
462
463 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
464 pll = pll_src[DDR_CLK_SRC][srcsel];
465 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
466 if (IS_ERR_VALUE(pllrate))
467 return pllrate;
468
469 return DIV_ROUND_CLOSEST(pllrate, div);
470 }
471
zynqmp_clk_get_dll_rate(struct zynqmp_clk_priv * priv)472 static ulong zynqmp_clk_get_dll_rate(struct zynqmp_clk_priv *priv)
473 {
474 u32 clk_ctrl, srcsel;
475 enum zynqmp_clk pll;
476 ulong pllrate;
477 int ret;
478
479 ret = zynqmp_mmio_read(CRL_APB_DLL_REF_CTRL, &clk_ctrl);
480 if (ret) {
481 printf("%s mio read fail\n", __func__);
482 return -EIO;
483 }
484
485 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
486 pll = pll_src[DLL_CLK_SRC][srcsel];
487 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
488 if (IS_ERR_VALUE(pllrate))
489 return pllrate;
490
491 return pllrate;
492 }
493
zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv * priv,enum zynqmp_clk id,bool two_divs)494 static ulong zynqmp_clk_get_peripheral_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("%s mio read fail\n", __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
513 if (two_divs) {
514 div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
515 if (!div1)
516 div1 = 1;
517 }
518 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
519
520 if (id == gem_tsu_ref)
521 pll = pll_src[GEM_TSU_CLK_SRC][srcsel];
522 else
523 pll = pll_src[PERI_CLK_SRC][srcsel];
524
525 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
526 if (IS_ERR_VALUE(pllrate))
527 return pllrate;
528
529 return
530 DIV_ROUND_CLOSEST(
531 DIV_ROUND_CLOSEST(pllrate, div0), div1);
532 }
533
zynqmp_clk_get_crf_crl_rate(struct zynqmp_clk_priv * priv,enum zynqmp_clk id,bool two_divs)534 static ulong zynqmp_clk_get_crf_crl_rate(struct zynqmp_clk_priv *priv,
535 enum zynqmp_clk id, bool two_divs)
536 {
537 enum zynqmp_clk pll;
538 u32 clk_ctrl, div0, srcsel;
539 u32 div1 = 1;
540 int ret;
541 ulong pllrate;
542
543 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
544 if (ret) {
545 printf("%d %s mio read fail\n", __LINE__, __func__);
546 return -EIO;
547 }
548
549 div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
550 if (!div0)
551 div0 = 1;
552 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
553
554 switch (id) {
555 case wdt:
556 case dbg_trace:
557 case topsw_lsbus:
558 pll = pll_src[WDT_CLK_SRC][srcsel];
559 break;
560 case dbg_fpd:
561 case dbg_tstmp:
562 pll = pll_src[DBG_FPD_CLK_SRC][srcsel];
563 break;
564 case timestamp_ref:
565 pll = pll_src[TIMESTAMP_CLK_SRC][srcsel];
566 break;
567 case sata_ref:
568 pll = pll_src[SATA_CLK_SRC][srcsel];
569 break;
570 case pcie_ref:
571 pll = pll_src[PCIE_CLK_SRC][srcsel];
572 break;
573 case gpu_ref ... gpu_pp1_ref:
574 pll = pll_src[GPU_CLK_SRC][srcsel];
575 break;
576 case gdma_ref:
577 case dpdma_ref:
578 case topsw_main:
579 pll = pll_src[TOPSW_MAIN_CLK_SRC][srcsel];
580 break;
581 case cpu_r5:
582 case ams_ref:
583 case adma_ref:
584 case lpd_lsbus:
585 case lpd_switch:
586 pll = pll_src[CPU_R5_CLK_SRC][srcsel];
587 break;
588 default:
589 return -ENXIO;
590 }
591 if (two_divs) {
592 ret = zynqmp_mmio_read(zynqmp_clk_get_register(pll), &clk_ctrl);
593 if (ret) {
594 printf("%d %s mio read fail\n", __LINE__, __func__);
595 return -EIO;
596 }
597 div1 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
598 if (!div1)
599 div1 = 1;
600 }
601
602 if (pll == iopll_to_fpd)
603 pll = iopll;
604
605 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
606 if (IS_ERR_VALUE(pllrate))
607 return pllrate;
608
609 return
610 DIV_ROUND_CLOSEST(
611 DIV_ROUND_CLOSEST(pllrate, div0), div1);
612 }
613
zynqmp_clk_calc_peripheral_two_divs(ulong rate,ulong pll_rate,u32 * div0,u32 * div1)614 static unsigned long zynqmp_clk_calc_peripheral_two_divs(ulong rate,
615 ulong pll_rate,
616 u32 *div0, u32 *div1)
617 {
618 long new_err, best_err = (long)(~0UL >> 1);
619 ulong new_rate, best_rate = 0;
620 u32 d0, d1;
621
622 for (d0 = 1; d0 <= ZYNQ_CLK_MAXDIV; d0++) {
623 for (d1 = 1; d1 <= ZYNQ_CLK_MAXDIV >> 1; d1++) {
624 new_rate = DIV_ROUND_CLOSEST(
625 DIV_ROUND_CLOSEST(pll_rate, d0), d1);
626 new_err = abs(new_rate - rate);
627
628 if (new_err < best_err) {
629 *div0 = d0;
630 *div1 = d1;
631 best_err = new_err;
632 best_rate = new_rate;
633 }
634 }
635 }
636
637 return best_rate;
638 }
639
zynqmp_clk_set_peripheral_rate(struct zynqmp_clk_priv * priv,enum zynqmp_clk id,ulong rate,bool two_divs)640 static ulong zynqmp_clk_set_peripheral_rate(struct zynqmp_clk_priv *priv,
641 enum zynqmp_clk id, ulong rate,
642 bool two_divs)
643 {
644 enum zynqmp_clk pll;
645 u32 clk_ctrl, div0 = 0, div1 = 0;
646 ulong pll_rate, new_rate;
647 u32 reg, srcsel;
648 int ret;
649 u32 mask;
650
651 reg = zynqmp_clk_get_register(id);
652 ret = zynqmp_mmio_read(reg, &clk_ctrl);
653 if (ret) {
654 printf("%s mio read fail\n", __func__);
655 return -EIO;
656 }
657
658 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
659 pll = pll_src[PERI_CLK_SRC][srcsel];
660 pll_rate = zynqmp_clk_get_pll_rate(priv, pll);
661 if (IS_ERR_VALUE(pll_rate))
662 return pll_rate;
663
664 clk_ctrl &= ~CLK_CTRL_DIV0_MASK;
665 if (two_divs) {
666 clk_ctrl &= ~CLK_CTRL_DIV1_MASK;
667 new_rate = zynqmp_clk_calc_peripheral_two_divs(rate, pll_rate,
668 &div0, &div1);
669 clk_ctrl |= div1 << CLK_CTRL_DIV1_SHIFT;
670 } else {
671 div0 = DIV_ROUND_CLOSEST(pll_rate, rate);
672 if (div0 > ZYNQ_CLK_MAXDIV)
673 div0 = ZYNQ_CLK_MAXDIV;
674 new_rate = DIV_ROUND_CLOSEST(rate, div0);
675 }
676 clk_ctrl |= div0 << CLK_CTRL_DIV0_SHIFT;
677
678 mask = (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT) |
679 (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT);
680
681 ret = zynqmp_mmio_write(reg, mask, clk_ctrl);
682 if (ret) {
683 printf("%s mio write fail\n", __func__);
684 return -EIO;
685 }
686
687 return new_rate;
688 }
689
zynqmp_clk_get_rate(struct clk * clk)690 static ulong zynqmp_clk_get_rate(struct clk *clk)
691 {
692 struct zynqmp_clk_priv *priv = dev_get_priv(clk->dev);
693 enum zynqmp_clk id = clk->id;
694 bool two_divs = false;
695
696 switch (id) {
697 case iopll ... vpll:
698 return zynqmp_clk_get_pll_rate(priv, id);
699 case acpu:
700 return zynqmp_clk_get_cpu_rate(priv, id);
701 case ddr_ref:
702 return zynqmp_clk_get_ddr_rate(priv);
703 case dll_ref:
704 return zynqmp_clk_get_dll_rate(priv);
705 case gem_tsu_ref:
706 case dp_video_ref ... dp_stc_ref:
707 case pl0 ... pl3:
708 case gem0_ref ... gem3_ref:
709 case gem0_tx ... gem3_tx:
710 case qspi_ref ... can1_ref:
711 case usb0_bus_ref ... usb3_dual_ref:
712 two_divs = true;
713 return zynqmp_clk_get_peripheral_rate(priv, id, two_divs);
714 case wdt:
715 case topsw_lsbus:
716 case sata_ref ... gpu_pp1_ref:
717 two_divs = true;
718 fallthrough;
719 case cpu_r5:
720 case dbg_fpd:
721 case ams_ref:
722 case adma_ref:
723 case lpd_lsbus:
724 case dbg_trace:
725 case dbg_tstmp:
726 case lpd_switch:
727 case topsw_main:
728 case timestamp_ref:
729 case gdma_ref ... dpdma_ref:
730 return zynqmp_clk_get_crf_crl_rate(priv, id, two_divs);
731 default:
732 return -ENXIO;
733 }
734 }
735
zynqmp_clk_set_rate(struct clk * clk,ulong rate)736 static ulong zynqmp_clk_set_rate(struct clk *clk, ulong rate)
737 {
738 struct zynqmp_clk_priv *priv = dev_get_priv(clk->dev);
739 enum zynqmp_clk id = clk->id;
740 bool two_divs = true;
741
742 switch (id) {
743 case gem0_ref ... gem3_ref:
744 case gem0_tx ... gem3_tx:
745 case gem0_rx ... gem3_rx:
746 case gem_tsu:
747 case qspi_ref ... can1_ref:
748 case usb0_bus_ref ... usb3_dual_ref:
749 case dp_video_ref ... dp_stc_ref:
750 return zynqmp_clk_set_peripheral_rate(priv, id,
751 rate, two_divs);
752 default:
753 return -ENXIO;
754 }
755 }
756
757 #if IS_ENABLED(CONFIG_CMD_CLK)
zynqmp_clk_dump(struct udevice * dev)758 static void zynqmp_clk_dump(struct udevice *dev)
759 {
760 int i, ret;
761
762 printf("clk\t\tfrequency\n");
763 for (i = 0; i < clk_max; i++) {
764 const char *name = clk_names[i];
765 if (name) {
766 struct clk clk;
767 unsigned long rate;
768
769 clk.id = i;
770 ret = clk_request(dev, &clk);
771 if (ret < 0) {
772 printf("%s clk_request() failed: %d\n",
773 __func__, ret);
774 break;
775 }
776
777 rate = clk_get_rate(&clk);
778
779 if ((rate == (unsigned long)-ENOSYS) ||
780 (rate == (unsigned long)-ENXIO) ||
781 (rate == (unsigned long)-EIO))
782 printf("%10s%20s\n", name, "unknown");
783 else
784 printf("%10s%20lu\n", name, rate);
785 }
786 }
787 }
788 #endif
789
zynqmp_get_freq_by_name(char * name,struct udevice * dev,ulong * freq)790 static int zynqmp_get_freq_by_name(char *name, struct udevice *dev, ulong *freq)
791 {
792 struct clk clk;
793 int ret;
794
795 ret = clk_get_by_name(dev, name, &clk);
796 if (ret < 0) {
797 dev_err(dev, "failed to get %s\n", name);
798 return ret;
799 }
800
801 *freq = clk_get_rate(&clk);
802 if (IS_ERR_VALUE(*freq)) {
803 dev_err(dev, "failed to get rate %s\n", name);
804 return -EINVAL;
805 }
806
807 return 0;
808 }
zynqmp_clk_probe(struct udevice * dev)809 static int zynqmp_clk_probe(struct udevice *dev)
810 {
811 int ret;
812 struct zynqmp_clk_priv *priv = dev_get_priv(dev);
813
814 debug("%s\n", __func__);
815 ret = zynqmp_get_freq_by_name("pss_ref_clk", dev, &priv->ps_clk_freq);
816 if (ret < 0)
817 return -EINVAL;
818
819 ret = zynqmp_get_freq_by_name("video_clk", dev, &priv->video_clk);
820 if (ret < 0)
821 return -EINVAL;
822
823 ret = zynqmp_get_freq_by_name("pss_alt_ref_clk", dev,
824 &priv->pss_alt_ref_clk);
825 if (ret < 0)
826 return -EINVAL;
827
828 ret = zynqmp_get_freq_by_name("aux_ref_clk", dev, &priv->aux_ref_clk);
829 if (ret < 0)
830 return -EINVAL;
831
832 ret = zynqmp_get_freq_by_name("gt_crx_ref_clk", dev,
833 &priv->gt_crx_ref_clk);
834 if (ret < 0)
835 return -EINVAL;
836
837 return 0;
838 }
839
zynqmp_clk_enable(struct clk * clk)840 static int zynqmp_clk_enable(struct clk *clk)
841 {
842 enum zynqmp_clk id = clk->id;
843 u32 reg, clk_ctrl, clkact_shift, mask;
844 int ret;
845
846 reg = zynqmp_clk_get_register(id);
847 debug("%s, clk_id:%x, clk_base:0x%x\n", __func__, id, reg);
848
849 switch (id) {
850 case usb0_bus_ref ... usb1:
851 clkact_shift = 25;
852 mask = 0x1;
853 break;
854 case gem0_tx ... gem3_tx:
855 case gem0_ref ... gem3_ref:
856 clkact_shift = 25;
857 mask = 0x3;
858 break;
859 case qspi_ref ... can1_ref:
860 case lpd_lsbus:
861 case topsw_lsbus:
862 clkact_shift = 24;
863 mask = 0x1;
864 break;
865 default:
866 return -ENXIO;
867 }
868
869 ret = zynqmp_mmio_read(reg, &clk_ctrl);
870 if (ret) {
871 printf("%s mio read fail\n", __func__);
872 return -EIO;
873 }
874
875 clk_ctrl |= (mask << clkact_shift);
876 ret = zynqmp_mmio_write(reg, mask << clkact_shift, clk_ctrl);
877 if (ret) {
878 printf("%s mio write fail\n", __func__);
879 return -EIO;
880 }
881
882 return ret;
883 }
884
885 static struct clk_ops zynqmp_clk_ops = {
886 .set_rate = zynqmp_clk_set_rate,
887 .get_rate = zynqmp_clk_get_rate,
888 .enable = zynqmp_clk_enable,
889 #if IS_ENABLED(CONFIG_CMD_CLK)
890 .dump = zynqmp_clk_dump,
891 #endif
892 };
893
894 static const struct udevice_id zynqmp_clk_ids[] = {
895 { .compatible = "xlnx,zynqmp-clk" },
896 { }
897 };
898
899 U_BOOT_DRIVER(zynqmp_clk) = {
900 .name = "zynqmp_clk",
901 .id = UCLASS_CLK,
902 .of_match = zynqmp_clk_ids,
903 .probe = zynqmp_clk_probe,
904 .ops = &zynqmp_clk_ops,
905 .priv_auto = sizeof(struct zynqmp_clk_priv),
906 };
907