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