blob: 62fed7e3e32cef0933f2a8e05edfc08af390bab7 [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) {
51 case IMX8QM_A53_DIV:
52 resource = SC_R_A53;
53 pm_clk = SC_PM_CLK_CPU;
54 break;
Oliver Grautec4a32902020-11-12 11:51:04 +010055 case IMX8QM_I2C0_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +000056 case IMX8QM_I2C0_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +010057 case IMX8QM_I2C0_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +000058 resource = SC_R_I2C_0;
59 pm_clk = SC_PM_CLK_PER;
60 break;
Oliver Grautec4a32902020-11-12 11:51:04 +010061 case IMX8QM_I2C1_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +000062 case IMX8QM_I2C1_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +010063 case IMX8QM_I2C1_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +000064 resource = SC_R_I2C_1;
65 pm_clk = SC_PM_CLK_PER;
66 break;
Oliver Grautec4a32902020-11-12 11:51:04 +010067 case IMX8QM_I2C2_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +000068 case IMX8QM_I2C2_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +010069 case IMX8QM_I2C2_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +000070 resource = SC_R_I2C_2;
71 pm_clk = SC_PM_CLK_PER;
72 break;
Oliver Grautec4a32902020-11-12 11:51:04 +010073 case IMX8QM_I2C3_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +000074 case IMX8QM_I2C3_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +010075 case IMX8QM_I2C3_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +000076 resource = SC_R_I2C_3;
77 pm_clk = SC_PM_CLK_PER;
78 break;
79 case IMX8QM_SDHC0_IPG_CLK:
80 case IMX8QM_SDHC0_CLK:
81 case IMX8QM_SDHC0_DIV:
82 resource = SC_R_SDHC_0;
83 pm_clk = SC_PM_CLK_PER;
84 break;
85 case IMX8QM_SDHC1_IPG_CLK:
86 case IMX8QM_SDHC1_CLK:
87 case IMX8QM_SDHC1_DIV:
88 resource = SC_R_SDHC_1;
89 pm_clk = SC_PM_CLK_PER;
90 break;
Marcel Ziswiler62eb8182019-05-31 19:00:17 +030091 case IMX8QM_SDHC2_IPG_CLK:
92 case IMX8QM_SDHC2_CLK:
93 case IMX8QM_SDHC2_DIV:
94 resource = SC_R_SDHC_2;
95 pm_clk = SC_PM_CLK_PER;
96 break;
Peng Fan9a0dc912019-03-05 02:32:35 +000097 case IMX8QM_UART0_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -030098 case IMX8QM_UART0_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +000099 resource = SC_R_UART_0;
100 pm_clk = SC_PM_CLK_PER;
101 break;
102 case IMX8QM_UART1_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300103 case IMX8QM_UART1_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000104 resource = SC_R_UART_1;
105 pm_clk = SC_PM_CLK_PER;
106 break;
107 case IMX8QM_UART2_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300108 case IMX8QM_UART2_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000109 resource = SC_R_UART_2;
110 pm_clk = SC_PM_CLK_PER;
111 break;
112 case IMX8QM_UART3_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300113 case IMX8QM_UART3_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000114 resource = SC_R_UART_3;
115 pm_clk = SC_PM_CLK_PER;
116 break;
117 case IMX8QM_ENET0_IPG_CLK:
118 case IMX8QM_ENET0_AHB_CLK:
119 case IMX8QM_ENET0_REF_DIV:
120 case IMX8QM_ENET0_PTP_CLK:
121 resource = SC_R_ENET_0;
122 pm_clk = SC_PM_CLK_PER;
123 break;
124 case IMX8QM_ENET1_IPG_CLK:
125 case IMX8QM_ENET1_AHB_CLK:
126 case IMX8QM_ENET1_REF_DIV:
127 case IMX8QM_ENET1_PTP_CLK:
128 resource = SC_R_ENET_1;
129 pm_clk = SC_PM_CLK_PER;
130 break;
131 default:
132 if (clk->id < IMX8QM_UART0_IPG_CLK ||
133 clk->id >= IMX8QM_CLK_END) {
134 printf("%s(Invalid clk ID #%lu)\n",
135 __func__, clk->id);
136 return -EINVAL;
137 }
Simon Glass29ff16a2021-03-25 10:26:08 +1300138 return -EINVAL;
Peng Fan9a0dc912019-03-05 02:32:35 +0000139 };
140
141 ret = sc_pm_get_clock_rate(-1, resource, pm_clk,
142 (sc_pm_clock_rate_t *)&rate);
143 if (ret) {
144 printf("%s err %d\n", __func__, ret);
145 return ret;
146 }
147
148 return rate;
149}
150
151ulong imx8_clk_set_rate(struct clk *clk, unsigned long rate)
152{
153 sc_pm_clk_t pm_clk;
154 u32 new_rate = rate;
155 u16 resource;
156 int ret;
157
158 debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
159
160 switch (clk->id) {
Oliver Grautec4a32902020-11-12 11:51:04 +0100161 case IMX8QM_I2C0_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000162 case IMX8QM_I2C0_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100163 case IMX8QM_I2C0_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000164 resource = SC_R_I2C_0;
165 pm_clk = SC_PM_CLK_PER;
166 break;
Oliver Grautec4a32902020-11-12 11:51:04 +0100167 case IMX8QM_I2C1_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000168 case IMX8QM_I2C1_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100169 case IMX8QM_I2C1_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000170 resource = SC_R_I2C_1;
171 pm_clk = SC_PM_CLK_PER;
172 break;
Oliver Grautec4a32902020-11-12 11:51:04 +0100173 case IMX8QM_I2C2_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000174 case IMX8QM_I2C2_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100175 case IMX8QM_I2C2_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000176 resource = SC_R_I2C_2;
177 pm_clk = SC_PM_CLK_PER;
178 break;
Oliver Grautec4a32902020-11-12 11:51:04 +0100179 case IMX8QM_I2C3_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000180 case IMX8QM_I2C3_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100181 case IMX8QM_I2C3_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000182 resource = SC_R_I2C_3;
183 pm_clk = SC_PM_CLK_PER;
184 break;
185 case IMX8QM_UART0_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300186 case IMX8QM_UART0_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000187 resource = SC_R_UART_0;
188 pm_clk = SC_PM_CLK_PER;
189 break;
190 case IMX8QM_UART1_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300191 case IMX8QM_UART1_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000192 resource = SC_R_UART_1;
193 pm_clk = SC_PM_CLK_PER;
194 break;
195 case IMX8QM_UART2_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300196 case IMX8QM_UART2_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000197 resource = SC_R_UART_2;
198 pm_clk = SC_PM_CLK_PER;
199 break;
200 case IMX8QM_UART3_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300201 case IMX8QM_UART3_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000202 resource = SC_R_UART_3;
203 pm_clk = SC_PM_CLK_PER;
204 break;
205 case IMX8QM_SDHC0_IPG_CLK:
206 case IMX8QM_SDHC0_CLK:
207 case IMX8QM_SDHC0_DIV:
208 resource = SC_R_SDHC_0;
209 pm_clk = SC_PM_CLK_PER;
210 break;
211 case IMX8QM_SDHC1_IPG_CLK:
212 case IMX8QM_SDHC1_CLK:
213 case IMX8QM_SDHC1_DIV:
214 resource = SC_R_SDHC_1;
215 pm_clk = SC_PM_CLK_PER;
216 break;
Marcel Ziswiler62eb8182019-05-31 19:00:17 +0300217 case IMX8QM_SDHC2_IPG_CLK:
218 case IMX8QM_SDHC2_CLK:
219 case IMX8QM_SDHC2_DIV:
220 resource = SC_R_SDHC_2;
221 pm_clk = SC_PM_CLK_PER;
222 break;
Peng Fan9a0dc912019-03-05 02:32:35 +0000223 case IMX8QM_ENET0_IPG_CLK:
224 case IMX8QM_ENET0_AHB_CLK:
225 case IMX8QM_ENET0_REF_DIV:
226 case IMX8QM_ENET0_PTP_CLK:
227 case IMX8QM_ENET0_ROOT_DIV:
228 resource = SC_R_ENET_0;
229 pm_clk = SC_PM_CLK_PER;
230 break;
231 case IMX8QM_ENET1_IPG_CLK:
232 case IMX8QM_ENET1_AHB_CLK:
233 case IMX8QM_ENET1_REF_DIV:
234 case IMX8QM_ENET1_PTP_CLK:
235 case IMX8QM_ENET1_ROOT_DIV:
236 resource = SC_R_ENET_1;
237 pm_clk = SC_PM_CLK_PER;
238 break;
239 default:
240 if (clk->id < IMX8QM_UART0_IPG_CLK ||
241 clk->id >= IMX8QM_CLK_END) {
242 printf("%s(Invalid clk ID #%lu)\n",
243 __func__, clk->id);
244 return -EINVAL;
245 }
Simon Glass29ff16a2021-03-25 10:26:08 +1300246 return -EINVAL;
Peng Fan9a0dc912019-03-05 02:32:35 +0000247 };
248
249 ret = sc_pm_set_clock_rate(-1, resource, pm_clk, &new_rate);
250 if (ret) {
251 printf("%s err %d\n", __func__, ret);
252 return ret;
253 }
254
255 return new_rate;
256}
257
258int __imx8_clk_enable(struct clk *clk, bool enable)
259{
260 sc_pm_clk_t pm_clk;
261 u16 resource;
262 int ret;
263
264 debug("%s(#%lu)\n", __func__, clk->id);
265
266 switch (clk->id) {
Oliver Grautec4a32902020-11-12 11:51:04 +0100267 case IMX8QM_I2C0_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000268 case IMX8QM_I2C0_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100269 case IMX8QM_I2C0_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000270 resource = SC_R_I2C_0;
271 pm_clk = SC_PM_CLK_PER;
272 break;
Oliver Grautec4a32902020-11-12 11:51:04 +0100273 case IMX8QM_I2C1_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000274 case IMX8QM_I2C1_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100275 case IMX8QM_I2C1_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000276 resource = SC_R_I2C_1;
277 pm_clk = SC_PM_CLK_PER;
278 break;
Oliver Grautec4a32902020-11-12 11:51:04 +0100279 case IMX8QM_I2C2_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000280 case IMX8QM_I2C2_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100281 case IMX8QM_I2C2_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000282 resource = SC_R_I2C_2;
283 pm_clk = SC_PM_CLK_PER;
284 break;
Oliver Grautec4a32902020-11-12 11:51:04 +0100285 case IMX8QM_I2C3_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000286 case IMX8QM_I2C3_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100287 case IMX8QM_I2C3_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000288 resource = SC_R_I2C_3;
289 pm_clk = SC_PM_CLK_PER;
290 break;
291 case IMX8QM_UART0_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300292 case IMX8QM_UART0_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000293 resource = SC_R_UART_0;
294 pm_clk = SC_PM_CLK_PER;
295 break;
296 case IMX8QM_UART1_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300297 case IMX8QM_UART1_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000298 resource = SC_R_UART_1;
299 pm_clk = SC_PM_CLK_PER;
300 break;
301 case IMX8QM_UART2_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300302 case IMX8QM_UART2_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000303 resource = SC_R_UART_2;
304 pm_clk = SC_PM_CLK_PER;
305 break;
306 case IMX8QM_UART3_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300307 case IMX8QM_UART3_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000308 resource = SC_R_UART_3;
309 pm_clk = SC_PM_CLK_PER;
310 break;
311 case IMX8QM_SDHC0_IPG_CLK:
312 case IMX8QM_SDHC0_CLK:
313 case IMX8QM_SDHC0_DIV:
314 resource = SC_R_SDHC_0;
315 pm_clk = SC_PM_CLK_PER;
316 break;
317 case IMX8QM_SDHC1_IPG_CLK:
318 case IMX8QM_SDHC1_CLK:
319 case IMX8QM_SDHC1_DIV:
320 resource = SC_R_SDHC_1;
321 pm_clk = SC_PM_CLK_PER;
322 break;
Marcel Ziswiler62eb8182019-05-31 19:00:17 +0300323 case IMX8QM_SDHC2_IPG_CLK:
324 case IMX8QM_SDHC2_CLK:
325 case IMX8QM_SDHC2_DIV:
326 resource = SC_R_SDHC_2;
327 pm_clk = SC_PM_CLK_PER;
328 break;
Peng Fan9a0dc912019-03-05 02:32:35 +0000329 case IMX8QM_ENET0_IPG_CLK:
330 case IMX8QM_ENET0_AHB_CLK:
331 case IMX8QM_ENET0_REF_DIV:
332 case IMX8QM_ENET0_PTP_CLK:
333 resource = SC_R_ENET_0;
334 pm_clk = SC_PM_CLK_PER;
335 break;
336 case IMX8QM_ENET1_IPG_CLK:
337 case IMX8QM_ENET1_AHB_CLK:
338 case IMX8QM_ENET1_REF_DIV:
339 case IMX8QM_ENET1_PTP_CLK:
340 resource = SC_R_ENET_1;
341 pm_clk = SC_PM_CLK_PER;
342 break;
343 default:
344 if (clk->id < IMX8QM_UART0_IPG_CLK ||
345 clk->id >= IMX8QM_CLK_END) {
346 printf("%s(Invalid clk ID #%lu)\n",
347 __func__, clk->id);
348 return -EINVAL;
349 }
Simon Glass29ff16a2021-03-25 10:26:08 +1300350 return -EINVAL;
Peng Fan9a0dc912019-03-05 02:32:35 +0000351 }
352
353 ret = sc_pm_clock_enable(-1, resource, pm_clk, enable, 0);
354 if (ret) {
355 printf("%s err %d\n", __func__, ret);
356 return ret;
357 }
358
359 return 0;
360}