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