blob: 1cfe0e25b1052bae2644f0aaf75d177d9c708fb0 [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>
Michal Simeka7acb532023-06-23 14:51:57 +020015#include <zynqmp_firmware.h>
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +053016#include <asm/arch/sys_proto.h>
Simon Glass11c89f32017-05-17 17:18:03 -060017#include <dm.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070018#include <linux/err.h>
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +053019
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +053020static const resource_size_t zynqmp_crf_apb_clkc_base = 0xfd1a0020;
21static const resource_size_t zynqmp_crl_apb_clkc_base = 0xff5e0020;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +053022
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +053023/* Full power domain clocks */
24#define CRF_APB_APLL_CTRL (zynqmp_crf_apb_clkc_base + 0x00)
25#define CRF_APB_DPLL_CTRL (zynqmp_crf_apb_clkc_base + 0x0c)
26#define CRF_APB_VPLL_CTRL (zynqmp_crf_apb_clkc_base + 0x18)
27#define CRF_APB_PLL_STATUS (zynqmp_crf_apb_clkc_base + 0x24)
28#define CRF_APB_APLL_TO_LPD_CTRL (zynqmp_crf_apb_clkc_base + 0x28)
29#define CRF_APB_DPLL_TO_LPD_CTRL (zynqmp_crf_apb_clkc_base + 0x2c)
30#define CRF_APB_VPLL_TO_LPD_CTRL (zynqmp_crf_apb_clkc_base + 0x30)
31/* Peripheral clocks */
32#define CRF_APB_ACPU_CTRL (zynqmp_crf_apb_clkc_base + 0x40)
33#define CRF_APB_DBG_TRACE_CTRL (zynqmp_crf_apb_clkc_base + 0x44)
34#define CRF_APB_DBG_FPD_CTRL (zynqmp_crf_apb_clkc_base + 0x48)
35#define CRF_APB_DP_VIDEO_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x50)
36#define CRF_APB_DP_AUDIO_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x54)
37#define CRF_APB_DP_STC_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x5c)
38#define CRF_APB_DDR_CTRL (zynqmp_crf_apb_clkc_base + 0x60)
39#define CRF_APB_GPU_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x64)
40#define CRF_APB_SATA_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x80)
41#define CRF_APB_PCIE_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x94)
42#define CRF_APB_GDMA_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x98)
43#define CRF_APB_DPDMA_REF_CTRL (zynqmp_crf_apb_clkc_base + 0x9c)
44#define CRF_APB_TOPSW_MAIN_CTRL (zynqmp_crf_apb_clkc_base + 0xa0)
45#define CRF_APB_TOPSW_LSBUS_CTRL (zynqmp_crf_apb_clkc_base + 0xa4)
46#define CRF_APB_GTGREF0_REF_CTRL (zynqmp_crf_apb_clkc_base + 0xa8)
47#define CRF_APB_DBG_TSTMP_CTRL (zynqmp_crf_apb_clkc_base + 0xd8)
48
49/* Low power domain clocks */
50#define CRL_APB_IOPLL_CTRL (zynqmp_crl_apb_clkc_base + 0x00)
51#define CRL_APB_RPLL_CTRL (zynqmp_crl_apb_clkc_base + 0x10)
52#define CRL_APB_PLL_STATUS (zynqmp_crl_apb_clkc_base + 0x20)
53#define CRL_APB_IOPLL_TO_FPD_CTRL (zynqmp_crl_apb_clkc_base + 0x24)
54#define CRL_APB_RPLL_TO_FPD_CTRL (zynqmp_crl_apb_clkc_base + 0x28)
55/* Peripheral clocks */
56#define CRL_APB_USB3_DUAL_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x2c)
57#define CRL_APB_GEM0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x30)
58#define CRL_APB_GEM1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x34)
59#define CRL_APB_GEM2_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x38)
60#define CRL_APB_GEM3_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x3c)
61#define CRL_APB_USB0_BUS_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x40)
62#define CRL_APB_USB1_BUS_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x44)
63#define CRL_APB_QSPI_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x48)
64#define CRL_APB_SDIO0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x4c)
65#define CRL_APB_SDIO1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x50)
66#define CRL_APB_UART0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x54)
67#define CRL_APB_UART1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x58)
68#define CRL_APB_SPI0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x5c)
69#define CRL_APB_SPI1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x60)
70#define CRL_APB_CAN0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x64)
71#define CRL_APB_CAN1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x68)
72#define CRL_APB_CPU_R5_CTRL (zynqmp_crl_apb_clkc_base + 0x70)
73#define CRL_APB_IOU_SWITCH_CTRL (zynqmp_crl_apb_clkc_base + 0x7c)
74#define CRL_APB_CSU_PLL_CTRL (zynqmp_crl_apb_clkc_base + 0x80)
75#define CRL_APB_PCAP_CTRL (zynqmp_crl_apb_clkc_base + 0x84)
76#define CRL_APB_LPD_SWITCH_CTRL (zynqmp_crl_apb_clkc_base + 0x88)
77#define CRL_APB_LPD_LSBUS_CTRL (zynqmp_crl_apb_clkc_base + 0x8c)
78#define CRL_APB_DBG_LPD_CTRL (zynqmp_crl_apb_clkc_base + 0x90)
79#define CRL_APB_NAND_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x94)
80#define CRL_APB_ADMA_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x98)
81#define CRL_APB_PL0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xa0)
82#define CRL_APB_PL1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xa4)
83#define CRL_APB_PL2_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xa8)
84#define CRL_APB_PL3_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xac)
85#define CRL_APB_PL0_THR_CNT (zynqmp_crl_apb_clkc_base + 0xb4)
86#define CRL_APB_PL1_THR_CNT (zynqmp_crl_apb_clkc_base + 0xbc)
87#define CRL_APB_PL2_THR_CNT (zynqmp_crl_apb_clkc_base + 0xc4)
88#define CRL_APB_PL3_THR_CNT (zynqmp_crl_apb_clkc_base + 0xdc)
89#define CRL_APB_GEM_TSU_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xe0)
90#define CRL_APB_DLL_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xe4)
91#define CRL_APB_AMS_REF_CTRL (zynqmp_crl_apb_clkc_base + 0xe8)
92#define CRL_APB_I2C0_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x100)
93#define CRL_APB_I2C1_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x104)
94#define CRL_APB_TIMESTAMP_REF_CTRL (zynqmp_crl_apb_clkc_base + 0x108)
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +053095
96#define ZYNQ_CLK_MAXDIV 0x3f
97#define CLK_CTRL_DIV1_SHIFT 16
98#define CLK_CTRL_DIV1_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT)
99#define CLK_CTRL_DIV0_SHIFT 8
100#define CLK_CTRL_DIV0_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT)
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700101#define CLK_CTRL_SRCSEL_MASK 0x7
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530102#define PLLCTRL_FBDIV_MASK 0x7f00
103#define PLLCTRL_FBDIV_SHIFT 8
104#define PLLCTRL_RESET_MASK 1
105#define PLLCTRL_RESET_SHIFT 0
106#define PLLCTRL_BYPASS_MASK 0x8
107#define PLLCTRL_BYPASS_SHFT 3
108#define PLLCTRL_POST_SRC_SHFT 24
109#define PLLCTRL_POST_SRC_MASK (0x7 << PLLCTRL_POST_SRC_SHFT)
Vipul Kumar488f0e72018-06-27 10:44:45 +0530110#define PLLCTRL_PRE_SRC_SHFT 20
111#define PLLCTRL_PRE_SRC_MASK (0x7 << PLLCTRL_PRE_SRC_SHFT)
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530112
113
114#define NUM_MIO_PINS 77
115
116enum zynqmp_clk {
117 iopll, rpll,
118 apll, dpll, vpll,
119 iopll_to_fpd, rpll_to_fpd, apll_to_lpd, dpll_to_lpd, vpll_to_lpd,
120 acpu, acpu_half,
121 dbg_fpd, dbg_lpd, dbg_trace, dbg_tstmp,
122 dp_video_ref, dp_audio_ref,
123 dp_stc_ref, gdma_ref, dpdma_ref,
124 ddr_ref, sata_ref, pcie_ref,
125 gpu_ref, gpu_pp0_ref, gpu_pp1_ref,
126 topsw_main, topsw_lsbus,
127 gtgref0_ref,
128 lpd_switch, lpd_lsbus,
129 usb0_bus_ref, usb1_bus_ref, usb3_dual_ref, usb0, usb1,
130 cpu_r5, cpu_r5_core,
131 csu_spb, csu_pll, pcap,
132 iou_switch,
133 gem_tsu_ref, gem_tsu,
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700134 gem0_tx, gem1_tx, gem2_tx, gem3_tx,
Michal Simek544f4482021-10-29 13:13:38 +0200135 gem0_rx, gem1_rx, gem2_rx, gem3_rx,
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530136 qspi_ref,
137 sdio0_ref, sdio1_ref,
138 uart0_ref, uart1_ref,
139 spi0_ref, spi1_ref,
140 nand_ref,
141 i2c0_ref, i2c1_ref, can0_ref, can1_ref, can0, can1,
142 dll_ref,
143 adma_ref,
144 timestamp_ref,
145 ams_ref,
146 pl0, pl1, pl2, pl3,
147 wdt,
Michal Simek544f4482021-10-29 13:13:38 +0200148 gem0_ref = 104,
149 gem1_ref, gem2_ref, gem3_ref,
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530150 clk_max,
151};
152
153static const char * const clk_names[clk_max] = {
154 "iopll", "rpll", "apll", "dpll",
155 "vpll", "iopll_to_fpd", "rpll_to_fpd",
156 "apll_to_lpd", "dpll_to_lpd", "vpll_to_lpd",
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700157 "acpu", "acpu_half", "dbg_fpd", "dbg_lpd",
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530158 "dbg_trace", "dbg_tstmp", "dp_video_ref",
159 "dp_audio_ref", "dp_stc_ref", "gdma_ref",
160 "dpdma_ref", "ddr_ref", "sata_ref", "pcie_ref",
161 "gpu_ref", "gpu_pp0_ref", "gpu_pp1_ref",
162 "topsw_main", "topsw_lsbus", "gtgref0_ref",
163 "lpd_switch", "lpd_lsbus", "usb0_bus_ref",
164 "usb1_bus_ref", "usb3_dual_ref", "usb0",
165 "usb1", "cpu_r5", "cpu_r5_core", "csu_spb",
166 "csu_pll", "pcap", "iou_switch", "gem_tsu_ref",
Michal Simek544f4482021-10-29 13:13:38 +0200167 "gem_tsu", "gem0_tx", "gem1_tx", "gem2_tx",
168 "gem3_tx", "gem0_rx", "gem1_rx", "gem2_rx",
169 "gem3_rx", "qspi_ref", "sdio0_ref", "sdio1_ref",
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530170 "uart0_ref", "uart1_ref", "spi0_ref",
171 "spi1_ref", "nand_ref", "i2c0_ref", "i2c1_ref",
172 "can0_ref", "can1_ref", "can0", "can1",
173 "dll_ref", "adma_ref", "timestamp_ref",
Michal Simek544f4482021-10-29 13:13:38 +0200174 "ams_ref", "pl0", "pl1", "pl2", "pl3", "wdt",
175 NULL, NULL, NULL, NULL,
176 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
177 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
178 NULL, NULL, NULL, NULL, "gem0_ref", "gem1_ref", "gem2_ref", "gem3_ref",
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530179};
180
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700181static const u32 pll_src[][4] = {
182 {apll, 0xff, dpll, vpll}, /* acpu */
183 {dpll, vpll, 0xff, 0xff}, /* ddr_ref */
184 {rpll, iopll, 0xff, 0xff}, /* dll_ref */
185 {iopll, 0xff, rpll, dpll_to_lpd}, /* gem_tsu_ref */
186 {iopll, 0xff, rpll, dpll}, /* peripheral */
187 {apll, 0xff, iopll_to_fpd, dpll}, /* wdt */
188 {iopll_to_fpd, 0xff, dpll, apll}, /* dbg_fpd */
189 {iopll, 0xff, rpll, dpll_to_lpd}, /* timestamp_ref */
190 {iopll_to_fpd, 0xff, apll, dpll}, /* sata_ref */
191 {iopll_to_fpd, 0xff, rpll_to_fpd, dpll},/* pcie_ref */
192 {iopll_to_fpd, 0xff, vpll, dpll}, /* gpu_ref */
193 {apll, 0xff, vpll, dpll}, /* topsw_main_ref */
194 {rpll, 0xff, iopll, dpll_to_lpd}, /* cpu_r5_ref */
195};
196
197enum zynqmp_clk_pll_src {
198 ACPU_CLK_SRC = 0,
199 DDR_CLK_SRC,
200 DLL_CLK_SRC,
201 GEM_TSU_CLK_SRC,
202 PERI_CLK_SRC,
203 WDT_CLK_SRC,
204 DBG_FPD_CLK_SRC,
205 TIMESTAMP_CLK_SRC,
206 SATA_CLK_SRC,
207 PCIE_CLK_SRC,
208 GPU_CLK_SRC,
209 TOPSW_MAIN_CLK_SRC,
210 CPU_R5_CLK_SRC
211};
212
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530213struct zynqmp_clk_priv {
214 unsigned long ps_clk_freq;
215 unsigned long video_clk;
216 unsigned long pss_alt_ref_clk;
217 unsigned long gt_crx_ref_clk;
218 unsigned long aux_ref_clk;
219};
220
221static u32 zynqmp_clk_get_register(enum zynqmp_clk id)
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530222{
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530223 switch (id) {
224 case iopll:
225 return CRL_APB_IOPLL_CTRL;
226 case rpll:
227 return CRL_APB_RPLL_CTRL;
228 case apll:
229 return CRF_APB_APLL_CTRL;
230 case dpll:
231 return CRF_APB_DPLL_CTRL;
232 case vpll:
233 return CRF_APB_VPLL_CTRL;
234 case acpu:
235 return CRF_APB_ACPU_CTRL;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700236 case dbg_fpd:
237 return CRF_APB_DBG_FPD_CTRL;
238 case dbg_trace:
239 return CRF_APB_DBG_TRACE_CTRL;
240 case dbg_tstmp:
241 return CRF_APB_DBG_TSTMP_CTRL;
Michal Simekacff4c82022-03-29 13:13:56 +0200242 case dp_video_ref:
243 return CRF_APB_DP_VIDEO_REF_CTRL;
244 case dp_audio_ref:
245 return CRF_APB_DP_AUDIO_REF_CTRL;
246 case dp_stc_ref:
247 return CRF_APB_DP_STC_REF_CTRL;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700248 case gpu_ref ... gpu_pp1_ref:
249 return CRF_APB_GPU_REF_CTRL;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530250 case ddr_ref:
251 return CRF_APB_DDR_CTRL;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700252 case sata_ref:
253 return CRF_APB_SATA_REF_CTRL;
254 case pcie_ref:
255 return CRF_APB_PCIE_REF_CTRL;
256 case gdma_ref:
257 return CRF_APB_GDMA_REF_CTRL;
258 case dpdma_ref:
259 return CRF_APB_DPDMA_REF_CTRL;
260 case topsw_main:
261 return CRF_APB_TOPSW_MAIN_CTRL;
262 case topsw_lsbus:
263 return CRF_APB_TOPSW_LSBUS_CTRL;
264 case lpd_switch:
265 return CRL_APB_LPD_SWITCH_CTRL;
266 case lpd_lsbus:
267 return CRL_APB_LPD_LSBUS_CTRL;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530268 case qspi_ref:
269 return CRL_APB_QSPI_REF_CTRL;
T Karthik Reddy2aa360e2021-02-03 03:10:45 -0700270 case usb3_dual_ref:
271 return CRL_APB_USB3_DUAL_REF_CTRL;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700272 case gem_tsu_ref:
Ashok Reddy Soma0a08f442023-07-20 01:28:59 -0600273 case gem_tsu:
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700274 return CRL_APB_GEM_TSU_REF_CTRL;
Michal Simek544f4482021-10-29 13:13:38 +0200275 case gem0_tx:
Ashok Reddy Soma0a08f442023-07-20 01:28:59 -0600276 case gem0_rx:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530277 case gem0_ref:
278 return CRL_APB_GEM0_REF_CTRL;
Michal Simek544f4482021-10-29 13:13:38 +0200279 case gem1_tx:
Ashok Reddy Soma0a08f442023-07-20 01:28:59 -0600280 case gem1_rx:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530281 case gem1_ref:
282 return CRL_APB_GEM1_REF_CTRL;
Michal Simek544f4482021-10-29 13:13:38 +0200283 case gem2_tx:
Ashok Reddy Soma0a08f442023-07-20 01:28:59 -0600284 case gem2_rx:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530285 case gem2_ref:
286 return CRL_APB_GEM2_REF_CTRL;
Michal Simek544f4482021-10-29 13:13:38 +0200287 case gem3_tx:
Ashok Reddy Soma0a08f442023-07-20 01:28:59 -0600288 case gem3_rx:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530289 case gem3_ref:
290 return CRL_APB_GEM3_REF_CTRL;
T Karthik Reddy2aa360e2021-02-03 03:10:45 -0700291 case usb0_bus_ref:
292 return CRL_APB_USB0_BUS_REF_CTRL;
293 case usb1_bus_ref:
294 return CRL_APB_USB1_BUS_REF_CTRL;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700295 case cpu_r5:
296 return CRL_APB_CPU_R5_CTRL;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530297 case uart0_ref:
298 return CRL_APB_UART0_REF_CTRL;
299 case uart1_ref:
300 return CRL_APB_UART1_REF_CTRL;
301 case sdio0_ref:
302 return CRL_APB_SDIO0_REF_CTRL;
303 case sdio1_ref:
304 return CRL_APB_SDIO1_REF_CTRL;
305 case spi0_ref:
306 return CRL_APB_SPI0_REF_CTRL;
307 case spi1_ref:
308 return CRL_APB_SPI1_REF_CTRL;
309 case nand_ref:
310 return CRL_APB_NAND_REF_CTRL;
311 case i2c0_ref:
312 return CRL_APB_I2C0_REF_CTRL;
313 case i2c1_ref:
314 return CRL_APB_I2C1_REF_CTRL;
315 case can0_ref:
316 return CRL_APB_CAN0_REF_CTRL;
317 case can1_ref:
318 return CRL_APB_CAN1_REF_CTRL;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700319 case dll_ref:
320 return CRL_APB_DLL_REF_CTRL;
321 case adma_ref:
322 return CRL_APB_ADMA_REF_CTRL;
323 case timestamp_ref:
324 return CRL_APB_TIMESTAMP_REF_CTRL;
325 case ams_ref:
326 return CRL_APB_AMS_REF_CTRL;
Vipul Kumarc35e5f62018-03-07 14:52:44 +0530327 case pl0:
328 return CRL_APB_PL0_REF_CTRL;
329 case pl1:
330 return CRL_APB_PL1_REF_CTRL;
331 case pl2:
332 return CRL_APB_PL2_REF_CTRL;
333 case pl3:
334 return CRL_APB_PL3_REF_CTRL;
335 case wdt:
336 return CRF_APB_TOPSW_LSBUS_CTRL;
337 case iopll_to_fpd:
338 return CRL_APB_IOPLL_TO_FPD_CTRL;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530339 default:
340 debug("Invalid clk id%d\n", id);
341 }
342 return 0;
343}
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530344
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530345static ulong zynqmp_clk_get_pll_src(ulong clk_ctrl,
346 struct zynqmp_clk_priv *priv,
347 bool is_pre_src)
348{
349 u32 src_sel;
350
351 if (is_pre_src)
Vipul Kumar488f0e72018-06-27 10:44:45 +0530352 src_sel = (clk_ctrl & PLLCTRL_PRE_SRC_MASK) >>
353 PLLCTRL_PRE_SRC_SHFT;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530354 else
355 src_sel = (clk_ctrl & PLLCTRL_POST_SRC_MASK) >>
356 PLLCTRL_POST_SRC_SHFT;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530357
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530358 switch (src_sel) {
359 case 4:
360 return priv->video_clk;
361 case 5:
362 return priv->pss_alt_ref_clk;
363 case 6:
364 return priv->aux_ref_clk;
365 case 7:
366 return priv->gt_crx_ref_clk;
367 case 0 ... 3:
368 default:
369 return priv->ps_clk_freq;
370 }
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530371}
372
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530373static ulong zynqmp_clk_get_pll_rate(struct zynqmp_clk_priv *priv,
374 enum zynqmp_clk id)
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530375{
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530376 u32 clk_ctrl, reset, mul;
377 ulong freq;
378 int ret;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530379
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530380 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530381 if (ret) {
382 printf("%s mio read fail\n", __func__);
383 return -EIO;
384 }
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530385
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530386 if (clk_ctrl & PLLCTRL_BYPASS_MASK)
387 freq = zynqmp_clk_get_pll_src(clk_ctrl, priv, 0);
388 else
389 freq = zynqmp_clk_get_pll_src(clk_ctrl, priv, 1);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530390
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530391 reset = (clk_ctrl & PLLCTRL_RESET_MASK) >> PLLCTRL_RESET_SHIFT;
392 if (reset && !(clk_ctrl & PLLCTRL_BYPASS_MASK))
393 return 0;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530394
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530395 mul = (clk_ctrl & PLLCTRL_FBDIV_MASK) >> PLLCTRL_FBDIV_SHIFT;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530396
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530397 freq *= mul;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530398
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530399 if (clk_ctrl & (1 << 16))
400 freq /= 2;
401
402 return freq;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530403}
404
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530405static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
406 enum zynqmp_clk id)
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530407{
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700408 u32 clk_ctrl, div, srcsel;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530409 enum zynqmp_clk pll;
410 int ret;
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530411 unsigned long pllrate;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530412
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530413 ret = zynqmp_mmio_read(CRF_APB_ACPU_CTRL, &clk_ctrl);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530414 if (ret) {
415 printf("%s mio read fail\n", __func__);
416 return -EIO;
417 }
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530418
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530419 div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530420
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700421 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
422 pll = pll_src[ACPU_CLK_SRC][srcsel];
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530423 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
424 if (IS_ERR_VALUE(pllrate))
425 return pllrate;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530426
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530427 return DIV_ROUND_CLOSEST(pllrate, div);
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530428}
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530429
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530430static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
431{
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700432 u32 clk_ctrl, div, srcsel;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530433 enum zynqmp_clk pll;
434 int ret;
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530435 ulong pllrate;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530436
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530437 ret = zynqmp_mmio_read(CRF_APB_DDR_CTRL, &clk_ctrl);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530438 if (ret) {
439 printf("%s mio read fail\n", __func__);
440 return -EIO;
441 }
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530442
443 div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
444
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700445 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
446 pll = pll_src[DDR_CLK_SRC][srcsel];
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530447 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
448 if (IS_ERR_VALUE(pllrate))
449 return pllrate;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530450
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530451 return DIV_ROUND_CLOSEST(pllrate, div);
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530452}
453
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700454static ulong zynqmp_clk_get_dll_rate(struct zynqmp_clk_priv *priv)
455{
456 u32 clk_ctrl, srcsel;
457 enum zynqmp_clk pll;
458 ulong pllrate;
459 int ret;
460
461 ret = zynqmp_mmio_read(CRL_APB_DLL_REF_CTRL, &clk_ctrl);
462 if (ret) {
463 printf("%s mio read fail\n", __func__);
464 return -EIO;
465 }
466
467 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
468 pll = pll_src[DLL_CLK_SRC][srcsel];
469 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
470 if (IS_ERR_VALUE(pllrate))
471 return pllrate;
472
473 return pllrate;
474}
475
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530476static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv,
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700477 enum zynqmp_clk id, bool two_divs)
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530478{
479 enum zynqmp_clk pll;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700480 u32 clk_ctrl, div0, srcsel;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530481 u32 div1 = 1;
482 int ret;
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530483 ulong pllrate;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530484
485 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530486 if (ret) {
487 printf("%s mio read fail\n", __func__);
488 return -EIO;
489 }
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530490
491 div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
492 if (!div0)
493 div0 = 1;
494
495 if (two_divs) {
496 div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
497 if (!div1)
498 div1 = 1;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530499 }
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700500 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
501
502 if (id == gem_tsu_ref)
503 pll = pll_src[GEM_TSU_CLK_SRC][srcsel];
504 else
505 pll = pll_src[PERI_CLK_SRC][srcsel];
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530506
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530507 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
508 if (IS_ERR_VALUE(pllrate))
509 return pllrate;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530510
511 return
512 DIV_ROUND_CLOSEST(
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530513 DIV_ROUND_CLOSEST(pllrate, div0), div1);
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530514}
515
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700516static ulong zynqmp_clk_get_crf_crl_rate(struct zynqmp_clk_priv *priv,
517 enum zynqmp_clk id, bool two_divs)
Vipul Kumarc35e5f62018-03-07 14:52:44 +0530518{
519 enum zynqmp_clk pll;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700520 u32 clk_ctrl, div0, srcsel;
Vipul Kumarc35e5f62018-03-07 14:52:44 +0530521 u32 div1 = 1;
522 int ret;
523 ulong pllrate;
524
525 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
526 if (ret) {
527 printf("%d %s mio read fail\n", __LINE__, __func__);
528 return -EIO;
529 }
530
531 div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
532 if (!div0)
533 div0 = 1;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700534 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
Vipul Kumarc35e5f62018-03-07 14:52:44 +0530535
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700536 switch (id) {
537 case wdt:
538 case dbg_trace:
539 case topsw_lsbus:
540 pll = pll_src[WDT_CLK_SRC][srcsel];
541 break;
542 case dbg_fpd:
543 case dbg_tstmp:
544 pll = pll_src[DBG_FPD_CLK_SRC][srcsel];
545 break;
546 case timestamp_ref:
547 pll = pll_src[TIMESTAMP_CLK_SRC][srcsel];
548 break;
549 case sata_ref:
550 pll = pll_src[SATA_CLK_SRC][srcsel];
551 break;
552 case pcie_ref:
553 pll = pll_src[PCIE_CLK_SRC][srcsel];
554 break;
555 case gpu_ref ... gpu_pp1_ref:
556 pll = pll_src[GPU_CLK_SRC][srcsel];
557 break;
558 case gdma_ref:
559 case dpdma_ref:
560 case topsw_main:
561 pll = pll_src[TOPSW_MAIN_CLK_SRC][srcsel];
562 break;
563 case cpu_r5:
564 case ams_ref:
565 case adma_ref:
566 case lpd_lsbus:
567 case lpd_switch:
568 pll = pll_src[CPU_R5_CLK_SRC][srcsel];
569 break;
570 default:
571 return -ENXIO;
572 }
Vipul Kumarc35e5f62018-03-07 14:52:44 +0530573 if (two_divs) {
574 ret = zynqmp_mmio_read(zynqmp_clk_get_register(pll), &clk_ctrl);
575 if (ret) {
576 printf("%d %s mio read fail\n", __LINE__, __func__);
577 return -EIO;
578 }
579 div1 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
580 if (!div1)
581 div1 = 1;
582 }
583
584 if (pll == iopll_to_fpd)
585 pll = iopll;
586
587 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
588 if (IS_ERR_VALUE(pllrate))
589 return pllrate;
590
591 return
592 DIV_ROUND_CLOSEST(
593 DIV_ROUND_CLOSEST(pllrate, div0), div1);
594}
595
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530596static unsigned long zynqmp_clk_calc_peripheral_two_divs(ulong rate,
597 ulong pll_rate,
598 u32 *div0, u32 *div1)
599{
600 long new_err, best_err = (long)(~0UL >> 1);
601 ulong new_rate, best_rate = 0;
602 u32 d0, d1;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530603
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530604 for (d0 = 1; d0 <= ZYNQ_CLK_MAXDIV; d0++) {
605 for (d1 = 1; d1 <= ZYNQ_CLK_MAXDIV >> 1; d1++) {
606 new_rate = DIV_ROUND_CLOSEST(
607 DIV_ROUND_CLOSEST(pll_rate, d0), d1);
608 new_err = abs(new_rate - rate);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530609
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530610 if (new_err < best_err) {
611 *div0 = d0;
612 *div1 = d1;
613 best_err = new_err;
614 best_rate = new_rate;
615 }
616 }
617 }
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530618
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530619 return best_rate;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530620}
621
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530622static ulong zynqmp_clk_set_peripheral_rate(struct zynqmp_clk_priv *priv,
623 enum zynqmp_clk id, ulong rate,
624 bool two_divs)
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530625{
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530626 enum zynqmp_clk pll;
627 u32 clk_ctrl, div0 = 0, div1 = 0;
628 ulong pll_rate, new_rate;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700629 u32 reg, srcsel;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530630 int ret;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530631 u32 mask;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530632
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530633 reg = zynqmp_clk_get_register(id);
634 ret = zynqmp_mmio_read(reg, &clk_ctrl);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530635 if (ret) {
636 printf("%s mio read fail\n", __func__);
637 return -EIO;
638 }
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530639
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700640 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
641 pll = pll_src[PERI_CLK_SRC][srcsel];
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530642 pll_rate = zynqmp_clk_get_pll_rate(priv, pll);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530643 if (IS_ERR_VALUE(pll_rate))
644 return pll_rate;
645
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530646 clk_ctrl &= ~CLK_CTRL_DIV0_MASK;
647 if (two_divs) {
648 clk_ctrl &= ~CLK_CTRL_DIV1_MASK;
649 new_rate = zynqmp_clk_calc_peripheral_two_divs(rate, pll_rate,
650 &div0, &div1);
651 clk_ctrl |= div1 << CLK_CTRL_DIV1_SHIFT;
652 } else {
653 div0 = DIV_ROUND_CLOSEST(pll_rate, rate);
654 if (div0 > ZYNQ_CLK_MAXDIV)
655 div0 = ZYNQ_CLK_MAXDIV;
656 new_rate = DIV_ROUND_CLOSEST(rate, div0);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530657 }
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530658 clk_ctrl |= div0 << CLK_CTRL_DIV0_SHIFT;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530659
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530660 mask = (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT) |
661 (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530662
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530663 ret = zynqmp_mmio_write(reg, mask, clk_ctrl);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530664 if (ret) {
665 printf("%s mio write fail\n", __func__);
666 return -EIO;
667 }
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530668
669 return new_rate;
670}
671
672static ulong zynqmp_clk_get_rate(struct clk *clk)
673{
674 struct zynqmp_clk_priv *priv = dev_get_priv(clk->dev);
675 enum zynqmp_clk id = clk->id;
676 bool two_divs = false;
677
678 switch (id) {
679 case iopll ... vpll:
680 return zynqmp_clk_get_pll_rate(priv, id);
681 case acpu:
682 return zynqmp_clk_get_cpu_rate(priv, id);
683 case ddr_ref:
684 return zynqmp_clk_get_ddr_rate(priv);
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700685 case dll_ref:
686 return zynqmp_clk_get_dll_rate(priv);
687 case gem_tsu_ref:
Michal Simekacff4c82022-03-29 13:13:56 +0200688 case dp_video_ref ... dp_stc_ref:
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700689 case pl0 ... pl3:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530690 case gem0_ref ... gem3_ref:
Michal Simek544f4482021-10-29 13:13:38 +0200691 case gem0_tx ... gem3_tx:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530692 case qspi_ref ... can1_ref:
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700693 case usb0_bus_ref ... usb3_dual_ref:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530694 two_divs = true;
695 return zynqmp_clk_get_peripheral_rate(priv, id, two_divs);
Vipul Kumarc35e5f62018-03-07 14:52:44 +0530696 case wdt:
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700697 case topsw_lsbus:
698 case sata_ref ... gpu_pp1_ref:
Vipul Kumarc35e5f62018-03-07 14:52:44 +0530699 two_divs = true;
Algapally Santosh Sagar9a990932023-05-19 17:08:15 +0530700 fallthrough;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700701 case cpu_r5:
702 case dbg_fpd:
703 case ams_ref:
704 case adma_ref:
705 case lpd_lsbus:
706 case dbg_trace:
707 case dbg_tstmp:
708 case lpd_switch:
709 case topsw_main:
710 case timestamp_ref:
711 case gdma_ref ... dpdma_ref:
712 return zynqmp_clk_get_crf_crl_rate(priv, id, two_divs);
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530713 default:
714 return -ENXIO;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530715 }
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530716}
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530717
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530718static ulong zynqmp_clk_set_rate(struct clk *clk, ulong rate)
719{
720 struct zynqmp_clk_priv *priv = dev_get_priv(clk->dev);
721 enum zynqmp_clk id = clk->id;
722 bool two_divs = true;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530723
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530724 switch (id) {
725 case gem0_ref ... gem3_ref:
Michal Simek544f4482021-10-29 13:13:38 +0200726 case gem0_tx ... gem3_tx:
Ashok Reddy Soma025964b2023-07-19 02:49:12 -0600727 case gem0_rx ... gem3_rx:
728 case gem_tsu:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530729 case qspi_ref ... can1_ref:
Michal Simek66a38922021-10-29 13:13:37 +0200730 case usb0_bus_ref ... usb3_dual_ref:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530731 return zynqmp_clk_set_peripheral_rate(priv, id,
732 rate, two_divs);
733 default:
734 return -ENXIO;
735 }
736}
737
738int soc_clk_dump(void)
739{
740 struct udevice *dev;
741 int i, ret;
742
743 ret = uclass_get_device_by_driver(UCLASS_CLK,
Simon Glass65130cd2020-12-28 20:34:56 -0700744 DM_DRIVER_GET(zynqmp_clk), &dev);
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530745 if (ret)
746 return ret;
747
748 printf("clk\t\tfrequency\n");
749 for (i = 0; i < clk_max; i++) {
750 const char *name = clk_names[i];
751 if (name) {
752 struct clk clk;
753 unsigned long rate;
754
755 clk.id = i;
756 ret = clk_request(dev, &clk);
757 if (ret < 0)
758 return ret;
759
760 rate = clk_get_rate(&clk);
761
762 clk_free(&clk);
763
764 if ((rate == (unsigned long)-ENOSYS) ||
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530765 (rate == (unsigned long)-ENXIO) ||
766 (rate == (unsigned long)-EIO))
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530767 printf("%10s%20s\n", name, "unknown");
768 else
769 printf("%10s%20lu\n", name, rate);
770 }
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530771 }
772
773 return 0;
774}
775
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530776static int zynqmp_get_freq_by_name(char *name, struct udevice *dev, ulong *freq)
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530777{
778 struct clk clk;
779 int ret;
780
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530781 ret = clk_get_by_name(dev, name, &clk);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530782 if (ret < 0) {
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530783 dev_err(dev, "failed to get %s\n", name);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530784 return ret;
785 }
786
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530787 *freq = clk_get_rate(&clk);
788 if (IS_ERR_VALUE(*freq)) {
789 dev_err(dev, "failed to get rate %s\n", name);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530790 return -EINVAL;
791 }
792
793 return 0;
794}
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530795static int zynqmp_clk_probe(struct udevice *dev)
796{
797 int ret;
798 struct zynqmp_clk_priv *priv = dev_get_priv(dev);
799
800 debug("%s\n", __func__);
801 ret = zynqmp_get_freq_by_name("pss_ref_clk", dev, &priv->ps_clk_freq);
802 if (ret < 0)
803 return -EINVAL;
804
805 ret = zynqmp_get_freq_by_name("video_clk", dev, &priv->video_clk);
806 if (ret < 0)
807 return -EINVAL;
808
809 ret = zynqmp_get_freq_by_name("pss_alt_ref_clk", dev,
810 &priv->pss_alt_ref_clk);
811 if (ret < 0)
812 return -EINVAL;
813
814 ret = zynqmp_get_freq_by_name("aux_ref_clk", dev, &priv->aux_ref_clk);
815 if (ret < 0)
816 return -EINVAL;
817
818 ret = zynqmp_get_freq_by_name("gt_crx_ref_clk", dev,
819 &priv->gt_crx_ref_clk);
820 if (ret < 0)
821 return -EINVAL;
822
823 return 0;
824}
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530825
T Karthik Reddy2aa360e2021-02-03 03:10:45 -0700826static int zynqmp_clk_enable(struct clk *clk)
827{
828 enum zynqmp_clk id = clk->id;
829 u32 reg, clk_ctrl, clkact_shift, mask;
830 int ret;
831
832 reg = zynqmp_clk_get_register(id);
833 debug("%s, clk_id:%x, clk_base:0x%x\n", __func__, id, reg);
834
835 switch (id) {
836 case usb0_bus_ref ... usb1:
837 clkact_shift = 25;
838 mask = 0x1;
839 break;
Michal Simek544f4482021-10-29 13:13:38 +0200840 case gem0_tx ... gem3_tx:
T Karthik Reddy2aa360e2021-02-03 03:10:45 -0700841 case gem0_ref ... gem3_ref:
842 clkact_shift = 25;
843 mask = 0x3;
844 break;
845 case qspi_ref ... can1_ref:
Michal Simek97790fb2021-07-01 19:01:42 +0200846 case lpd_lsbus:
T Karthik Reddy2aa360e2021-02-03 03:10:45 -0700847 clkact_shift = 24;
848 mask = 0x1;
849 break;
850 default:
851 return -ENXIO;
852 }
853
854 ret = zynqmp_mmio_read(reg, &clk_ctrl);
855 if (ret) {
856 printf("%s mio read fail\n", __func__);
857 return -EIO;
858 }
859
860 clk_ctrl |= (mask << clkact_shift);
861 ret = zynqmp_mmio_write(reg, mask << clkact_shift, clk_ctrl);
862 if (ret) {
863 printf("%s mio write fail\n", __func__);
864 return -EIO;
865 }
866
867 return ret;
868}
869
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530870static struct clk_ops zynqmp_clk_ops = {
871 .set_rate = zynqmp_clk_set_rate,
872 .get_rate = zynqmp_clk_get_rate,
T Karthik Reddy2aa360e2021-02-03 03:10:45 -0700873 .enable = zynqmp_clk_enable,
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530874};
875
876static const struct udevice_id zynqmp_clk_ids[] = {
Michal Simekd260ac72018-02-21 13:59:21 +0100877 { .compatible = "xlnx,zynqmp-clk" },
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530878 { }
879};
880
881U_BOOT_DRIVER(zynqmp_clk) = {
Michal Simek33093082020-01-07 08:50:34 +0100882 .name = "zynqmp_clk",
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530883 .id = UCLASS_CLK,
884 .of_match = zynqmp_clk_ids,
885 .probe = zynqmp_clk_probe,
886 .ops = &zynqmp_clk_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700887 .priv_auto = sizeof(struct zynqmp_clk_priv),
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530888};