blob: 466d71786cfb2b1ffe617bd5c7ea7304238683c0 [file] [log] [blame]
Peng Fan9a0dc912019-03-05 02:32:35 +00001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright 2018 NXP
4 * Peng Fan <peng.fan@nxp.com>
5 */
6
Peng Fan9a0dc912019-03-05 02:32:35 +00007#include <clk-uclass.h>
8#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -06009#include <log.h>
Peng Fan2e0644a2023-04-28 12:08:09 +080010#include <firmware/imx/sci/sci.h>
Peng Fan9a0dc912019-03-05 02:32:35 +000011#include <asm/arch/clock.h>
12#include <dt-bindings/clock/imx8qm-clock.h>
13#include <dt-bindings/soc/imx_rsrc.h>
14#include <misc.h>
15
16#include "clk-imx8.h"
17
Simon Glass495e80f2023-02-05 15:36:26 -070018#if IS_ENABLED(CONFIG_CMD_CLK)
Peng Fan9a0dc912019-03-05 02:32:35 +000019struct imx8_clks imx8_clk_names[] = {
20 { IMX8QM_A53_DIV, "A53_DIV" },
21 { IMX8QM_UART0_CLK, "UART0" },
22 { IMX8QM_UART1_CLK, "UART1" },
23 { IMX8QM_UART2_CLK, "UART2" },
24 { IMX8QM_UART3_CLK, "UART3" },
25 { IMX8QM_SDHC0_CLK, "SDHC0" },
26 { IMX8QM_SDHC1_CLK, "SDHC1" },
27 { IMX8QM_SDHC2_CLK, "SDHC2" },
28 { IMX8QM_ENET0_AHB_CLK, "ENET0_AHB" },
29 { IMX8QM_ENET0_IPG_CLK, "ENET0_IPG" },
30 { IMX8QM_ENET0_REF_DIV, "ENET0_REF" },
31 { IMX8QM_ENET0_PTP_CLK, "ENET0_PTP" },
32 { IMX8QM_ENET1_AHB_CLK, "ENET1_AHB" },
33 { IMX8QM_ENET1_IPG_CLK, "ENET1_IPG" },
34 { IMX8QM_ENET1_REF_DIV, "ENET1_REF" },
35 { IMX8QM_ENET1_PTP_CLK, "ENET1_PTP" },
36};
37
38int num_clks = ARRAY_SIZE(imx8_clk_names);
39#endif
40
41ulong imx8_clk_get_rate(struct clk *clk)
42{
43 sc_pm_clk_t pm_clk;
44 ulong rate;
45 u16 resource;
46 int ret;
47
48 debug("%s(#%lu)\n", __func__, clk->id);
49
50 switch (clk->id) {
Peng Fanb62eb192024-10-16 15:50:29 +080051 case IMX8QM_CLK_DUMMY:
52 return 0;
Peng Fan9a0dc912019-03-05 02:32:35 +000053 case IMX8QM_A53_DIV:
54 resource = SC_R_A53;
55 pm_clk = SC_PM_CLK_CPU;
56 break;
Oliver Grautec4a32902020-11-12 11:51:04 +010057 case IMX8QM_I2C0_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +000058 case IMX8QM_I2C0_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +010059 case IMX8QM_I2C0_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +000060 resource = SC_R_I2C_0;
61 pm_clk = SC_PM_CLK_PER;
62 break;
Oliver Grautec4a32902020-11-12 11:51:04 +010063 case IMX8QM_I2C1_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +000064 case IMX8QM_I2C1_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +010065 case IMX8QM_I2C1_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +000066 resource = SC_R_I2C_1;
67 pm_clk = SC_PM_CLK_PER;
68 break;
Oliver Grautec4a32902020-11-12 11:51:04 +010069 case IMX8QM_I2C2_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +000070 case IMX8QM_I2C2_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +010071 case IMX8QM_I2C2_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +000072 resource = SC_R_I2C_2;
73 pm_clk = SC_PM_CLK_PER;
74 break;
Oliver Grautec4a32902020-11-12 11:51:04 +010075 case IMX8QM_I2C3_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +000076 case IMX8QM_I2C3_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +010077 case IMX8QM_I2C3_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +000078 resource = SC_R_I2C_3;
79 pm_clk = SC_PM_CLK_PER;
80 break;
81 case IMX8QM_SDHC0_IPG_CLK:
82 case IMX8QM_SDHC0_CLK:
83 case IMX8QM_SDHC0_DIV:
84 resource = SC_R_SDHC_0;
85 pm_clk = SC_PM_CLK_PER;
86 break;
87 case IMX8QM_SDHC1_IPG_CLK:
88 case IMX8QM_SDHC1_CLK:
89 case IMX8QM_SDHC1_DIV:
90 resource = SC_R_SDHC_1;
91 pm_clk = SC_PM_CLK_PER;
92 break;
Marcel Ziswiler62eb8182019-05-31 19:00:17 +030093 case IMX8QM_SDHC2_IPG_CLK:
94 case IMX8QM_SDHC2_CLK:
95 case IMX8QM_SDHC2_DIV:
96 resource = SC_R_SDHC_2;
97 pm_clk = SC_PM_CLK_PER;
98 break;
Peng Fan9a0dc912019-03-05 02:32:35 +000099 case IMX8QM_UART0_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300100 case IMX8QM_UART0_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000101 resource = SC_R_UART_0;
102 pm_clk = SC_PM_CLK_PER;
103 break;
104 case IMX8QM_UART1_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300105 case IMX8QM_UART1_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000106 resource = SC_R_UART_1;
107 pm_clk = SC_PM_CLK_PER;
108 break;
109 case IMX8QM_UART2_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300110 case IMX8QM_UART2_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000111 resource = SC_R_UART_2;
112 pm_clk = SC_PM_CLK_PER;
113 break;
114 case IMX8QM_UART3_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300115 case IMX8QM_UART3_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000116 resource = SC_R_UART_3;
117 pm_clk = SC_PM_CLK_PER;
118 break;
119 case IMX8QM_ENET0_IPG_CLK:
120 case IMX8QM_ENET0_AHB_CLK:
121 case IMX8QM_ENET0_REF_DIV:
122 case IMX8QM_ENET0_PTP_CLK:
123 resource = SC_R_ENET_0;
124 pm_clk = SC_PM_CLK_PER;
125 break;
126 case IMX8QM_ENET1_IPG_CLK:
127 case IMX8QM_ENET1_AHB_CLK:
128 case IMX8QM_ENET1_REF_DIV:
129 case IMX8QM_ENET1_PTP_CLK:
130 resource = SC_R_ENET_1;
131 pm_clk = SC_PM_CLK_PER;
132 break;
133 default:
134 if (clk->id < IMX8QM_UART0_IPG_CLK ||
135 clk->id >= IMX8QM_CLK_END) {
136 printf("%s(Invalid clk ID #%lu)\n",
137 __func__, clk->id);
138 return -EINVAL;
139 }
Simon Glass29ff16a2021-03-25 10:26:08 +1300140 return -EINVAL;
Peng Fan9a0dc912019-03-05 02:32:35 +0000141 };
142
143 ret = sc_pm_get_clock_rate(-1, resource, pm_clk,
144 (sc_pm_clock_rate_t *)&rate);
145 if (ret) {
146 printf("%s err %d\n", __func__, ret);
147 return ret;
148 }
149
150 return rate;
151}
152
153ulong imx8_clk_set_rate(struct clk *clk, unsigned long rate)
154{
155 sc_pm_clk_t pm_clk;
156 u32 new_rate = rate;
157 u16 resource;
158 int ret;
159
160 debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
161
162 switch (clk->id) {
Oliver Grautec4a32902020-11-12 11:51:04 +0100163 case IMX8QM_I2C0_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000164 case IMX8QM_I2C0_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100165 case IMX8QM_I2C0_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000166 resource = SC_R_I2C_0;
167 pm_clk = SC_PM_CLK_PER;
168 break;
Oliver Grautec4a32902020-11-12 11:51:04 +0100169 case IMX8QM_I2C1_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000170 case IMX8QM_I2C1_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100171 case IMX8QM_I2C1_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000172 resource = SC_R_I2C_1;
173 pm_clk = SC_PM_CLK_PER;
174 break;
Oliver Grautec4a32902020-11-12 11:51:04 +0100175 case IMX8QM_I2C2_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000176 case IMX8QM_I2C2_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100177 case IMX8QM_I2C2_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000178 resource = SC_R_I2C_2;
179 pm_clk = SC_PM_CLK_PER;
180 break;
Oliver Grautec4a32902020-11-12 11:51:04 +0100181 case IMX8QM_I2C3_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000182 case IMX8QM_I2C3_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100183 case IMX8QM_I2C3_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000184 resource = SC_R_I2C_3;
185 pm_clk = SC_PM_CLK_PER;
186 break;
187 case IMX8QM_UART0_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300188 case IMX8QM_UART0_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000189 resource = SC_R_UART_0;
190 pm_clk = SC_PM_CLK_PER;
191 break;
192 case IMX8QM_UART1_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300193 case IMX8QM_UART1_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000194 resource = SC_R_UART_1;
195 pm_clk = SC_PM_CLK_PER;
196 break;
197 case IMX8QM_UART2_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300198 case IMX8QM_UART2_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000199 resource = SC_R_UART_2;
200 pm_clk = SC_PM_CLK_PER;
201 break;
202 case IMX8QM_UART3_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300203 case IMX8QM_UART3_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000204 resource = SC_R_UART_3;
205 pm_clk = SC_PM_CLK_PER;
206 break;
207 case IMX8QM_SDHC0_IPG_CLK:
208 case IMX8QM_SDHC0_CLK:
209 case IMX8QM_SDHC0_DIV:
210 resource = SC_R_SDHC_0;
211 pm_clk = SC_PM_CLK_PER;
212 break;
213 case IMX8QM_SDHC1_IPG_CLK:
214 case IMX8QM_SDHC1_CLK:
215 case IMX8QM_SDHC1_DIV:
216 resource = SC_R_SDHC_1;
217 pm_clk = SC_PM_CLK_PER;
218 break;
Marcel Ziswiler62eb8182019-05-31 19:00:17 +0300219 case IMX8QM_SDHC2_IPG_CLK:
220 case IMX8QM_SDHC2_CLK:
221 case IMX8QM_SDHC2_DIV:
222 resource = SC_R_SDHC_2;
223 pm_clk = SC_PM_CLK_PER;
224 break;
Peng Fan9a0dc912019-03-05 02:32:35 +0000225 case IMX8QM_ENET0_IPG_CLK:
226 case IMX8QM_ENET0_AHB_CLK:
227 case IMX8QM_ENET0_REF_DIV:
228 case IMX8QM_ENET0_PTP_CLK:
229 case IMX8QM_ENET0_ROOT_DIV:
230 resource = SC_R_ENET_0;
231 pm_clk = SC_PM_CLK_PER;
232 break;
233 case IMX8QM_ENET1_IPG_CLK:
234 case IMX8QM_ENET1_AHB_CLK:
235 case IMX8QM_ENET1_REF_DIV:
236 case IMX8QM_ENET1_PTP_CLK:
237 case IMX8QM_ENET1_ROOT_DIV:
238 resource = SC_R_ENET_1;
239 pm_clk = SC_PM_CLK_PER;
240 break;
241 default:
242 if (clk->id < IMX8QM_UART0_IPG_CLK ||
243 clk->id >= IMX8QM_CLK_END) {
244 printf("%s(Invalid clk ID #%lu)\n",
245 __func__, clk->id);
246 return -EINVAL;
247 }
Simon Glass29ff16a2021-03-25 10:26:08 +1300248 return -EINVAL;
Peng Fan9a0dc912019-03-05 02:32:35 +0000249 };
250
251 ret = sc_pm_set_clock_rate(-1, resource, pm_clk, &new_rate);
252 if (ret) {
253 printf("%s err %d\n", __func__, ret);
254 return ret;
255 }
256
257 return new_rate;
258}
259
260int __imx8_clk_enable(struct clk *clk, bool enable)
261{
262 sc_pm_clk_t pm_clk;
263 u16 resource;
264 int ret;
265
266 debug("%s(#%lu)\n", __func__, clk->id);
267
268 switch (clk->id) {
Peng Fanb62eb192024-10-16 15:50:29 +0800269 case IMX8QM_CLK_DUMMY:
270 return 0;
Oliver Grautec4a32902020-11-12 11:51:04 +0100271 case IMX8QM_I2C0_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000272 case IMX8QM_I2C0_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100273 case IMX8QM_I2C0_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000274 resource = SC_R_I2C_0;
275 pm_clk = SC_PM_CLK_PER;
276 break;
Oliver Grautec4a32902020-11-12 11:51:04 +0100277 case IMX8QM_I2C1_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000278 case IMX8QM_I2C1_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100279 case IMX8QM_I2C1_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000280 resource = SC_R_I2C_1;
281 pm_clk = SC_PM_CLK_PER;
282 break;
Oliver Grautec4a32902020-11-12 11:51:04 +0100283 case IMX8QM_I2C2_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000284 case IMX8QM_I2C2_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100285 case IMX8QM_I2C2_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000286 resource = SC_R_I2C_2;
287 pm_clk = SC_PM_CLK_PER;
288 break;
Oliver Grautec4a32902020-11-12 11:51:04 +0100289 case IMX8QM_I2C3_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000290 case IMX8QM_I2C3_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100291 case IMX8QM_I2C3_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000292 resource = SC_R_I2C_3;
293 pm_clk = SC_PM_CLK_PER;
294 break;
295 case IMX8QM_UART0_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300296 case IMX8QM_UART0_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000297 resource = SC_R_UART_0;
298 pm_clk = SC_PM_CLK_PER;
299 break;
300 case IMX8QM_UART1_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300301 case IMX8QM_UART1_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000302 resource = SC_R_UART_1;
303 pm_clk = SC_PM_CLK_PER;
304 break;
305 case IMX8QM_UART2_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300306 case IMX8QM_UART2_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000307 resource = SC_R_UART_2;
308 pm_clk = SC_PM_CLK_PER;
309 break;
310 case IMX8QM_UART3_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300311 case IMX8QM_UART3_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000312 resource = SC_R_UART_3;
313 pm_clk = SC_PM_CLK_PER;
314 break;
315 case IMX8QM_SDHC0_IPG_CLK:
316 case IMX8QM_SDHC0_CLK:
317 case IMX8QM_SDHC0_DIV:
318 resource = SC_R_SDHC_0;
319 pm_clk = SC_PM_CLK_PER;
320 break;
321 case IMX8QM_SDHC1_IPG_CLK:
322 case IMX8QM_SDHC1_CLK:
323 case IMX8QM_SDHC1_DIV:
324 resource = SC_R_SDHC_1;
325 pm_clk = SC_PM_CLK_PER;
326 break;
Marcel Ziswiler62eb8182019-05-31 19:00:17 +0300327 case IMX8QM_SDHC2_IPG_CLK:
328 case IMX8QM_SDHC2_CLK:
329 case IMX8QM_SDHC2_DIV:
330 resource = SC_R_SDHC_2;
331 pm_clk = SC_PM_CLK_PER;
332 break;
Peng Fan9a0dc912019-03-05 02:32:35 +0000333 case IMX8QM_ENET0_IPG_CLK:
334 case IMX8QM_ENET0_AHB_CLK:
335 case IMX8QM_ENET0_REF_DIV:
336 case IMX8QM_ENET0_PTP_CLK:
337 resource = SC_R_ENET_0;
338 pm_clk = SC_PM_CLK_PER;
339 break;
340 case IMX8QM_ENET1_IPG_CLK:
341 case IMX8QM_ENET1_AHB_CLK:
342 case IMX8QM_ENET1_REF_DIV:
343 case IMX8QM_ENET1_PTP_CLK:
344 resource = SC_R_ENET_1;
345 pm_clk = SC_PM_CLK_PER;
346 break;
347 default:
348 if (clk->id < IMX8QM_UART0_IPG_CLK ||
349 clk->id >= IMX8QM_CLK_END) {
350 printf("%s(Invalid clk ID #%lu)\n",
351 __func__, clk->id);
352 return -EINVAL;
353 }
Simon Glass29ff16a2021-03-25 10:26:08 +1300354 return -EINVAL;
Peng Fan9a0dc912019-03-05 02:32:35 +0000355 }
356
357 ret = sc_pm_clock_enable(-1, resource, pm_clk, enable, 0);
358 if (ret) {
359 printf("%s err %d\n", __func__, ret);
360 return ret;
361 }
362
363 return 0;
364}