blob: 8320d4918462403c0ff57a46c447cdf41a516fa2 [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:
273 return CRL_APB_GEM_TSU_REF_CTRL;
Michal Simek544f4482021-10-29 13:13:38 +0200274 case gem0_tx:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530275 case gem0_ref:
276 return CRL_APB_GEM0_REF_CTRL;
Michal Simek544f4482021-10-29 13:13:38 +0200277 case gem1_tx:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530278 case gem1_ref:
279 return CRL_APB_GEM1_REF_CTRL;
Michal Simek544f4482021-10-29 13:13:38 +0200280 case gem2_tx:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530281 case gem2_ref:
282 return CRL_APB_GEM2_REF_CTRL;
Michal Simek544f4482021-10-29 13:13:38 +0200283 case gem3_tx:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530284 case gem3_ref:
285 return CRL_APB_GEM3_REF_CTRL;
T Karthik Reddy2aa360e2021-02-03 03:10:45 -0700286 case usb0_bus_ref:
287 return CRL_APB_USB0_BUS_REF_CTRL;
288 case usb1_bus_ref:
289 return CRL_APB_USB1_BUS_REF_CTRL;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700290 case cpu_r5:
291 return CRL_APB_CPU_R5_CTRL;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530292 case uart0_ref:
293 return CRL_APB_UART0_REF_CTRL;
294 case uart1_ref:
295 return CRL_APB_UART1_REF_CTRL;
296 case sdio0_ref:
297 return CRL_APB_SDIO0_REF_CTRL;
298 case sdio1_ref:
299 return CRL_APB_SDIO1_REF_CTRL;
300 case spi0_ref:
301 return CRL_APB_SPI0_REF_CTRL;
302 case spi1_ref:
303 return CRL_APB_SPI1_REF_CTRL;
304 case nand_ref:
305 return CRL_APB_NAND_REF_CTRL;
306 case i2c0_ref:
307 return CRL_APB_I2C0_REF_CTRL;
308 case i2c1_ref:
309 return CRL_APB_I2C1_REF_CTRL;
310 case can0_ref:
311 return CRL_APB_CAN0_REF_CTRL;
312 case can1_ref:
313 return CRL_APB_CAN1_REF_CTRL;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700314 case dll_ref:
315 return CRL_APB_DLL_REF_CTRL;
316 case adma_ref:
317 return CRL_APB_ADMA_REF_CTRL;
318 case timestamp_ref:
319 return CRL_APB_TIMESTAMP_REF_CTRL;
320 case ams_ref:
321 return CRL_APB_AMS_REF_CTRL;
Vipul Kumarc35e5f62018-03-07 14:52:44 +0530322 case pl0:
323 return CRL_APB_PL0_REF_CTRL;
324 case pl1:
325 return CRL_APB_PL1_REF_CTRL;
326 case pl2:
327 return CRL_APB_PL2_REF_CTRL;
328 case pl3:
329 return CRL_APB_PL3_REF_CTRL;
330 case wdt:
331 return CRF_APB_TOPSW_LSBUS_CTRL;
332 case iopll_to_fpd:
333 return CRL_APB_IOPLL_TO_FPD_CTRL;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530334 default:
335 debug("Invalid clk id%d\n", id);
336 }
337 return 0;
338}
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530339
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530340static ulong zynqmp_clk_get_pll_src(ulong clk_ctrl,
341 struct zynqmp_clk_priv *priv,
342 bool is_pre_src)
343{
344 u32 src_sel;
345
346 if (is_pre_src)
Vipul Kumar488f0e72018-06-27 10:44:45 +0530347 src_sel = (clk_ctrl & PLLCTRL_PRE_SRC_MASK) >>
348 PLLCTRL_PRE_SRC_SHFT;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530349 else
350 src_sel = (clk_ctrl & PLLCTRL_POST_SRC_MASK) >>
351 PLLCTRL_POST_SRC_SHFT;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530352
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530353 switch (src_sel) {
354 case 4:
355 return priv->video_clk;
356 case 5:
357 return priv->pss_alt_ref_clk;
358 case 6:
359 return priv->aux_ref_clk;
360 case 7:
361 return priv->gt_crx_ref_clk;
362 case 0 ... 3:
363 default:
364 return priv->ps_clk_freq;
365 }
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530366}
367
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530368static ulong zynqmp_clk_get_pll_rate(struct zynqmp_clk_priv *priv,
369 enum zynqmp_clk id)
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530370{
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530371 u32 clk_ctrl, reset, mul;
372 ulong freq;
373 int ret;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530374
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530375 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530376 if (ret) {
377 printf("%s mio read fail\n", __func__);
378 return -EIO;
379 }
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530380
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530381 if (clk_ctrl & PLLCTRL_BYPASS_MASK)
382 freq = zynqmp_clk_get_pll_src(clk_ctrl, priv, 0);
383 else
384 freq = zynqmp_clk_get_pll_src(clk_ctrl, priv, 1);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530385
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530386 reset = (clk_ctrl & PLLCTRL_RESET_MASK) >> PLLCTRL_RESET_SHIFT;
387 if (reset && !(clk_ctrl & PLLCTRL_BYPASS_MASK))
388 return 0;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530389
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530390 mul = (clk_ctrl & PLLCTRL_FBDIV_MASK) >> PLLCTRL_FBDIV_SHIFT;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530391
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530392 freq *= mul;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530393
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530394 if (clk_ctrl & (1 << 16))
395 freq /= 2;
396
397 return freq;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530398}
399
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530400static ulong zynqmp_clk_get_cpu_rate(struct zynqmp_clk_priv *priv,
401 enum zynqmp_clk id)
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530402{
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700403 u32 clk_ctrl, div, srcsel;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530404 enum zynqmp_clk pll;
405 int ret;
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530406 unsigned long pllrate;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530407
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530408 ret = zynqmp_mmio_read(CRF_APB_ACPU_CTRL, &clk_ctrl);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530409 if (ret) {
410 printf("%s mio read fail\n", __func__);
411 return -EIO;
412 }
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530413
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530414 div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530415
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700416 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
417 pll = pll_src[ACPU_CLK_SRC][srcsel];
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530418 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
419 if (IS_ERR_VALUE(pllrate))
420 return pllrate;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530421
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530422 return DIV_ROUND_CLOSEST(pllrate, div);
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530423}
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530424
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530425static ulong zynqmp_clk_get_ddr_rate(struct zynqmp_clk_priv *priv)
426{
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700427 u32 clk_ctrl, div, srcsel;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530428 enum zynqmp_clk pll;
429 int ret;
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530430 ulong pllrate;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530431
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530432 ret = zynqmp_mmio_read(CRF_APB_DDR_CTRL, &clk_ctrl);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530433 if (ret) {
434 printf("%s mio read fail\n", __func__);
435 return -EIO;
436 }
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530437
438 div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
439
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700440 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
441 pll = pll_src[DDR_CLK_SRC][srcsel];
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530442 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
443 if (IS_ERR_VALUE(pllrate))
444 return pllrate;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530445
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530446 return DIV_ROUND_CLOSEST(pllrate, div);
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530447}
448
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700449static ulong zynqmp_clk_get_dll_rate(struct zynqmp_clk_priv *priv)
450{
451 u32 clk_ctrl, srcsel;
452 enum zynqmp_clk pll;
453 ulong pllrate;
454 int ret;
455
456 ret = zynqmp_mmio_read(CRL_APB_DLL_REF_CTRL, &clk_ctrl);
457 if (ret) {
458 printf("%s mio read fail\n", __func__);
459 return -EIO;
460 }
461
462 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
463 pll = pll_src[DLL_CLK_SRC][srcsel];
464 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
465 if (IS_ERR_VALUE(pllrate))
466 return pllrate;
467
468 return pllrate;
469}
470
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530471static ulong zynqmp_clk_get_peripheral_rate(struct zynqmp_clk_priv *priv,
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700472 enum zynqmp_clk id, bool two_divs)
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530473{
474 enum zynqmp_clk pll;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700475 u32 clk_ctrl, div0, srcsel;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530476 u32 div1 = 1;
477 int ret;
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530478 ulong pllrate;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530479
480 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530481 if (ret) {
482 printf("%s mio read fail\n", __func__);
483 return -EIO;
484 }
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530485
486 div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
487 if (!div0)
488 div0 = 1;
489
490 if (two_divs) {
491 div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
492 if (!div1)
493 div1 = 1;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530494 }
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700495 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
496
497 if (id == gem_tsu_ref)
498 pll = pll_src[GEM_TSU_CLK_SRC][srcsel];
499 else
500 pll = pll_src[PERI_CLK_SRC][srcsel];
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530501
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530502 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
503 if (IS_ERR_VALUE(pllrate))
504 return pllrate;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530505
506 return
507 DIV_ROUND_CLOSEST(
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530508 DIV_ROUND_CLOSEST(pllrate, div0), div1);
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530509}
510
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700511static ulong zynqmp_clk_get_crf_crl_rate(struct zynqmp_clk_priv *priv,
512 enum zynqmp_clk id, bool two_divs)
Vipul Kumarc35e5f62018-03-07 14:52:44 +0530513{
514 enum zynqmp_clk pll;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700515 u32 clk_ctrl, div0, srcsel;
Vipul Kumarc35e5f62018-03-07 14:52:44 +0530516 u32 div1 = 1;
517 int ret;
518 ulong pllrate;
519
520 ret = zynqmp_mmio_read(zynqmp_clk_get_register(id), &clk_ctrl);
521 if (ret) {
522 printf("%d %s mio read fail\n", __LINE__, __func__);
523 return -EIO;
524 }
525
526 div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
527 if (!div0)
528 div0 = 1;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700529 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
Vipul Kumarc35e5f62018-03-07 14:52:44 +0530530
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700531 switch (id) {
532 case wdt:
533 case dbg_trace:
534 case topsw_lsbus:
535 pll = pll_src[WDT_CLK_SRC][srcsel];
536 break;
537 case dbg_fpd:
538 case dbg_tstmp:
539 pll = pll_src[DBG_FPD_CLK_SRC][srcsel];
540 break;
541 case timestamp_ref:
542 pll = pll_src[TIMESTAMP_CLK_SRC][srcsel];
543 break;
544 case sata_ref:
545 pll = pll_src[SATA_CLK_SRC][srcsel];
546 break;
547 case pcie_ref:
548 pll = pll_src[PCIE_CLK_SRC][srcsel];
549 break;
550 case gpu_ref ... gpu_pp1_ref:
551 pll = pll_src[GPU_CLK_SRC][srcsel];
552 break;
553 case gdma_ref:
554 case dpdma_ref:
555 case topsw_main:
556 pll = pll_src[TOPSW_MAIN_CLK_SRC][srcsel];
557 break;
558 case cpu_r5:
559 case ams_ref:
560 case adma_ref:
561 case lpd_lsbus:
562 case lpd_switch:
563 pll = pll_src[CPU_R5_CLK_SRC][srcsel];
564 break;
565 default:
566 return -ENXIO;
567 }
Vipul Kumarc35e5f62018-03-07 14:52:44 +0530568 if (two_divs) {
569 ret = zynqmp_mmio_read(zynqmp_clk_get_register(pll), &clk_ctrl);
570 if (ret) {
571 printf("%d %s mio read fail\n", __LINE__, __func__);
572 return -EIO;
573 }
574 div1 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
575 if (!div1)
576 div1 = 1;
577 }
578
579 if (pll == iopll_to_fpd)
580 pll = iopll;
581
582 pllrate = zynqmp_clk_get_pll_rate(priv, pll);
583 if (IS_ERR_VALUE(pllrate))
584 return pllrate;
585
586 return
587 DIV_ROUND_CLOSEST(
588 DIV_ROUND_CLOSEST(pllrate, div0), div1);
589}
590
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530591static unsigned long zynqmp_clk_calc_peripheral_two_divs(ulong rate,
592 ulong pll_rate,
593 u32 *div0, u32 *div1)
594{
595 long new_err, best_err = (long)(~0UL >> 1);
596 ulong new_rate, best_rate = 0;
597 u32 d0, d1;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530598
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530599 for (d0 = 1; d0 <= ZYNQ_CLK_MAXDIV; d0++) {
600 for (d1 = 1; d1 <= ZYNQ_CLK_MAXDIV >> 1; d1++) {
601 new_rate = DIV_ROUND_CLOSEST(
602 DIV_ROUND_CLOSEST(pll_rate, d0), d1);
603 new_err = abs(new_rate - rate);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530604
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530605 if (new_err < best_err) {
606 *div0 = d0;
607 *div1 = d1;
608 best_err = new_err;
609 best_rate = new_rate;
610 }
611 }
612 }
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530613
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530614 return best_rate;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530615}
616
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530617static ulong zynqmp_clk_set_peripheral_rate(struct zynqmp_clk_priv *priv,
618 enum zynqmp_clk id, ulong rate,
619 bool two_divs)
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530620{
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530621 enum zynqmp_clk pll;
622 u32 clk_ctrl, div0 = 0, div1 = 0;
623 ulong pll_rate, new_rate;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700624 u32 reg, srcsel;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530625 int ret;
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530626 u32 mask;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530627
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530628 reg = zynqmp_clk_get_register(id);
629 ret = zynqmp_mmio_read(reg, &clk_ctrl);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530630 if (ret) {
631 printf("%s mio read fail\n", __func__);
632 return -EIO;
633 }
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530634
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700635 srcsel = clk_ctrl & CLK_CTRL_SRCSEL_MASK;
636 pll = pll_src[PERI_CLK_SRC][srcsel];
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530637 pll_rate = zynqmp_clk_get_pll_rate(priv, pll);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530638 if (IS_ERR_VALUE(pll_rate))
639 return pll_rate;
640
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530641 clk_ctrl &= ~CLK_CTRL_DIV0_MASK;
642 if (two_divs) {
643 clk_ctrl &= ~CLK_CTRL_DIV1_MASK;
644 new_rate = zynqmp_clk_calc_peripheral_two_divs(rate, pll_rate,
645 &div0, &div1);
646 clk_ctrl |= div1 << CLK_CTRL_DIV1_SHIFT;
647 } else {
648 div0 = DIV_ROUND_CLOSEST(pll_rate, rate);
649 if (div0 > ZYNQ_CLK_MAXDIV)
650 div0 = ZYNQ_CLK_MAXDIV;
651 new_rate = DIV_ROUND_CLOSEST(rate, div0);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530652 }
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530653 clk_ctrl |= div0 << CLK_CTRL_DIV0_SHIFT;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530654
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530655 mask = (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT) |
656 (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530657
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530658 ret = zynqmp_mmio_write(reg, mask, clk_ctrl);
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530659 if (ret) {
660 printf("%s mio write fail\n", __func__);
661 return -EIO;
662 }
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530663
664 return new_rate;
665}
666
667static ulong zynqmp_clk_get_rate(struct clk *clk)
668{
669 struct zynqmp_clk_priv *priv = dev_get_priv(clk->dev);
670 enum zynqmp_clk id = clk->id;
671 bool two_divs = false;
672
673 switch (id) {
674 case iopll ... vpll:
675 return zynqmp_clk_get_pll_rate(priv, id);
676 case acpu:
677 return zynqmp_clk_get_cpu_rate(priv, id);
678 case ddr_ref:
679 return zynqmp_clk_get_ddr_rate(priv);
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700680 case dll_ref:
681 return zynqmp_clk_get_dll_rate(priv);
682 case gem_tsu_ref:
Michal Simekacff4c82022-03-29 13:13:56 +0200683 case dp_video_ref ... dp_stc_ref:
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700684 case pl0 ... pl3:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530685 case gem0_ref ... gem3_ref:
Michal Simek544f4482021-10-29 13:13:38 +0200686 case gem0_tx ... gem3_tx:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530687 case qspi_ref ... can1_ref:
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700688 case usb0_bus_ref ... usb3_dual_ref:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530689 two_divs = true;
690 return zynqmp_clk_get_peripheral_rate(priv, id, two_divs);
Vipul Kumarc35e5f62018-03-07 14:52:44 +0530691 case wdt:
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700692 case topsw_lsbus:
693 case sata_ref ... gpu_pp1_ref:
Vipul Kumarc35e5f62018-03-07 14:52:44 +0530694 two_divs = true;
Algapally Santosh Sagar9a990932023-05-19 17:08:15 +0530695 fallthrough;
T Karthik Reddy97ab47d2021-02-24 23:44:46 -0700696 case cpu_r5:
697 case dbg_fpd:
698 case ams_ref:
699 case adma_ref:
700 case lpd_lsbus:
701 case dbg_trace:
702 case dbg_tstmp:
703 case lpd_switch:
704 case topsw_main:
705 case timestamp_ref:
706 case gdma_ref ... dpdma_ref:
707 return zynqmp_clk_get_crf_crl_rate(priv, id, two_divs);
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530708 default:
709 return -ENXIO;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530710 }
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530711}
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530712
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530713static ulong zynqmp_clk_set_rate(struct clk *clk, ulong rate)
714{
715 struct zynqmp_clk_priv *priv = dev_get_priv(clk->dev);
716 enum zynqmp_clk id = clk->id;
717 bool two_divs = true;
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530718
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530719 switch (id) {
720 case gem0_ref ... gem3_ref:
Michal Simek544f4482021-10-29 13:13:38 +0200721 case gem0_tx ... gem3_tx:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530722 case qspi_ref ... can1_ref:
Michal Simek66a38922021-10-29 13:13:37 +0200723 case usb0_bus_ref ... usb3_dual_ref:
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530724 return zynqmp_clk_set_peripheral_rate(priv, id,
725 rate, two_divs);
726 default:
727 return -ENXIO;
728 }
729}
730
731int soc_clk_dump(void)
732{
733 struct udevice *dev;
734 int i, ret;
735
736 ret = uclass_get_device_by_driver(UCLASS_CLK,
Simon Glass65130cd2020-12-28 20:34:56 -0700737 DM_DRIVER_GET(zynqmp_clk), &dev);
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530738 if (ret)
739 return ret;
740
741 printf("clk\t\tfrequency\n");
742 for (i = 0; i < clk_max; i++) {
743 const char *name = clk_names[i];
744 if (name) {
745 struct clk clk;
746 unsigned long rate;
747
748 clk.id = i;
749 ret = clk_request(dev, &clk);
750 if (ret < 0)
751 return ret;
752
753 rate = clk_get_rate(&clk);
754
755 clk_free(&clk);
756
757 if ((rate == (unsigned long)-ENOSYS) ||
Siva Durga Prasad Paladugubcfc0862017-04-13 16:59:38 +0530758 (rate == (unsigned long)-ENXIO) ||
759 (rate == (unsigned long)-EIO))
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530760 printf("%10s%20s\n", name, "unknown");
761 else
762 printf("%10s%20lu\n", name, rate);
763 }
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530764 }
765
766 return 0;
767}
768
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530769static int zynqmp_get_freq_by_name(char *name, struct udevice *dev, ulong *freq)
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530770{
771 struct clk clk;
772 int ret;
773
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530774 ret = clk_get_by_name(dev, name, &clk);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530775 if (ret < 0) {
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530776 dev_err(dev, "failed to get %s\n", name);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530777 return ret;
778 }
779
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530780 *freq = clk_get_rate(&clk);
781 if (IS_ERR_VALUE(*freq)) {
782 dev_err(dev, "failed to get rate %s\n", name);
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530783 return -EINVAL;
784 }
785
786 return 0;
787}
Siva Durga Prasad Paladuguf0471e92017-02-03 23:56:49 +0530788static int zynqmp_clk_probe(struct udevice *dev)
789{
790 int ret;
791 struct zynqmp_clk_priv *priv = dev_get_priv(dev);
792
793 debug("%s\n", __func__);
794 ret = zynqmp_get_freq_by_name("pss_ref_clk", dev, &priv->ps_clk_freq);
795 if (ret < 0)
796 return -EINVAL;
797
798 ret = zynqmp_get_freq_by_name("video_clk", dev, &priv->video_clk);
799 if (ret < 0)
800 return -EINVAL;
801
802 ret = zynqmp_get_freq_by_name("pss_alt_ref_clk", dev,
803 &priv->pss_alt_ref_clk);
804 if (ret < 0)
805 return -EINVAL;
806
807 ret = zynqmp_get_freq_by_name("aux_ref_clk", dev, &priv->aux_ref_clk);
808 if (ret < 0)
809 return -EINVAL;
810
811 ret = zynqmp_get_freq_by_name("gt_crx_ref_clk", dev,
812 &priv->gt_crx_ref_clk);
813 if (ret < 0)
814 return -EINVAL;
815
816 return 0;
817}
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530818
T Karthik Reddy2aa360e2021-02-03 03:10:45 -0700819static int zynqmp_clk_enable(struct clk *clk)
820{
821 enum zynqmp_clk id = clk->id;
822 u32 reg, clk_ctrl, clkact_shift, mask;
823 int ret;
824
825 reg = zynqmp_clk_get_register(id);
826 debug("%s, clk_id:%x, clk_base:0x%x\n", __func__, id, reg);
827
828 switch (id) {
829 case usb0_bus_ref ... usb1:
830 clkact_shift = 25;
831 mask = 0x1;
832 break;
Michal Simek544f4482021-10-29 13:13:38 +0200833 case gem0_tx ... gem3_tx:
T Karthik Reddy2aa360e2021-02-03 03:10:45 -0700834 case gem0_ref ... gem3_ref:
835 clkact_shift = 25;
836 mask = 0x3;
837 break;
838 case qspi_ref ... can1_ref:
Michal Simek97790fb2021-07-01 19:01:42 +0200839 case lpd_lsbus:
T Karthik Reddy2aa360e2021-02-03 03:10:45 -0700840 clkact_shift = 24;
841 mask = 0x1;
842 break;
843 default:
844 return -ENXIO;
845 }
846
847 ret = zynqmp_mmio_read(reg, &clk_ctrl);
848 if (ret) {
849 printf("%s mio read fail\n", __func__);
850 return -EIO;
851 }
852
853 clk_ctrl |= (mask << clkact_shift);
854 ret = zynqmp_mmio_write(reg, mask << clkact_shift, clk_ctrl);
855 if (ret) {
856 printf("%s mio write fail\n", __func__);
857 return -EIO;
858 }
859
860 return ret;
861}
862
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530863static struct clk_ops zynqmp_clk_ops = {
864 .set_rate = zynqmp_clk_set_rate,
865 .get_rate = zynqmp_clk_get_rate,
T Karthik Reddy2aa360e2021-02-03 03:10:45 -0700866 .enable = zynqmp_clk_enable,
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530867};
868
869static const struct udevice_id zynqmp_clk_ids[] = {
Michal Simekd260ac72018-02-21 13:59:21 +0100870 { .compatible = "xlnx,zynqmp-clk" },
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530871 { }
872};
873
874U_BOOT_DRIVER(zynqmp_clk) = {
Michal Simek33093082020-01-07 08:50:34 +0100875 .name = "zynqmp_clk",
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530876 .id = UCLASS_CLK,
877 .of_match = zynqmp_clk_ids,
878 .probe = zynqmp_clk_probe,
879 .ops = &zynqmp_clk_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700880 .priv_auto = sizeof(struct zynqmp_clk_priv),
Siva Durga Prasad Paladugu468b55f2016-11-15 16:15:41 +0530881};