blob: be0ee50e0e4fdb728d35b186011ef467f6935c71 [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;
Michal Simek6f735e42022-03-29 13:13:56 +0200241 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;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700247 case gpu_ref ... gpu_pp1_ref:
248 return CRF_APB_GPU_REF_CTRL;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530249 case ddr_ref:
250 return CRF_APB_DDR_CTRL;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700251 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;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530267 case qspi_ref:
268 return CRL_APB_QSPI_REF_CTRL;
T Karthik Reddya72a6ae2021-02-03 03:10:45 -0700269 case usb3_dual_ref:
270 return CRL_APB_USB3_DUAL_REF_CTRL;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700271 case gem_tsu_ref:
272 return CRL_APB_GEM_TSU_REF_CTRL;
Michal Simek0e789d22021-10-29 13:13:38 +0200273 case gem0_tx:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530274 case gem0_ref:
275 return CRL_APB_GEM0_REF_CTRL;
Michal Simek0e789d22021-10-29 13:13:38 +0200276 case gem1_tx:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530277 case gem1_ref:
278 return CRL_APB_GEM1_REF_CTRL;
Michal Simek0e789d22021-10-29 13:13:38 +0200279 case gem2_tx:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530280 case gem2_ref:
281 return CRL_APB_GEM2_REF_CTRL;
Michal Simek0e789d22021-10-29 13:13:38 +0200282 case gem3_tx:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530283 case gem3_ref:
284 return CRL_APB_GEM3_REF_CTRL;
T Karthik Reddya72a6ae2021-02-03 03:10:45 -0700285 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;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700289 case cpu_r5:
290 return CRL_APB_CPU_R5_CTRL;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530291 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;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700313 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;
Vipul Kumara79b5902018-03-07 14:52:44 +0530321 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;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530333 default:
334 debug("Invalid clk id%d\n", id);
335 }
336 return 0;
337}
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530338
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530339static 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)
Vipul Kumarb4f01582018-06-27 10:44:45 +0530346 src_sel = (clk_ctrl & PLLCTRL_PRE_SRC_MASK) >>
347 PLLCTRL_PRE_SRC_SHFT;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530348 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
367static 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);
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530375 if (ret) {
376 printf("%s mio read fail\n", __func__);
377 return -EIO;
378 }
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530379
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
399static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
400 enum zynqmp_clk id)
401{
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700402 u32 clk_ctrl, div, srcsel;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530403 enum zynqmp_clk pll;
404 int ret;
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530405 unsigned long pllrate;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530406
407 ret = zynqmp_mmio_read(CRF_APB_ACPU_CTRL, &clk_ctrl);
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530408 if (ret) {
409 printf("%s mio read fail\n", __func__);
410 return -EIO;
411 }
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530412
413 div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
414
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700415 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
416 pll = pll_src[ACPU_CLK_SRC][srcsel];
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530417 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
418 if (IS_ERR_VALUE(pllrate))
419 return pllrate;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530420
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530421 return DIV_ROUND_CLOSEST(pllrate, div);
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530422}
423
424static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
425{
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700426 u32 clk_ctrl, div, srcsel;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530427 enum zynqmp_clk pll;
428 int ret;
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530429 ulong pllrate;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530430
431 ret = zynqmp_mmio_read(CRF_APB_DDR_CTRL, &clk_ctrl);
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530432 if (ret) {
433 printf("%s mio read fail\n", __func__);
434 return -EIO;
435 }
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530436
437 div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
438
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700439 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
440 pll = pll_src[DDR_CLK_SRC][srcsel];
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530441 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
442 if (IS_ERR_VALUE(pllrate))
443 return pllrate;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530444
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530445 return DIV_ROUND_CLOSEST(pllrate, div);
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530446}
447
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700448static 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
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530470static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv,
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700471 enum zynqmp_clk id, bool two_divs)
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530472{
473 enum zynqmp_clk pll;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700474 u32 clk_ctrl, div0, srcsel;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530475 u32 div1 = 1;
476 int ret;
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530477 ulong pllrate;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530478
479 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530480 if (ret) {
481 printf("%s mio read fail\n", __func__);
482 return -EIO;
483 }
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530484
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 }
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700494 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530495
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700496 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
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530501 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
502 if (IS_ERR_VALUE(pllrate))
503 return pllrate;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530504
505 return
506 DIV_ROUND_CLOSEST(
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530507 DIV_ROUND_CLOSEST(pllrate, div0), div1);
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530508}
509
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700510static ulong zynqmp_clk_get_crf_crl_rate(struct zynqmp_clk_priv *priv,
511 enum zynqmp_clk id, bool two_divs)
Vipul Kumara79b5902018-03-07 14:52:44 +0530512{
513 enum zynqmp_clk pll;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700514 u32 clk_ctrl, div0, srcsel;
Vipul Kumara79b5902018-03-07 14:52:44 +0530515 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;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700528 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
Vipul Kumara79b5902018-03-07 14:52:44 +0530529
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700530 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 }
Vipul Kumara79b5902018-03-07 14:52:44 +0530567 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
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530590static 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 }
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530610 }
611 }
612
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530613 return best_rate;
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530614}
615
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530616static ulong zynqmp_clk_set_peripheral_rate(struct zynqmp_clk_priv *priv,
617 enum zynqmp_clk id, ulong rate,
618 bool two_divs)
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530619{
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530620 enum zynqmp_clk pll;
621 u32 clk_ctrl, div0 = 0, div1 = 0;
622 ulong pll_rate, new_rate;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700623 u32 reg, srcsel;
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530624 int ret;
625 u32 mask;
626
627 reg = zynqmp_clk_get_register(id);
628 ret = zynqmp_mmio_read(reg, &clk_ctrl);
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530629 if (ret) {
630 printf("%s mio read fail\n", __func__);
631 return -EIO;
632 }
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530633
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700634 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
635 pll = pll_src[PERI_CLK_SRC][srcsel];
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530636 pll_rate = zynqmp_clk_get_pll_rate(priv, pll);
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530637 if (IS_ERR_VALUE(pll_rate))
638 return pll_rate;
639
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530640 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);
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530658 if (ret) {
659 printf("%s mio write fail\n", __func__);
660 return -EIO;
661 }
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530662
663 return new_rate;
664}
665
666static 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;
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530671
672 switch (id) {
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530673 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);
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700679 case dll_ref:
680 return zynqmp_clk_get_dll_rate(priv);
681 case gem_tsu_ref:
Michal Simek6f735e42022-03-29 13:13:56 +0200682 case dp_video_ref ... dp_stc_ref:
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700683 case pl0 ... pl3:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530684 case gem0_ref ... gem3_ref:
Michal Simek0e789d22021-10-29 13:13:38 +0200685 case gem0_tx ... gem3_tx:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530686 case qspi_ref ... can1_ref:
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700687 case usb0_bus_ref ... usb3_dual_ref:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530688 two_divs = true;
689 return zynqmp_clk_get_peripheral_rate(priv, id, two_divs);
Vipul Kumara79b5902018-03-07 14:52:44 +0530690 case wdt:
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700691 case topsw_lsbus:
692 case sata_ref ... gpu_pp1_ref:
Vipul Kumara79b5902018-03-07 14:52:44 +0530693 two_divs = true;
Algapally Santosh Sagar71c5fdc2023-05-19 17:08:15 +0530694 fallthrough;
T Karthik Reddydd4c6422021-02-24 23:44:46 -0700695 case cpu_r5:
696 case dbg_fpd:
697 case ams_ref:
698 case adma_ref:
699 case lpd_lsbus:
700 case dbg_trace:
701 case dbg_tstmp:
702 case lpd_switch:
703 case topsw_main:
704 case timestamp_ref:
705 case gdma_ref ... dpdma_ref:
706 return zynqmp_clk_get_crf_crl_rate(priv, id, two_divs);
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530707 default:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530708 return -ENXIO;
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530709 }
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530710}
711
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530712static ulong zynqmp_clk_set_rate(struct clk *clk, ulong rate)
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530713{
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530714 struct zynqmp_clk_priv *priv = dev_get_priv(clk->dev);
715 enum zynqmp_clk id = clk->id;
716 bool two_divs = true;
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530717
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530718 switch (id) {
719 case gem0_ref ... gem3_ref:
Michal Simek0e789d22021-10-29 13:13:38 +0200720 case gem0_tx ... gem3_tx:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530721 case qspi_ref ... can1_ref:
Michal Simeke959ade2021-10-29 13:13:37 +0200722 case usb0_bus_ref ... usb3_dual_ref:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530723 return zynqmp_clk_set_peripheral_rate(priv, id,
724 rate, two_divs);
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530725 default:
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530726 return -ENXIO;
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530727 }
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530728}
729
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530730int soc_clk_dump(void)
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530731{
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530732 struct udevice *dev;
733 int i, ret;
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530734
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530735 ret = uclass_get_device_by_driver(UCLASS_CLK,
Simon Glass65e25be2020-12-28 20:34:56 -0700736 DM_DRIVER_GET(zynqmp_clk), &dev);
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530737 if (ret)
738 return ret;
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530739
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530740 printf("clk\t\tfrequency\n");
741 for (i = 0; i < clk_max; i++) {
742 const char *name = clk_names[i];
743 if (name) {
744 struct clk clk;
745 unsigned long rate;
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530746
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530747 clk.id = i;
748 ret = clk_request(dev, &clk);
749 if (ret < 0)
750 return ret;
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530751
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530752 rate = clk_get_rate(&clk);
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530753
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530754 clk_free(&clk);
755
756 if ((rate == (unsigned long)-ENOSYS) ||
Siva Durga Prasad Paladugu154799a2017-04-13 16:59:38 +0530757 (rate == (unsigned long)-ENXIO) ||
758 (rate == (unsigned long)-EIO))
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530759 printf("%10s%20s\n", name, "unknown");
760 else
761 printf("%10s%20lu\n", name, rate);
762 }
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530763 }
764
765 return 0;
766}
767
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530768static int zynqmp_get_freq_by_name(char *name, struct udevice *dev, ulong *freq)
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530769{
770 struct clk clk;
771 int ret;
772
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530773 ret = clk_get_by_name(dev, name, &clk);
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530774 if (ret < 0) {
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530775 dev_err(dev, "failed to get %s\n", name);
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530776 return ret;
777 }
778
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530779 *freq = clk_get_rate(&clk);
780 if (IS_ERR_VALUE(*freq)) {
781 dev_err(dev, "failed to get rate %s\n", name);
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530782 return -EINVAL;
783 }
784
785 return 0;
786}
Siva Durga Prasad Paladuguad76f8c2017-02-03 23:56:49 +0530787static int zynqmp_clk_probe(struct udevice *dev)
788{
789 int ret;
790 struct zynqmp_clk_priv *priv = dev_get_priv(dev);
791
792 debug("%s\n", __func__);
793 ret = zynqmp_get_freq_by_name("pss_ref_clk", dev, &priv->ps_clk_freq);
794 if (ret < 0)
795 return -EINVAL;
796
797 ret = zynqmp_get_freq_by_name("video_clk", dev, &priv->video_clk);
798 if (ret < 0)
799 return -EINVAL;
800
801 ret = zynqmp_get_freq_by_name("pss_alt_ref_clk", dev,
802 &priv->pss_alt_ref_clk);
803 if (ret < 0)
804 return -EINVAL;
805
806 ret = zynqmp_get_freq_by_name("aux_ref_clk", dev, &priv->aux_ref_clk);
807 if (ret < 0)
808 return -EINVAL;
809
810 ret = zynqmp_get_freq_by_name("gt_crx_ref_clk", dev,
811 &priv->gt_crx_ref_clk);
812 if (ret < 0)
813 return -EINVAL;
814
815 return 0;
816}
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530817
T Karthik Reddya72a6ae2021-02-03 03:10:45 -0700818static int zynqmp_clk_enable(struct clk *clk)
819{
820 enum zynqmp_clk id = clk->id;
821 u32 reg, clk_ctrl, clkact_shift, mask;
822 int ret;
823
824 reg = zynqmp_clk_get_register(id);
825 debug("%s, clk_id:%x, clk_base:0x%x\n", __func__, id, reg);
826
827 switch (id) {
828 case usb0_bus_ref ... usb1:
829 clkact_shift = 25;
830 mask = 0x1;
831 break;
Michal Simek0e789d22021-10-29 13:13:38 +0200832 case gem0_tx ... gem3_tx:
T Karthik Reddya72a6ae2021-02-03 03:10:45 -0700833 case gem0_ref ... gem3_ref:
834 clkact_shift = 25;
835 mask = 0x3;
836 break;
837 case qspi_ref ... can1_ref:
Michal Simek0c383a72021-07-01 19:01:42 +0200838 case lpd_lsbus:
T Karthik Reddya72a6ae2021-02-03 03:10:45 -0700839 clkact_shift = 24;
840 mask = 0x1;
841 break;
842 default:
843 return -ENXIO;
844 }
845
846 ret = zynqmp_mmio_read(reg, &clk_ctrl);
847 if (ret) {
848 printf("%s mio read fail\n", __func__);
849 return -EIO;
850 }
851
852 clk_ctrl |= (mask << clkact_shift);
853 ret = zynqmp_mmio_write(reg, mask << clkact_shift, clk_ctrl);
854 if (ret) {
855 printf("%s mio write fail\n", __func__);
856 return -EIO;
857 }
858
859 return ret;
860}
861
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530862static struct clk_ops zynqmp_clk_ops = {
863 .set_rate = zynqmp_clk_set_rate,
864 .get_rate = zynqmp_clk_get_rate,
T Karthik Reddya72a6ae2021-02-03 03:10:45 -0700865 .enable = zynqmp_clk_enable,
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530866};
867
868static const struct udevice_id zynqmp_clk_ids[] = {
Michal Simek969dd4c2018-02-21 13:59:21 +0100869 { .compatible = "xlnx,zynqmp-clk" },
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530870 { }
871};
872
873U_BOOT_DRIVER(zynqmp_clk) = {
Michal Simek6c0e59f2020-01-07 08:50:34 +0100874 .name = "zynqmp_clk",
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530875 .id = UCLASS_CLK,
876 .of_match = zynqmp_clk_ids,
877 .probe = zynqmp_clk_probe,
878 .ops = &zynqmp_clk_ops,
Simon Glass41575d82020-12-03 16:55:17 -0700879 .priv_auto = sizeof(struct zynqmp_clk_priv),
Siva Durga Prasad Paladugu128ec1f2016-11-15 16:15:41 +0530880};