blob: 9038fb8befd9c15b693ab96d611c0961bb56046b [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +05302/*
3 * ZynqMP clock driver
4 *
5 * Copyright (C) 2016 Xilinx, Inc.
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +05306 */
7
8#include <common.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -06009#include <log.h>
Simon Glass336d4612020-02-03 07:36:16 -070010#include <malloc.h>
11#include <dm/device_compat.h>
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +053012#include <linux/bitops.h>
13#include <clk-uclass.h>
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +053014#include <clk.h>
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +053015#include <asm/arch/sys_proto.h>
Simon Glass9d922452017-05-17 17:18:03 -060016#include <dm.h>
Simon Glass61b29b82020-02-03 07:36:15 -070017#include <linux/err.h>
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +053018
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +053019static const resource_size_t zynqmp_crf_apb_clkc_base = 0xfd1a0020;
20static const resource_size_t zynqmp_crl_apb_clkc_base = 0xff5e0020;
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +053021
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +053022/* 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)
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +053094
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)
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700100#define CLK_CTRL_SRCSEL_MASK 0x7
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530101#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)
Vipul Kumarb4f01582018-06-27 10:44:45 +0530109#define PLLCTRL_PRE_SRC_SHFT 20
110#define PLLCTRL_PRE_SRC_MASK (0x7 << PLLCTRL_PRE_SRC_SHFT)
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530111
112
113#define NUM_MIO_PINS 77
114
115enum 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,
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700133 gem0_tx, gem1_tx, gem2_tx, gem3_tx,
Michal Simek0e789d22021-10-29 13:13:38 +0200134 gem0_rx, gem1_rx, gem2_rx, gem3_rx,
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530135 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,
Michal Simek0e789d22021-10-29 13:13:38 +0200147 gem0_ref = 104,
148 gem1_ref, gem2_ref, gem3_ref,
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530149 clk_max,
150};
151
152static 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",
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700156 "acpu", "acpu_half", "dbg_fpd", "dbg_lpd",
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530157 "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",
Michal Simek0e789d22021-10-29 13:13:38 +0200166 "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",
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530169 "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",
Michal Simek0e789d22021-10-29 13:13:38 +0200173 "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",
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530178};
179
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700180static 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
196enum 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
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530212struct 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
220static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530221{
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530222 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;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700235 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 gpu_ref ... gpu_pp1_ref:
242 return CRF_APB_GPU_REF_CTRL;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530243 case ddr_ref:
244 return CRF_APB_DDR_CTRL;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700245 case sata_ref:
246 return CRF_APB_SATA_REF_CTRL;
247 case pcie_ref:
248 return CRF_APB_PCIE_REF_CTRL;
249 case gdma_ref:
250 return CRF_APB_GDMA_REF_CTRL;
251 case dpdma_ref:
252 return CRF_APB_DPDMA_REF_CTRL;
253 case topsw_main:
254 return CRF_APB_TOPSW_MAIN_CTRL;
255 case topsw_lsbus:
256 return CRF_APB_TOPSW_LSBUS_CTRL;
257 case lpd_switch:
258 return CRL_APB_LPD_SWITCH_CTRL;
259 case lpd_lsbus:
260 return CRL_APB_LPD_LSBUS_CTRL;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530261 case qspi_ref:
262 return CRL_APB_QSPI_REF_CTRL;
T Karthik Reddya72a6ae2021-02-03 03:10:45 -0700263 case usb3_dual_ref:
264 return CRL_APB_USB3_DUAL_REF_CTRL;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700265 case gem_tsu_ref:
266 return CRL_APB_GEM_TSU_REF_CTRL;
Michal Simek0e789d22021-10-29 13:13:38 +0200267 case gem0_tx:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530268 case gem0_ref:
269 return CRL_APB_GEM0_REF_CTRL;
Michal Simek0e789d22021-10-29 13:13:38 +0200270 case gem1_tx:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530271 case gem1_ref:
272 return CRL_APB_GEM1_REF_CTRL;
Michal Simek0e789d22021-10-29 13:13:38 +0200273 case gem2_tx:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530274 case gem2_ref:
275 return CRL_APB_GEM2_REF_CTRL;
Michal Simek0e789d22021-10-29 13:13:38 +0200276 case gem3_tx:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530277 case gem3_ref:
278 return CRL_APB_GEM3_REF_CTRL;
T Karthik Reddya72a6ae2021-02-03 03:10:45 -0700279 case usb0_bus_ref:
280 return CRL_APB_USB0_BUS_REF_CTRL;
281 case usb1_bus_ref:
282 return CRL_APB_USB1_BUS_REF_CTRL;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700283 case cpu_r5:
284 return CRL_APB_CPU_R5_CTRL;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530285 case uart0_ref:
286 return CRL_APB_UART0_REF_CTRL;
287 case uart1_ref:
288 return CRL_APB_UART1_REF_CTRL;
289 case sdio0_ref:
290 return CRL_APB_SDIO0_REF_CTRL;
291 case sdio1_ref:
292 return CRL_APB_SDIO1_REF_CTRL;
293 case spi0_ref:
294 return CRL_APB_SPI0_REF_CTRL;
295 case spi1_ref:
296 return CRL_APB_SPI1_REF_CTRL;
297 case nand_ref:
298 return CRL_APB_NAND_REF_CTRL;
299 case i2c0_ref:
300 return CRL_APB_I2C0_REF_CTRL;
301 case i2c1_ref:
302 return CRL_APB_I2C1_REF_CTRL;
303 case can0_ref:
304 return CRL_APB_CAN0_REF_CTRL;
305 case can1_ref:
306 return CRL_APB_CAN1_REF_CTRL;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700307 case dll_ref:
308 return CRL_APB_DLL_REF_CTRL;
309 case adma_ref:
310 return CRL_APB_ADMA_REF_CTRL;
311 case timestamp_ref:
312 return CRL_APB_TIMESTAMP_REF_CTRL;
313 case ams_ref:
314 return CRL_APB_AMS_REF_CTRL;
Vipul Kumara79b5902018-03-07 14:52:44 +0530315 case pl0:
316 return CRL_APB_PL0_REF_CTRL;
317 case pl1:
318 return CRL_APB_PL1_REF_CTRL;
319 case pl2:
320 return CRL_APB_PL2_REF_CTRL;
321 case pl3:
322 return CRL_APB_PL3_REF_CTRL;
323 case wdt:
324 return CRF_APB_TOPSW_LSBUS_CTRL;
325 case iopll_to_fpd:
326 return CRL_APB_IOPLL_TO_FPD_CTRL;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530327 default:
328 debug("Invalid clk id%d\n", id);
329 }
330 return 0;
331}
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530332
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530333static ulong zynqmp_clk_get_pll_src(ulong clk_ctrl,
334 struct zynqmp_clk_priv *priv,
335 bool is_pre_src)
336{
337 u32 src_sel;
338
339 if (is_pre_src)
Vipul Kumarb4f01582018-06-27 10:44:45 +0530340 src_sel = (clk_ctrl & PLLCTRL_PRE_SRC_MASK) >>
341 PLLCTRL_PRE_SRC_SHFT;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530342 else
343 src_sel = (clk_ctrl & PLLCTRL_POST_SRC_MASK) >>
344 PLLCTRL_POST_SRC_SHFT;
345
346 switch (src_sel) {
347 case 4:
348 return priv->video_clk;
349 case 5:
350 return priv->pss_alt_ref_clk;
351 case 6:
352 return priv->aux_ref_clk;
353 case 7:
354 return priv->gt_crx_ref_clk;
355 case 0 ... 3:
356 default:
357 return priv->ps_clk_freq;
358 }
359}
360
361static ulong zynqmp_clk_get_pll_rate(struct zynqmp_clk_priv *priv,
362 enum zynqmp_clk id)
363{
364 u32 clk_ctrl, reset, mul;
365 ulong freq;
366 int ret;
367
368 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530369 if (ret) {
370 printf("%s mio read fail\n", __func__);
371 return -EIO;
372 }
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530373
374 if (clk_ctrl & PLLCTRL_BYPASS_MASK)
375 freq = zynqmp_clk_get_pll_src(clk_ctrl, priv, 0);
376 else
377 freq = zynqmp_clk_get_pll_src(clk_ctrl, priv, 1);
378
379 reset = (clk_ctrl & PLLCTRL_RESET_MASK) >> PLLCTRL_RESET_SHIFT;
380 if (reset && !(clk_ctrl & PLLCTRL_BYPASS_MASK))
381 return 0;
382
383 mul = (clk_ctrl & PLLCTRL_FBDIV_MASK) >> PLLCTRL_FBDIV_SHIFT;
384
385 freq *= mul;
386
387 if (clk_ctrl & (1 << 16))
388 freq /= 2;
389
390 return freq;
391}
392
393static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
394 enum zynqmp_clk id)
395{
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700396 u32 clk_ctrl, div, srcsel;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530397 enum zynqmp_clk pll;
398 int ret;
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530399 unsigned long pllrate;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530400
401 ret = zynqmp_mmio_read(CRF_APB_ACPU_CTRL, &clk_ctrl);
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530402 if (ret) {
403 printf("%s mio read fail\n", __func__);
404 return -EIO;
405 }
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530406
407 div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
408
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700409 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
410 pll = pll_src[ACPU_CLK_SRC][srcsel];
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530411 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
412 if (IS_ERR_VALUE(pllrate))
413 return pllrate;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530414
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530415 return DIV_ROUND_CLOSEST(pllrate, div);
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530416}
417
418static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
419{
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700420 u32 clk_ctrl, div, srcsel;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530421 enum zynqmp_clk pll;
422 int ret;
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530423 ulong pllrate;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530424
425 ret = zynqmp_mmio_read(CRF_APB_DDR_CTRL, &clk_ctrl);
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530426 if (ret) {
427 printf("%s mio read fail\n", __func__);
428 return -EIO;
429 }
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530430
431 div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
432
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700433 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
434 pll = pll_src[DDR_CLK_SRC][srcsel];
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530435 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
436 if (IS_ERR_VALUE(pllrate))
437 return pllrate;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530438
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530439 return DIV_ROUND_CLOSEST(pllrate, div);
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530440}
441
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700442static ulong zynqmp_clk_get_dll_rate(struct zynqmp_clk_priv *priv)
443{
444 u32 clk_ctrl, srcsel;
445 enum zynqmp_clk pll;
446 ulong pllrate;
447 int ret;
448
449 ret = zynqmp_mmio_read(CRL_APB_DLL_REF_CTRL, &clk_ctrl);
450 if (ret) {
451 printf("%s mio read fail\n", __func__);
452 return -EIO;
453 }
454
455 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
456 pll = pll_src[DLL_CLK_SRC][srcsel];
457 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
458 if (IS_ERR_VALUE(pllrate))
459 return pllrate;
460
461 return pllrate;
462}
463
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530464static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv,
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700465 enum zynqmp_clk id, bool two_divs)
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530466{
467 enum zynqmp_clk pll;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700468 u32 clk_ctrl, div0, srcsel;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530469 u32 div1 = 1;
470 int ret;
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530471 ulong pllrate;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530472
473 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530474 if (ret) {
475 printf("%s mio read fail\n", __func__);
476 return -EIO;
477 }
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530478
479 div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
480 if (!div0)
481 div0 = 1;
482
483 if (two_divs) {
484 div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
485 if (!div1)
486 div1 = 1;
487 }
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700488 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530489
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700490 if (id == gem_tsu_ref)
491 pll = pll_src[GEM_TSU_CLK_SRC][srcsel];
492 else
493 pll = pll_src[PERI_CLK_SRC][srcsel];
494
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530495 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
496 if (IS_ERR_VALUE(pllrate))
497 return pllrate;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530498
499 return
500 DIV_ROUND_CLOSEST(
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530501 DIV_ROUND_CLOSEST(pllrate, div0), div1);
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530502}
503
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700504static ulong zynqmp_clk_get_crf_crl_rate(struct zynqmp_clk_priv *priv,
505 enum zynqmp_clk id, bool two_divs)
Vipul Kumara79b5902018-03-07 14:52:44 +0530506{
507 enum zynqmp_clk pll;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700508 u32 clk_ctrl, div0, srcsel;
Vipul Kumara79b5902018-03-07 14:52:44 +0530509 u32 div1 = 1;
510 int ret;
511 ulong pllrate;
512
513 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
514 if (ret) {
515 printf("%d %s mio read fail\n", __LINE__, __func__);
516 return -EIO;
517 }
518
519 div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
520 if (!div0)
521 div0 = 1;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700522 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
Vipul Kumara79b5902018-03-07 14:52:44 +0530523
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700524 switch (id) {
525 case wdt:
526 case dbg_trace:
527 case topsw_lsbus:
528 pll = pll_src[WDT_CLK_SRC][srcsel];
529 break;
530 case dbg_fpd:
531 case dbg_tstmp:
532 pll = pll_src[DBG_FPD_CLK_SRC][srcsel];
533 break;
534 case timestamp_ref:
535 pll = pll_src[TIMESTAMP_CLK_SRC][srcsel];
536 break;
537 case sata_ref:
538 pll = pll_src[SATA_CLK_SRC][srcsel];
539 break;
540 case pcie_ref:
541 pll = pll_src[PCIE_CLK_SRC][srcsel];
542 break;
543 case gpu_ref ... gpu_pp1_ref:
544 pll = pll_src[GPU_CLK_SRC][srcsel];
545 break;
546 case gdma_ref:
547 case dpdma_ref:
548 case topsw_main:
549 pll = pll_src[TOPSW_MAIN_CLK_SRC][srcsel];
550 break;
551 case cpu_r5:
552 case ams_ref:
553 case adma_ref:
554 case lpd_lsbus:
555 case lpd_switch:
556 pll = pll_src[CPU_R5_CLK_SRC][srcsel];
557 break;
558 default:
559 return -ENXIO;
560 }
Vipul Kumara79b5902018-03-07 14:52:44 +0530561 if (two_divs) {
562 ret = zynqmp_mmio_read(zynqmp_clk_get_register(pll), &clk_ctrl);
563 if (ret) {
564 printf("%d %s mio read fail\n", __LINE__, __func__);
565 return -EIO;
566 }
567 div1 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
568 if (!div1)
569 div1 = 1;
570 }
571
572 if (pll == iopll_to_fpd)
573 pll = iopll;
574
575 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
576 if (IS_ERR_VALUE(pllrate))
577 return pllrate;
578
579 return
580 DIV_ROUND_CLOSEST(
581 DIV_ROUND_CLOSEST(pllrate, div0), div1);
582}
583
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530584static unsigned long zynqmp_clk_calc_peripheral_two_divs(ulong rate,
585 ulong pll_rate,
586 u32 *div0, u32 *div1)
587{
588 long new_err, best_err = (long)(~0UL >> 1);
589 ulong new_rate, best_rate = 0;
590 u32 d0, d1;
591
592 for (d0 = 1; d0 <= ZYNQ_CLK_MAXDIV; d0++) {
593 for (d1 = 1; d1 <= ZYNQ_CLK_MAXDIV >> 1; d1++) {
594 new_rate = DIV_ROUND_CLOSEST(
595 DIV_ROUND_CLOSEST(pll_rate, d0), d1);
596 new_err = abs(new_rate - rate);
597
598 if (new_err < best_err) {
599 *div0 = d0;
600 *div1 = d1;
601 best_err = new_err;
602 best_rate = new_rate;
603 }
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530604 }
605 }
606
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530607 return best_rate;
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530608}
609
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530610static ulong zynqmp_clk_set_peripheral_rate(struct zynqmp_clk_priv *priv,
611 enum zynqmp_clk id, ulong rate,
612 bool two_divs)
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530613{
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530614 enum zynqmp_clk pll;
615 u32 clk_ctrl, div0 = 0, div1 = 0;
616 ulong pll_rate, new_rate;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700617 u32 reg, srcsel;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530618 int ret;
619 u32 mask;
620
621 reg = zynqmp_clk_get_register(id);
622 ret = zynqmp_mmio_read(reg, &clk_ctrl);
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530623 if (ret) {
624 printf("%s mio read fail\n", __func__);
625 return -EIO;
626 }
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530627
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700628 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
629 pll = pll_src[PERI_CLK_SRC][srcsel];
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530630 pll_rate = zynqmp_clk_get_pll_rate(priv, pll);
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530631 if (IS_ERR_VALUE(pll_rate))
632 return pll_rate;
633
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530634 clk_ctrl &= ~CLK_CTRL_DIV0_MASK;
635 if (two_divs) {
636 clk_ctrl &= ~CLK_CTRL_DIV1_MASK;
637 new_rate = zynqmp_clk_calc_peripheral_two_divs(rate, pll_rate,
638 &div0, &div1);
639 clk_ctrl |= div1 << CLK_CTRL_DIV1_SHIFT;
640 } else {
641 div0 = DIV_ROUND_CLOSEST(pll_rate, rate);
642 if (div0 > ZYNQ_CLK_MAXDIV)
643 div0 = ZYNQ_CLK_MAXDIV;
644 new_rate = DIV_ROUND_CLOSEST(rate, div0);
645 }
646 clk_ctrl |= div0 << CLK_CTRL_DIV0_SHIFT;
647
648 mask = (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT) |
649 (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT);
650
651 ret = zynqmp_mmio_write(reg, mask, clk_ctrl);
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530652 if (ret) {
653 printf("%s mio write fail\n", __func__);
654 return -EIO;
655 }
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530656
657 return new_rate;
658}
659
660static ulong zynqmp_clk_get_rate(struct clk *clk)
661{
662 struct zynqmp_clk_priv *priv = dev_get_priv(clk->dev);
663 enum zynqmp_clk id = clk->id;
664 bool two_divs = false;
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530665
666 switch (id) {
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530667 case iopll ... vpll:
668 return zynqmp_clk_get_pll_rate(priv, id);
669 case acpu:
670 return zynqmp_clk_get_cpu_rate(priv, id);
671 case ddr_ref:
672 return zynqmp_clk_get_ddr_rate(priv);
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700673 case dll_ref:
674 return zynqmp_clk_get_dll_rate(priv);
675 case gem_tsu_ref:
676 case pl0 ... pl3:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530677 case gem0_ref ... gem3_ref:
Michal Simek0e789d22021-10-29 13:13:38 +0200678 case gem0_tx ... gem3_tx:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530679 case qspi_ref ... can1_ref:
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700680 case usb0_bus_ref ... usb3_dual_ref:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530681 two_divs = true;
682 return zynqmp_clk_get_peripheral_rate(priv, id, two_divs);
Vipul Kumara79b5902018-03-07 14:52:44 +0530683 case wdt:
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700684 case topsw_lsbus:
685 case sata_ref ... gpu_pp1_ref:
Vipul Kumara79b5902018-03-07 14:52:44 +0530686 two_divs = true;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700687 case cpu_r5:
688 case dbg_fpd:
689 case ams_ref:
690 case adma_ref:
691 case lpd_lsbus:
692 case dbg_trace:
693 case dbg_tstmp:
694 case lpd_switch:
695 case topsw_main:
696 case timestamp_ref:
697 case gdma_ref ... dpdma_ref:
698 return zynqmp_clk_get_crf_crl_rate(priv, id, two_divs);
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530699 default:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530700 return -ENXIO;
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530701 }
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530702}
703
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530704static ulong zynqmp_clk_set_rate(struct clk *clk, ulong rate)
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530705{
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530706 struct zynqmp_clk_priv *priv = dev_get_priv(clk->dev);
707 enum zynqmp_clk id = clk->id;
708 bool two_divs = true;
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530709
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530710 switch (id) {
711 case gem0_ref ... gem3_ref:
Michal Simek0e789d22021-10-29 13:13:38 +0200712 case gem0_tx ... gem3_tx:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530713 case qspi_ref ... can1_ref:
Michal Simeke959ade2021-10-29 13:13:37 +0200714 case usb0_bus_ref ... usb3_dual_ref:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530715 return zynqmp_clk_set_peripheral_rate(priv, id,
716 rate, two_divs);
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530717 default:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530718 return -ENXIO;
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530719 }
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530720}
721
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530722int soc_clk_dump(void)
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530723{
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530724 struct udevice *dev;
725 int i, ret;
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530726
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530727 ret = uclass_get_device_by_driver(UCLASS_CLK,
Simon Glass65e25be2020-12-28 20:34:56 -0700728 DM_DRIVER_GET(zynqmp_clk), &dev);
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530729 if (ret)
730 return ret;
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530731
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530732 printf("clk\t\tfrequency\n");
733 for (i = 0; i < clk_max; i++) {
734 const char *name = clk_names[i];
735 if (name) {
736 struct clk clk;
737 unsigned long rate;
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530738
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530739 clk.id = i;
740 ret = clk_request(dev, &clk);
741 if (ret < 0)
742 return ret;
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530743
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530744 rate = clk_get_rate(&clk);
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530745
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530746 clk_free(&clk);
747
748 if ((rate == (unsigned long)-ENOSYS) ||
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530749 (rate == (unsigned long)-ENXIO) ||
750 (rate == (unsigned long)-EIO))
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530751 printf("%10s%20s\n", name, "unknown");
752 else
753 printf("%10s%20lu\n", name, rate);
754 }
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530755 }
756
757 return 0;
758}
759
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530760static int zynqmp_get_freq_by_name(char *name, struct udevice *dev, ulong *freq)
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530761{
762 struct clk clk;
763 int ret;
764
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530765 ret = clk_get_by_name(dev, name, &clk);
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530766 if (ret < 0) {
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530767 dev_err(dev, "failed to get %s\n", name);
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530768 return ret;
769 }
770
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530771 *freq = clk_get_rate(&clk);
772 if (IS_ERR_VALUE(*freq)) {
773 dev_err(dev, "failed to get rate %s\n", name);
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530774 return -EINVAL;
775 }
776
777 return 0;
778}
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530779static int zynqmp_clk_probe(struct udevice *dev)
780{
781 int ret;
782 struct zynqmp_clk_priv *priv = dev_get_priv(dev);
783
784 debug("%s\n", __func__);
785 ret = zynqmp_get_freq_by_name("pss_ref_clk", dev, &priv->ps_clk_freq);
786 if (ret < 0)
787 return -EINVAL;
788
789 ret = zynqmp_get_freq_by_name("video_clk", dev, &priv->video_clk);
790 if (ret < 0)
791 return -EINVAL;
792
793 ret = zynqmp_get_freq_by_name("pss_alt_ref_clk", dev,
794 &priv->pss_alt_ref_clk);
795 if (ret < 0)
796 return -EINVAL;
797
798 ret = zynqmp_get_freq_by_name("aux_ref_clk", dev, &priv->aux_ref_clk);
799 if (ret < 0)
800 return -EINVAL;
801
802 ret = zynqmp_get_freq_by_name("gt_crx_ref_clk", dev,
803 &priv->gt_crx_ref_clk);
804 if (ret < 0)
805 return -EINVAL;
806
807 return 0;
808}
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530809
T Karthik Reddya72a6ae2021-02-03 03:10:45 -0700810static int zynqmp_clk_enable(struct clk *clk)
811{
812 enum zynqmp_clk id = clk->id;
813 u32 reg, clk_ctrl, clkact_shift, mask;
814 int ret;
815
816 reg = zynqmp_clk_get_register(id);
817 debug("%s, clk_id:%x, clk_base:0x%x\n", __func__, id, reg);
818
819 switch (id) {
820 case usb0_bus_ref ... usb1:
821 clkact_shift = 25;
822 mask = 0x1;
823 break;
Michal Simek0e789d22021-10-29 13:13:38 +0200824 case gem0_tx ... gem3_tx:
T Karthik Reddya72a6ae2021-02-03 03:10:45 -0700825 case gem0_ref ... gem3_ref:
826 clkact_shift = 25;
827 mask = 0x3;
828 break;
829 case qspi_ref ... can1_ref:
Michal Simek0c383a72021-07-01 19:01:42 +0200830 case lpd_lsbus:
T Karthik Reddya72a6ae2021-02-03 03:10:45 -0700831 clkact_shift = 24;
832 mask = 0x1;
833 break;
834 default:
835 return -ENXIO;
836 }
837
838 ret = zynqmp_mmio_read(reg, &clk_ctrl);
839 if (ret) {
840 printf("%s mio read fail\n", __func__);
841 return -EIO;
842 }
843
844 clk_ctrl |= (mask << clkact_shift);
845 ret = zynqmp_mmio_write(reg, mask << clkact_shift, clk_ctrl);
846 if (ret) {
847 printf("%s mio write fail\n", __func__);
848 return -EIO;
849 }
850
851 return ret;
852}
853
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530854static struct clk_ops zynqmp_clk_ops = {
855 .set_rate = zynqmp_clk_set_rate,
856 .get_rate = zynqmp_clk_get_rate,
T Karthik Reddya72a6ae2021-02-03 03:10:45 -0700857 .enable = zynqmp_clk_enable,
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530858};
859
860static const struct udevice_id zynqmp_clk_ids[] = {
Michal Simek969dd4c2018-02-21 13:59:21 +0100861 { .compatible = "xlnx,zynqmp-clk" },
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530862 { }
863};
864
865U_BOOT_DRIVER(zynqmp_clk) = {
Michal Simek6c0e59f2020-01-07 08:50:34 +0100866 .name = "zynqmp_clk",
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530867 .id = UCLASS_CLK,
868 .of_match = zynqmp_clk_ids,
869 .probe = zynqmp_clk_probe,
870 .ops = &zynqmp_clk_ops,
Simon Glass41575d82020-12-03 16:55:17 -0700871 .priv_auto = sizeof(struct zynqmp_clk_priv),
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530872};