blob: be0ee50e0e4fdb728d35b186011ef467f6935c71 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +05302/*
3 * ZynqMP clock driver
4 *
5 * Copyright (C) 2016 Xilinx, Inc.
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +05306 */
7
8#include <common.h>
Simon Glass0f2af882020-05-10 11:40:05 -06009#include <log.h>
Simon Glass9bc15642020-02-03 07:36:16 -070010#include <malloc.h>
11#include <dm/device_compat.h>
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +053012#include <linux/bitops.h>
13#include <clk-uclass.h>
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +053014#include <clk.h>
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +053015#include <asm/arch/sys_proto.h>
Simon Glass11c89f32017-05-17 17:18:03 -060016#include <dm.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070017#include <linux/err.h>
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +053018
Siva Durga Prasad Paladuguf0471e92017-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 Paladugu468b55f2016-11-15 16:15:41 +053021
Siva Durga Prasad Paladuguf0471e92017-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 Paladuguf0471e92017-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 Reddy97ab47d2021-02-24 23:44:46 -0700100#define CLK_CTRL_SRCSEL_MASK 0x7
Siva Durga Prasad Paladuguf0471e92017-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 Kumar488f0e72018-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 Paladuguf0471e92017-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 Reddy97ab47d2021-02-24 23:44:46 -0700133 gem0_tx, gem1_tx, gem2_tx, gem3_tx,
Michal Simek544f4482021-10-29 13:13:38 +0200134 gem0_rx, gem1_rx, gem2_rx, gem3_rx,
Siva Durga Prasad Paladuguf0471e92017-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 Simek544f4482021-10-29 13:13:38 +0200147 gem0_ref = 104,
148 gem1_ref, gem2_ref, gem3_ref,
Siva Durga Prasad Paladuguf0471e92017-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 Reddy97ab47d2021-02-24 23:44:46 -0700156 "acpu", "acpu_half", "dbg_fpd", "dbg_lpd",
Siva Durga Prasad Paladuguf0471e92017-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 Simek544f4482021-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 Paladuguf0471e92017-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 Simek544f4482021-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 Paladuguf0471e92017-02-03 23:56:49 +0530178};
179
T Karthik Reddy97ab47d2021-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 Paladuguf0471e92017-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 Paladugu468b55f2016-11-15 16:15:41 +0530221{
Siva Durga Prasad Paladuguf0471e92017-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 Reddy97ab47d2021-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 Simekacff4c82022-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 Reddy97ab47d2021-02-24 23:44:46 -0700247 case gpu_ref ... gpu_pp1_ref:
248 return CRF_APB_GPU_REF_CTRL;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530249 case ddr_ref:
250 return CRF_APB_DDR_CTRL;
T Karthik Reddy97ab47d2021-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 Paladuguf0471e92017-02-03 23:56:49 +0530267 case qspi_ref:
268 return CRL_APB_QSPI_REF_CTRL;
T Karthik Reddy2aa360e2021-02-03 03:10:45 -0700269 case usb3_dual_ref:
270 return CRL_APB_USB3_DUAL_REF_CTRL;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700271 case gem_tsu_ref:
272 return CRL_APB_GEM_TSU_REF_CTRL;
Michal Simek544f4482021-10-29 13:13:38 +0200273 case gem0_tx:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530274 case gem0_ref:
275 return CRL_APB_GEM0_REF_CTRL;
Michal Simek544f4482021-10-29 13:13:38 +0200276 case gem1_tx:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530277 case gem1_ref:
278 return CRL_APB_GEM1_REF_CTRL;
Michal Simek544f4482021-10-29 13:13:38 +0200279 case gem2_tx:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530280 case gem2_ref:
281 return CRL_APB_GEM2_REF_CTRL;
Michal Simek544f4482021-10-29 13:13:38 +0200282 case gem3_tx:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530283 case gem3_ref:
284 return CRL_APB_GEM3_REF_CTRL;
T Karthik Reddy2aa360e2021-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 Reddy97ab47d2021-02-24 23:44:46 -0700289 case cpu_r5:
290 return CRL_APB_CPU_R5_CTRL;
Siva Durga Prasad Paladuguf0471e92017-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 Reddy97ab47d2021-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 Kumarc35e5f62018-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 Paladuguf0471e92017-02-03 23:56:49 +0530333 default:
334 debug("Invalid clk id%d\n", id);
335 }
336 return 0;
337}
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530338
Siva Durga Prasad Paladuguf0471e92017-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 Kumar488f0e72018-06-27 10:44:45 +0530346 src_sel = (clk_ctrl & PLLCTRL_PRE_SRC_MASK) >>
347 PLLCTRL_PRE_SRC_SHFT;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530348 else
349 src_sel = (clk_ctrl & PLLCTRL_POST_SRC_MASK) >>
350 PLLCTRL_POST_SRC_SHFT;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530351
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530352 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 }
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530365}
366
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530367static ulong zynqmp_clk_get_pll_rate(struct zynqmp_clk_priv *priv,
368 enum zynqmp_clk id)
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530369{
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530370 u32 clk_ctrl, reset, mul;
371 ulong freq;
372 int ret;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530373
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530374 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530375 if (ret) {
376 printf("%s mio read fail\n", __func__);
377 return -EIO;
378 }
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530379
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530380 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);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530384
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530385 reset = (clk_ctrl & PLLCTRL_RESET_MASK) >> PLLCTRL_RESET_SHIFT;
386 if (reset && !(clk_ctrl & PLLCTRL_BYPASS_MASK))
387 return 0;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530388
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530389 mul = (clk_ctrl & PLLCTRL_FBDIV_MASK) >> PLLCTRL_FBDIV_SHIFT;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530390
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530391 freq *= mul;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530392
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530393 if (clk_ctrl & (1 << 16))
394 freq /= 2;
395
396 return freq;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530397}
398
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530399static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
400 enum zynqmp_clk id)
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530401{
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700402 u32 clk_ctrl, div, srcsel;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530403 enum zynqmp_clk pll;
404 int ret;
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530405 unsigned long pllrate;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530406
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530407 ret = zynqmp_mmio_read(CRF_APB_ACPU_CTRL, &clk_ctrl);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530408 if (ret) {
409 printf("%s mio read fail\n", __func__);
410 return -EIO;
411 }
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530412
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530413 div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530414
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700415 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
416 pll = pll_src[ACPU_CLK_SRC][srcsel];
Siva Durga Prasad Paladugubcfc0862017-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 Paladugu468b55f2016-11-15 16:15:41 +0530420
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530421 return DIV_ROUND_CLOSEST(pllrate, div);
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530422}
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530423
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530424static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
425{
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700426 u32 clk_ctrl, div, srcsel;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530427 enum zynqmp_clk pll;
428 int ret;
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530429 ulong pllrate;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530430
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530431 ret = zynqmp_mmio_read(CRF_APB_DDR_CTRL, &clk_ctrl);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530432 if (ret) {
433 printf("%s mio read fail\n", __func__);
434 return -EIO;
435 }
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530436
437 div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
438
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700439 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
440 pll = pll_src[DDR_CLK_SRC][srcsel];
Siva Durga Prasad Paladugubcfc0862017-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 Paladuguf0471e92017-02-03 23:56:49 +0530444
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530445 return DIV_ROUND_CLOSEST(pllrate, div);
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530446}
447
T Karthik Reddy97ab47d2021-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 Paladuguf0471e92017-02-03 23:56:49 +0530470static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv,
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700471 enum zynqmp_clk id, bool two_divs)
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530472{
473 enum zynqmp_clk pll;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700474 u32 clk_ctrl, div0, srcsel;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530475 u32 div1 = 1;
476 int ret;
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530477 ulong pllrate;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530478
479 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530480 if (ret) {
481 printf("%s mio read fail\n", __func__);
482 return -EIO;
483 }
Siva Durga Prasad Paladuguf0471e92017-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;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530493 }
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700494 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
495
496 if (id == gem_tsu_ref)
497 pll = pll_src[GEM_TSU_CLK_SRC][srcsel];
498 else
499 pll = pll_src[PERI_CLK_SRC][srcsel];
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530500
Siva Durga Prasad Paladugubcfc0862017-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 Paladuguf0471e92017-02-03 23:56:49 +0530504
505 return
506 DIV_ROUND_CLOSEST(
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530507 DIV_ROUND_CLOSEST(pllrate, div0), div1);
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530508}
509
T Karthik Reddy97ab47d2021-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 Kumarc35e5f62018-03-07 14:52:44 +0530512{
513 enum zynqmp_clk pll;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700514 u32 clk_ctrl, div0, srcsel;
Vipul Kumarc35e5f62018-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 Reddy97ab47d2021-02-24 23:44:46 -0700528 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
Vipul Kumarc35e5f62018-03-07 14:52:44 +0530529
T Karthik Reddy97ab47d2021-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 Kumarc35e5f62018-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 Paladuguf0471e92017-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;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530597
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530598 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);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530603
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530604 if (new_err < best_err) {
605 *div0 = d0;
606 *div1 = d1;
607 best_err = new_err;
608 best_rate = new_rate;
609 }
610 }
611 }
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530612
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530613 return best_rate;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530614}
615
Siva Durga Prasad Paladuguf0471e92017-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 Paladugu468b55f2016-11-15 16:15:41 +0530619{
Siva Durga Prasad Paladuguf0471e92017-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 Reddy97ab47d2021-02-24 23:44:46 -0700623 u32 reg, srcsel;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530624 int ret;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530625 u32 mask;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530626
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530627 reg = zynqmp_clk_get_register(id);
628 ret = zynqmp_mmio_read(reg, &clk_ctrl);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530629 if (ret) {
630 printf("%s mio read fail\n", __func__);
631 return -EIO;
632 }
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530633
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700634 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
635 pll = pll_src[PERI_CLK_SRC][srcsel];
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530636 pll_rate = zynqmp_clk_get_pll_rate(priv, pll);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530637 if (IS_ERR_VALUE(pll_rate))
638 return pll_rate;
639
Siva Durga Prasad Paladuguf0471e92017-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);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530651 }
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530652 clk_ctrl |= div0 << CLK_CTRL_DIV0_SHIFT;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530653
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530654 mask = (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT) |
655 (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530656
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530657 ret = zynqmp_mmio_write(reg, mask, clk_ctrl);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530658 if (ret) {
659 printf("%s mio write fail\n", __func__);
660 return -EIO;
661 }
Siva Durga Prasad Paladuguf0471e92017-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;
671
672 switch (id) {
673 case iopll ... vpll:
674 return zynqmp_clk_get_pll_rate(priv, id);
675 case acpu:
676 return zynqmp_clk_get_cpu_rate(priv, id);
677 case ddr_ref:
678 return zynqmp_clk_get_ddr_rate(priv);
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700679 case dll_ref:
680 return zynqmp_clk_get_dll_rate(priv);
681 case gem_tsu_ref:
Michal Simekacff4c82022-03-29 13:13:56 +0200682 case dp_video_ref ... dp_stc_ref:
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700683 case pl0 ... pl3:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530684 case gem0_ref ... gem3_ref:
Michal Simek544f4482021-10-29 13:13:38 +0200685 case gem0_tx ... gem3_tx:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530686 case qspi_ref ... can1_ref:
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700687 case usb0_bus_ref ... usb3_dual_ref:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530688 two_divs = true;
689 return zynqmp_clk_get_peripheral_rate(priv, id, two_divs);
Vipul Kumarc35e5f62018-03-07 14:52:44 +0530690 case wdt:
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700691 case topsw_lsbus:
692 case sata_ref ... gpu_pp1_ref:
Vipul Kumarc35e5f62018-03-07 14:52:44 +0530693 two_divs = true;
Algapally Santosh Sagar9a990932023-05-19 17:08:15 +0530694 fallthrough;
T Karthik Reddy97ab47d2021-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 Paladuguf0471e92017-02-03 23:56:49 +0530707 default:
708 return -ENXIO;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530709 }
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530710}
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530711
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530712static ulong zynqmp_clk_set_rate(struct clk *clk, ulong rate)
713{
714 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 Paladugu468b55f2016-11-15 16:15:41 +0530717
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530718 switch (id) {
719 case gem0_ref ... gem3_ref:
Michal Simek544f4482021-10-29 13:13:38 +0200720 case gem0_tx ... gem3_tx:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530721 case qspi_ref ... can1_ref:
Michal Simek66a38922021-10-29 13:13:37 +0200722 case usb0_bus_ref ... usb3_dual_ref:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530723 return zynqmp_clk_set_peripheral_rate(priv, id,
724 rate, two_divs);
725 default:
726 return -ENXIO;
727 }
728}
729
730int soc_clk_dump(void)
731{
732 struct udevice *dev;
733 int i, ret;
734
735 ret = uclass_get_device_by_driver(UCLASS_CLK,
Simon Glass65130cd2020-12-28 20:34:56 -0700736 DM_DRIVER_GET(zynqmp_clk), &dev);
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530737 if (ret)
738 return ret;
739
740 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;
746
747 clk.id = i;
748 ret = clk_request(dev, &clk);
749 if (ret < 0)
750 return ret;
751
752 rate = clk_get_rate(&clk);
753
754 clk_free(&clk);
755
756 if ((rate == (unsigned long)-ENOSYS) ||
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530757 (rate == (unsigned long)-ENXIO) ||
758 (rate == (unsigned long)-EIO))
Siva Durga Prasad Paladuguf0471e92017-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 Paladugu468b55f2016-11-15 16:15:41 +0530763 }
764
765 return 0;
766}
767
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530768static int zynqmp_get_freq_by_name(char *name, struct udevice *dev, ulong *freq)
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530769{
770 struct clk clk;
771 int ret;
772
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530773 ret = clk_get_by_name(dev, name, &clk);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530774 if (ret < 0) {
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530775 dev_err(dev, "failed to get %s\n", name);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530776 return ret;
777 }
778
Siva Durga Prasad Paladuguf0471e92017-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 Paladugu468b55f2016-11-15 16:15:41 +0530782 return -EINVAL;
783 }
784
785 return 0;
786}
Siva Durga Prasad Paladuguf0471e92017-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 Paladugu468b55f2016-11-15 16:15:41 +0530817
T Karthik Reddy2aa360e2021-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 Simek544f4482021-10-29 13:13:38 +0200832 case gem0_tx ... gem3_tx:
T Karthik Reddy2aa360e2021-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 Simek97790fb2021-07-01 19:01:42 +0200838 case lpd_lsbus:
T Karthik Reddy2aa360e2021-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 Paladugu468b55f2016-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 Reddy2aa360e2021-02-03 03:10:45 -0700865 .enable = zynqmp_clk_enable,
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530866};
867
868static const struct udevice_id zynqmp_clk_ids[] = {
Michal Simekd260ac72018-02-21 13:59:21 +0100869 { .compatible = "xlnx,zynqmp-clk" },
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530870 { }
871};
872
873U_BOOT_DRIVER(zynqmp_clk) = {
Michal Simek33093082020-01-07 08:50:34 +0100874 .name = "zynqmp_clk",
Siva Durga Prasad Paladugu468b55f2016-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 Glass8a2b47f2020-12-03 16:55:17 -0700879 .priv_auto = sizeof(struct zynqmp_clk_priv),
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530880};