blob: 01e33de9d63f26eb9b0c3bae0b48e443b3b473e1 [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
7#include <common.h>
8#include <clk-uclass.h>
9#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -060010#include <log.h>
Peng Fan2e0644a2023-04-28 12:08:09 +080011#include <firmware/imx/sci/sci.h>
Peng Fan9a0dc912019-03-05 02:32:35 +000012#include <asm/arch/clock.h>
13#include <dt-bindings/clock/imx8qm-clock.h>
14#include <dt-bindings/soc/imx_rsrc.h>
15#include <misc.h>
16
17#include "clk-imx8.h"
18
Simon Glass495e80f2023-02-05 15:36:26 -070019#if IS_ENABLED(CONFIG_CMD_CLK)
Peng Fan9a0dc912019-03-05 02:32:35 +000020struct imx8_clks imx8_clk_names[] = {
21 { IMX8QM_A53_DIV, "A53_DIV" },
22 { IMX8QM_UART0_CLK, "UART0" },
23 { IMX8QM_UART1_CLK, "UART1" },
24 { IMX8QM_UART2_CLK, "UART2" },
25 { IMX8QM_UART3_CLK, "UART3" },
26 { IMX8QM_SDHC0_CLK, "SDHC0" },
27 { IMX8QM_SDHC1_CLK, "SDHC1" },
28 { IMX8QM_SDHC2_CLK, "SDHC2" },
29 { IMX8QM_ENET0_AHB_CLK, "ENET0_AHB" },
30 { IMX8QM_ENET0_IPG_CLK, "ENET0_IPG" },
31 { IMX8QM_ENET0_REF_DIV, "ENET0_REF" },
32 { IMX8QM_ENET0_PTP_CLK, "ENET0_PTP" },
33 { IMX8QM_ENET1_AHB_CLK, "ENET1_AHB" },
34 { IMX8QM_ENET1_IPG_CLK, "ENET1_IPG" },
35 { IMX8QM_ENET1_REF_DIV, "ENET1_REF" },
36 { IMX8QM_ENET1_PTP_CLK, "ENET1_PTP" },
37};
38
39int num_clks = ARRAY_SIZE(imx8_clk_names);
40#endif
41
42ulong imx8_clk_get_rate(struct clk *clk)
43{
44 sc_pm_clk_t pm_clk;
45 ulong rate;
46 u16 resource;
47 int ret;
48
49 debug("%s(#%lu)\n", __func__, clk->id);
50
51 switch (clk->id) {
52 case IMX8QM_A53_DIV:
53 resource = SC_R_A53;
54 pm_clk = SC_PM_CLK_CPU;
55 break;
Oliver Grautec4a32902020-11-12 11:51:04 +010056 case IMX8QM_I2C0_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +000057 case IMX8QM_I2C0_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +010058 case IMX8QM_I2C0_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +000059 resource = SC_R_I2C_0;
60 pm_clk = SC_PM_CLK_PER;
61 break;
Oliver Grautec4a32902020-11-12 11:51:04 +010062 case IMX8QM_I2C1_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +000063 case IMX8QM_I2C1_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +010064 case IMX8QM_I2C1_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +000065 resource = SC_R_I2C_1;
66 pm_clk = SC_PM_CLK_PER;
67 break;
Oliver Grautec4a32902020-11-12 11:51:04 +010068 case IMX8QM_I2C2_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +000069 case IMX8QM_I2C2_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +010070 case IMX8QM_I2C2_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +000071 resource = SC_R_I2C_2;
72 pm_clk = SC_PM_CLK_PER;
73 break;
Oliver Grautec4a32902020-11-12 11:51:04 +010074 case IMX8QM_I2C3_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +000075 case IMX8QM_I2C3_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +010076 case IMX8QM_I2C3_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +000077 resource = SC_R_I2C_3;
78 pm_clk = SC_PM_CLK_PER;
79 break;
80 case IMX8QM_SDHC0_IPG_CLK:
81 case IMX8QM_SDHC0_CLK:
82 case IMX8QM_SDHC0_DIV:
83 resource = SC_R_SDHC_0;
84 pm_clk = SC_PM_CLK_PER;
85 break;
86 case IMX8QM_SDHC1_IPG_CLK:
87 case IMX8QM_SDHC1_CLK:
88 case IMX8QM_SDHC1_DIV:
89 resource = SC_R_SDHC_1;
90 pm_clk = SC_PM_CLK_PER;
91 break;
Marcel Ziswiler62eb8182019-05-31 19:00:17 +030092 case IMX8QM_SDHC2_IPG_CLK:
93 case IMX8QM_SDHC2_CLK:
94 case IMX8QM_SDHC2_DIV:
95 resource = SC_R_SDHC_2;
96 pm_clk = SC_PM_CLK_PER;
97 break;
Peng Fan9a0dc912019-03-05 02:32:35 +000098 case IMX8QM_UART0_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -030099 case IMX8QM_UART0_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000100 resource = SC_R_UART_0;
101 pm_clk = SC_PM_CLK_PER;
102 break;
103 case IMX8QM_UART1_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300104 case IMX8QM_UART1_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000105 resource = SC_R_UART_1;
106 pm_clk = SC_PM_CLK_PER;
107 break;
108 case IMX8QM_UART2_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300109 case IMX8QM_UART2_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000110 resource = SC_R_UART_2;
111 pm_clk = SC_PM_CLK_PER;
112 break;
113 case IMX8QM_UART3_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300114 case IMX8QM_UART3_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000115 resource = SC_R_UART_3;
116 pm_clk = SC_PM_CLK_PER;
117 break;
118 case IMX8QM_ENET0_IPG_CLK:
119 case IMX8QM_ENET0_AHB_CLK:
120 case IMX8QM_ENET0_REF_DIV:
121 case IMX8QM_ENET0_PTP_CLK:
122 resource = SC_R_ENET_0;
123 pm_clk = SC_PM_CLK_PER;
124 break;
125 case IMX8QM_ENET1_IPG_CLK:
126 case IMX8QM_ENET1_AHB_CLK:
127 case IMX8QM_ENET1_REF_DIV:
128 case IMX8QM_ENET1_PTP_CLK:
129 resource = SC_R_ENET_1;
130 pm_clk = SC_PM_CLK_PER;
131 break;
132 default:
133 if (clk->id < IMX8QM_UART0_IPG_CLK ||
134 clk->id >= IMX8QM_CLK_END) {
135 printf("%s(Invalid clk ID #%lu)\n",
136 __func__, clk->id);
137 return -EINVAL;
138 }
Simon Glass29ff16a2021-03-25 10:26:08 +1300139 return -EINVAL;
Peng Fan9a0dc912019-03-05 02:32:35 +0000140 };
141
142 ret = sc_pm_get_clock_rate(-1, resource, pm_clk,
143 (sc_pm_clock_rate_t *)&rate);
144 if (ret) {
145 printf("%s err %d\n", __func__, ret);
146 return ret;
147 }
148
149 return rate;
150}
151
152ulong imx8_clk_set_rate(struct clk *clk, unsigned long rate)
153{
154 sc_pm_clk_t pm_clk;
155 u32 new_rate = rate;
156 u16 resource;
157 int ret;
158
159 debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
160
161 switch (clk->id) {
Oliver Grautec4a32902020-11-12 11:51:04 +0100162 case IMX8QM_I2C0_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000163 case IMX8QM_I2C0_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100164 case IMX8QM_I2C0_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000165 resource = SC_R_I2C_0;
166 pm_clk = SC_PM_CLK_PER;
167 break;
Oliver Grautec4a32902020-11-12 11:51:04 +0100168 case IMX8QM_I2C1_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000169 case IMX8QM_I2C1_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100170 case IMX8QM_I2C1_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000171 resource = SC_R_I2C_1;
172 pm_clk = SC_PM_CLK_PER;
173 break;
Oliver Grautec4a32902020-11-12 11:51:04 +0100174 case IMX8QM_I2C2_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000175 case IMX8QM_I2C2_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100176 case IMX8QM_I2C2_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000177 resource = SC_R_I2C_2;
178 pm_clk = SC_PM_CLK_PER;
179 break;
Oliver Grautec4a32902020-11-12 11:51:04 +0100180 case IMX8QM_I2C3_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000181 case IMX8QM_I2C3_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100182 case IMX8QM_I2C3_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000183 resource = SC_R_I2C_3;
184 pm_clk = SC_PM_CLK_PER;
185 break;
186 case IMX8QM_UART0_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300187 case IMX8QM_UART0_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000188 resource = SC_R_UART_0;
189 pm_clk = SC_PM_CLK_PER;
190 break;
191 case IMX8QM_UART1_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300192 case IMX8QM_UART1_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000193 resource = SC_R_UART_1;
194 pm_clk = SC_PM_CLK_PER;
195 break;
196 case IMX8QM_UART2_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300197 case IMX8QM_UART2_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000198 resource = SC_R_UART_2;
199 pm_clk = SC_PM_CLK_PER;
200 break;
201 case IMX8QM_UART3_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300202 case IMX8QM_UART3_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000203 resource = SC_R_UART_3;
204 pm_clk = SC_PM_CLK_PER;
205 break;
206 case IMX8QM_SDHC0_IPG_CLK:
207 case IMX8QM_SDHC0_CLK:
208 case IMX8QM_SDHC0_DIV:
209 resource = SC_R_SDHC_0;
210 pm_clk = SC_PM_CLK_PER;
211 break;
212 case IMX8QM_SDHC1_IPG_CLK:
213 case IMX8QM_SDHC1_CLK:
214 case IMX8QM_SDHC1_DIV:
215 resource = SC_R_SDHC_1;
216 pm_clk = SC_PM_CLK_PER;
217 break;
Marcel Ziswiler62eb8182019-05-31 19:00:17 +0300218 case IMX8QM_SDHC2_IPG_CLK:
219 case IMX8QM_SDHC2_CLK:
220 case IMX8QM_SDHC2_DIV:
221 resource = SC_R_SDHC_2;
222 pm_clk = SC_PM_CLK_PER;
223 break;
Peng Fan9a0dc912019-03-05 02:32:35 +0000224 case IMX8QM_ENET0_IPG_CLK:
225 case IMX8QM_ENET0_AHB_CLK:
226 case IMX8QM_ENET0_REF_DIV:
227 case IMX8QM_ENET0_PTP_CLK:
228 case IMX8QM_ENET0_ROOT_DIV:
229 resource = SC_R_ENET_0;
230 pm_clk = SC_PM_CLK_PER;
231 break;
232 case IMX8QM_ENET1_IPG_CLK:
233 case IMX8QM_ENET1_AHB_CLK:
234 case IMX8QM_ENET1_REF_DIV:
235 case IMX8QM_ENET1_PTP_CLK:
236 case IMX8QM_ENET1_ROOT_DIV:
237 resource = SC_R_ENET_1;
238 pm_clk = SC_PM_CLK_PER;
239 break;
240 default:
241 if (clk->id < IMX8QM_UART0_IPG_CLK ||
242 clk->id >= IMX8QM_CLK_END) {
243 printf("%s(Invalid clk ID #%lu)\n",
244 __func__, clk->id);
245 return -EINVAL;
246 }
Simon Glass29ff16a2021-03-25 10:26:08 +1300247 return -EINVAL;
Peng Fan9a0dc912019-03-05 02:32:35 +0000248 };
249
250 ret = sc_pm_set_clock_rate(-1, resource, pm_clk, &new_rate);
251 if (ret) {
252 printf("%s err %d\n", __func__, ret);
253 return ret;
254 }
255
256 return new_rate;
257}
258
259int __imx8_clk_enable(struct clk *clk, bool enable)
260{
261 sc_pm_clk_t pm_clk;
262 u16 resource;
263 int ret;
264
265 debug("%s(#%lu)\n", __func__, clk->id);
266
267 switch (clk->id) {
Oliver Grautec4a32902020-11-12 11:51:04 +0100268 case IMX8QM_I2C0_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000269 case IMX8QM_I2C0_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100270 case IMX8QM_I2C0_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000271 resource = SC_R_I2C_0;
272 pm_clk = SC_PM_CLK_PER;
273 break;
Oliver Grautec4a32902020-11-12 11:51:04 +0100274 case IMX8QM_I2C1_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000275 case IMX8QM_I2C1_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100276 case IMX8QM_I2C1_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000277 resource = SC_R_I2C_1;
278 pm_clk = SC_PM_CLK_PER;
279 break;
Oliver Grautec4a32902020-11-12 11:51:04 +0100280 case IMX8QM_I2C2_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000281 case IMX8QM_I2C2_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100282 case IMX8QM_I2C2_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000283 resource = SC_R_I2C_2;
284 pm_clk = SC_PM_CLK_PER;
285 break;
Oliver Grautec4a32902020-11-12 11:51:04 +0100286 case IMX8QM_I2C3_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000287 case IMX8QM_I2C3_CLK:
Oliver Grautec4a32902020-11-12 11:51:04 +0100288 case IMX8QM_I2C3_DIV:
Peng Fan9a0dc912019-03-05 02:32:35 +0000289 resource = SC_R_I2C_3;
290 pm_clk = SC_PM_CLK_PER;
291 break;
292 case IMX8QM_UART0_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300293 case IMX8QM_UART0_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000294 resource = SC_R_UART_0;
295 pm_clk = SC_PM_CLK_PER;
296 break;
297 case IMX8QM_UART1_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300298 case IMX8QM_UART1_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000299 resource = SC_R_UART_1;
300 pm_clk = SC_PM_CLK_PER;
301 break;
302 case IMX8QM_UART2_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300303 case IMX8QM_UART2_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000304 resource = SC_R_UART_2;
305 pm_clk = SC_PM_CLK_PER;
306 break;
307 case IMX8QM_UART3_CLK:
Fabio Estevam2eeee7c2024-03-08 17:13:16 -0300308 case IMX8QM_UART3_IPG_CLK:
Peng Fan9a0dc912019-03-05 02:32:35 +0000309 resource = SC_R_UART_3;
310 pm_clk = SC_PM_CLK_PER;
311 break;
312 case IMX8QM_SDHC0_IPG_CLK:
313 case IMX8QM_SDHC0_CLK:
314 case IMX8QM_SDHC0_DIV:
315 resource = SC_R_SDHC_0;
316 pm_clk = SC_PM_CLK_PER;
317 break;
318 case IMX8QM_SDHC1_IPG_CLK:
319 case IMX8QM_SDHC1_CLK:
320 case IMX8QM_SDHC1_DIV:
321 resource = SC_R_SDHC_1;
322 pm_clk = SC_PM_CLK_PER;
323 break;
Marcel Ziswiler62eb8182019-05-31 19:00:17 +0300324 case IMX8QM_SDHC2_IPG_CLK:
325 case IMX8QM_SDHC2_CLK:
326 case IMX8QM_SDHC2_DIV:
327 resource = SC_R_SDHC_2;
328 pm_clk = SC_PM_CLK_PER;
329 break;
Peng Fan9a0dc912019-03-05 02:32:35 +0000330 case IMX8QM_ENET0_IPG_CLK:
331 case IMX8QM_ENET0_AHB_CLK:
332 case IMX8QM_ENET0_REF_DIV:
333 case IMX8QM_ENET0_PTP_CLK:
334 resource = SC_R_ENET_0;
335 pm_clk = SC_PM_CLK_PER;
336 break;
337 case IMX8QM_ENET1_IPG_CLK:
338 case IMX8QM_ENET1_AHB_CLK:
339 case IMX8QM_ENET1_REF_DIV:
340 case IMX8QM_ENET1_PTP_CLK:
341 resource = SC_R_ENET_1;
342 pm_clk = SC_PM_CLK_PER;
343 break;
344 default:
345 if (clk->id < IMX8QM_UART0_IPG_CLK ||
346 clk->id >= IMX8QM_CLK_END) {
347 printf("%s(Invalid clk ID #%lu)\n",
348 __func__, clk->id);
349 return -EINVAL;
350 }
Simon Glass29ff16a2021-03-25 10:26:08 +1300351 return -EINVAL;
Peng Fan9a0dc912019-03-05 02:32:35 +0000352 }
353
354 ret = sc_pm_clock_enable(-1, resource, pm_clk, enable, 0);
355 if (ret) {
356 printf("%s err %d\n", __func__, ret);
357 return ret;
358 }
359
360 return 0;
361}