blob: 7e466d630a079c2c15c0d0e6a833f3f66e0b960a [file] [log] [blame]
Peng Fane45efe92019-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 Glassf7ae49f2020-05-10 11:40:05 -060010#include <log.h>
Peng Fane45efe92019-03-05 02:32:35 +000011#include <asm/arch/sci/sci.h>
12#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
19#if CONFIG_IS_ENABLED(CMD_CLK)
20struct 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 Graute61eb1fe2020-11-12 11:51:04 +010056 case IMX8QM_I2C0_IPG_CLK:
Peng Fane45efe92019-03-05 02:32:35 +000057 case IMX8QM_I2C0_CLK:
Oliver Graute61eb1fe2020-11-12 11:51:04 +010058 case IMX8QM_I2C0_DIV:
Peng Fane45efe92019-03-05 02:32:35 +000059 resource = SC_R_I2C_0;
60 pm_clk = SC_PM_CLK_PER;
61 break;
Oliver Graute61eb1fe2020-11-12 11:51:04 +010062 case IMX8QM_I2C1_IPG_CLK:
Peng Fane45efe92019-03-05 02:32:35 +000063 case IMX8QM_I2C1_CLK:
Oliver Graute61eb1fe2020-11-12 11:51:04 +010064 case IMX8QM_I2C1_DIV:
Peng Fane45efe92019-03-05 02:32:35 +000065 resource = SC_R_I2C_1;
66 pm_clk = SC_PM_CLK_PER;
67 break;
Oliver Graute61eb1fe2020-11-12 11:51:04 +010068 case IMX8QM_I2C2_IPG_CLK:
Peng Fane45efe92019-03-05 02:32:35 +000069 case IMX8QM_I2C2_CLK:
Oliver Graute61eb1fe2020-11-12 11:51:04 +010070 case IMX8QM_I2C2_DIV:
Peng Fane45efe92019-03-05 02:32:35 +000071 resource = SC_R_I2C_2;
72 pm_clk = SC_PM_CLK_PER;
73 break;
Oliver Graute61eb1fe2020-11-12 11:51:04 +010074 case IMX8QM_I2C3_IPG_CLK:
Peng Fane45efe92019-03-05 02:32:35 +000075 case IMX8QM_I2C3_CLK:
Oliver Graute61eb1fe2020-11-12 11:51:04 +010076 case IMX8QM_I2C3_DIV:
Peng Fane45efe92019-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 Ziswiler16f8b842019-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 Fane45efe92019-03-05 02:32:35 +000098 case IMX8QM_UART0_IPG_CLK:
99 case IMX8QM_UART0_CLK:
100 resource = SC_R_UART_0;
101 pm_clk = SC_PM_CLK_PER;
102 break;
103 case IMX8QM_UART1_CLK:
104 resource = SC_R_UART_1;
105 pm_clk = SC_PM_CLK_PER;
106 break;
107 case IMX8QM_UART2_CLK:
108 resource = SC_R_UART_2;
109 pm_clk = SC_PM_CLK_PER;
110 break;
111 case IMX8QM_UART3_CLK:
112 resource = SC_R_UART_3;
113 pm_clk = SC_PM_CLK_PER;
114 break;
115 case IMX8QM_ENET0_IPG_CLK:
116 case IMX8QM_ENET0_AHB_CLK:
117 case IMX8QM_ENET0_REF_DIV:
118 case IMX8QM_ENET0_PTP_CLK:
119 resource = SC_R_ENET_0;
120 pm_clk = SC_PM_CLK_PER;
121 break;
122 case IMX8QM_ENET1_IPG_CLK:
123 case IMX8QM_ENET1_AHB_CLK:
124 case IMX8QM_ENET1_REF_DIV:
125 case IMX8QM_ENET1_PTP_CLK:
126 resource = SC_R_ENET_1;
127 pm_clk = SC_PM_CLK_PER;
128 break;
129 default:
130 if (clk->id < IMX8QM_UART0_IPG_CLK ||
131 clk->id >= IMX8QM_CLK_END) {
132 printf("%s(Invalid clk ID #%lu)\n",
133 __func__, clk->id);
134 return -EINVAL;
135 }
136 return -ENOTSUPP;
137 };
138
139 ret = sc_pm_get_clock_rate(-1, resource, pm_clk,
140 (sc_pm_clock_rate_t *)&rate);
141 if (ret) {
142 printf("%s err %d\n", __func__, ret);
143 return ret;
144 }
145
146 return rate;
147}
148
149ulong imx8_clk_set_rate(struct clk *clk, unsigned long rate)
150{
151 sc_pm_clk_t pm_clk;
152 u32 new_rate = rate;
153 u16 resource;
154 int ret;
155
156 debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
157
158 switch (clk->id) {
Oliver Graute61eb1fe2020-11-12 11:51:04 +0100159 case IMX8QM_I2C0_IPG_CLK:
Peng Fane45efe92019-03-05 02:32:35 +0000160 case IMX8QM_I2C0_CLK:
Oliver Graute61eb1fe2020-11-12 11:51:04 +0100161 case IMX8QM_I2C0_DIV:
Peng Fane45efe92019-03-05 02:32:35 +0000162 resource = SC_R_I2C_0;
163 pm_clk = SC_PM_CLK_PER;
164 break;
Oliver Graute61eb1fe2020-11-12 11:51:04 +0100165 case IMX8QM_I2C1_IPG_CLK:
Peng Fane45efe92019-03-05 02:32:35 +0000166 case IMX8QM_I2C1_CLK:
Oliver Graute61eb1fe2020-11-12 11:51:04 +0100167 case IMX8QM_I2C1_DIV:
Peng Fane45efe92019-03-05 02:32:35 +0000168 resource = SC_R_I2C_1;
169 pm_clk = SC_PM_CLK_PER;
170 break;
Oliver Graute61eb1fe2020-11-12 11:51:04 +0100171 case IMX8QM_I2C2_IPG_CLK:
Peng Fane45efe92019-03-05 02:32:35 +0000172 case IMX8QM_I2C2_CLK:
Oliver Graute61eb1fe2020-11-12 11:51:04 +0100173 case IMX8QM_I2C2_DIV:
Peng Fane45efe92019-03-05 02:32:35 +0000174 resource = SC_R_I2C_2;
175 pm_clk = SC_PM_CLK_PER;
176 break;
Oliver Graute61eb1fe2020-11-12 11:51:04 +0100177 case IMX8QM_I2C3_IPG_CLK:
Peng Fane45efe92019-03-05 02:32:35 +0000178 case IMX8QM_I2C3_CLK:
Oliver Graute61eb1fe2020-11-12 11:51:04 +0100179 case IMX8QM_I2C3_DIV:
Peng Fane45efe92019-03-05 02:32:35 +0000180 resource = SC_R_I2C_3;
181 pm_clk = SC_PM_CLK_PER;
182 break;
183 case IMX8QM_UART0_CLK:
184 resource = SC_R_UART_0;
185 pm_clk = SC_PM_CLK_PER;
186 break;
187 case IMX8QM_UART1_CLK:
188 resource = SC_R_UART_1;
189 pm_clk = SC_PM_CLK_PER;
190 break;
191 case IMX8QM_UART2_CLK:
192 resource = SC_R_UART_2;
193 pm_clk = SC_PM_CLK_PER;
194 break;
195 case IMX8QM_UART3_CLK:
196 resource = SC_R_UART_3;
197 pm_clk = SC_PM_CLK_PER;
198 break;
199 case IMX8QM_SDHC0_IPG_CLK:
200 case IMX8QM_SDHC0_CLK:
201 case IMX8QM_SDHC0_DIV:
202 resource = SC_R_SDHC_0;
203 pm_clk = SC_PM_CLK_PER;
204 break;
205 case IMX8QM_SDHC1_IPG_CLK:
206 case IMX8QM_SDHC1_CLK:
207 case IMX8QM_SDHC1_DIV:
208 resource = SC_R_SDHC_1;
209 pm_clk = SC_PM_CLK_PER;
210 break;
Marcel Ziswiler16f8b842019-05-31 19:00:17 +0300211 case IMX8QM_SDHC2_IPG_CLK:
212 case IMX8QM_SDHC2_CLK:
213 case IMX8QM_SDHC2_DIV:
214 resource = SC_R_SDHC_2;
215 pm_clk = SC_PM_CLK_PER;
216 break;
Peng Fane45efe92019-03-05 02:32:35 +0000217 case IMX8QM_ENET0_IPG_CLK:
218 case IMX8QM_ENET0_AHB_CLK:
219 case IMX8QM_ENET0_REF_DIV:
220 case IMX8QM_ENET0_PTP_CLK:
221 case IMX8QM_ENET0_ROOT_DIV:
222 resource = SC_R_ENET_0;
223 pm_clk = SC_PM_CLK_PER;
224 break;
225 case IMX8QM_ENET1_IPG_CLK:
226 case IMX8QM_ENET1_AHB_CLK:
227 case IMX8QM_ENET1_REF_DIV:
228 case IMX8QM_ENET1_PTP_CLK:
229 case IMX8QM_ENET1_ROOT_DIV:
230 resource = SC_R_ENET_1;
231 pm_clk = SC_PM_CLK_PER;
232 break;
233 default:
234 if (clk->id < IMX8QM_UART0_IPG_CLK ||
235 clk->id >= IMX8QM_CLK_END) {
236 printf("%s(Invalid clk ID #%lu)\n",
237 __func__, clk->id);
238 return -EINVAL;
239 }
240 return -ENOTSUPP;
241 };
242
243 ret = sc_pm_set_clock_rate(-1, resource, pm_clk, &new_rate);
244 if (ret) {
245 printf("%s err %d\n", __func__, ret);
246 return ret;
247 }
248
249 return new_rate;
250}
251
252int __imx8_clk_enable(struct clk *clk, bool enable)
253{
254 sc_pm_clk_t pm_clk;
255 u16 resource;
256 int ret;
257
258 debug("%s(#%lu)\n", __func__, clk->id);
259
260 switch (clk->id) {
Oliver Graute61eb1fe2020-11-12 11:51:04 +0100261 case IMX8QM_I2C0_IPG_CLK:
Peng Fane45efe92019-03-05 02:32:35 +0000262 case IMX8QM_I2C0_CLK:
Oliver Graute61eb1fe2020-11-12 11:51:04 +0100263 case IMX8QM_I2C0_DIV:
Peng Fane45efe92019-03-05 02:32:35 +0000264 resource = SC_R_I2C_0;
265 pm_clk = SC_PM_CLK_PER;
266 break;
Oliver Graute61eb1fe2020-11-12 11:51:04 +0100267 case IMX8QM_I2C1_IPG_CLK:
Peng Fane45efe92019-03-05 02:32:35 +0000268 case IMX8QM_I2C1_CLK:
Oliver Graute61eb1fe2020-11-12 11:51:04 +0100269 case IMX8QM_I2C1_DIV:
Peng Fane45efe92019-03-05 02:32:35 +0000270 resource = SC_R_I2C_1;
271 pm_clk = SC_PM_CLK_PER;
272 break;
Oliver Graute61eb1fe2020-11-12 11:51:04 +0100273 case IMX8QM_I2C2_IPG_CLK:
Peng Fane45efe92019-03-05 02:32:35 +0000274 case IMX8QM_I2C2_CLK:
Oliver Graute61eb1fe2020-11-12 11:51:04 +0100275 case IMX8QM_I2C2_DIV:
Peng Fane45efe92019-03-05 02:32:35 +0000276 resource = SC_R_I2C_2;
277 pm_clk = SC_PM_CLK_PER;
278 break;
Oliver Graute61eb1fe2020-11-12 11:51:04 +0100279 case IMX8QM_I2C3_IPG_CLK:
Peng Fane45efe92019-03-05 02:32:35 +0000280 case IMX8QM_I2C3_CLK:
Oliver Graute61eb1fe2020-11-12 11:51:04 +0100281 case IMX8QM_I2C3_DIV:
Peng Fane45efe92019-03-05 02:32:35 +0000282 resource = SC_R_I2C_3;
283 pm_clk = SC_PM_CLK_PER;
284 break;
285 case IMX8QM_UART0_CLK:
286 resource = SC_R_UART_0;
287 pm_clk = SC_PM_CLK_PER;
288 break;
289 case IMX8QM_UART1_CLK:
290 resource = SC_R_UART_1;
291 pm_clk = SC_PM_CLK_PER;
292 break;
293 case IMX8QM_UART2_CLK:
294 resource = SC_R_UART_2;
295 pm_clk = SC_PM_CLK_PER;
296 break;
297 case IMX8QM_UART3_CLK:
298 resource = SC_R_UART_3;
299 pm_clk = SC_PM_CLK_PER;
300 break;
301 case IMX8QM_SDHC0_IPG_CLK:
302 case IMX8QM_SDHC0_CLK:
303 case IMX8QM_SDHC0_DIV:
304 resource = SC_R_SDHC_0;
305 pm_clk = SC_PM_CLK_PER;
306 break;
307 case IMX8QM_SDHC1_IPG_CLK:
308 case IMX8QM_SDHC1_CLK:
309 case IMX8QM_SDHC1_DIV:
310 resource = SC_R_SDHC_1;
311 pm_clk = SC_PM_CLK_PER;
312 break;
Marcel Ziswiler16f8b842019-05-31 19:00:17 +0300313 case IMX8QM_SDHC2_IPG_CLK:
314 case IMX8QM_SDHC2_CLK:
315 case IMX8QM_SDHC2_DIV:
316 resource = SC_R_SDHC_2;
317 pm_clk = SC_PM_CLK_PER;
318 break;
Peng Fane45efe92019-03-05 02:32:35 +0000319 case IMX8QM_ENET0_IPG_CLK:
320 case IMX8QM_ENET0_AHB_CLK:
321 case IMX8QM_ENET0_REF_DIV:
322 case IMX8QM_ENET0_PTP_CLK:
323 resource = SC_R_ENET_0;
324 pm_clk = SC_PM_CLK_PER;
325 break;
326 case IMX8QM_ENET1_IPG_CLK:
327 case IMX8QM_ENET1_AHB_CLK:
328 case IMX8QM_ENET1_REF_DIV:
329 case IMX8QM_ENET1_PTP_CLK:
330 resource = SC_R_ENET_1;
331 pm_clk = SC_PM_CLK_PER;
332 break;
333 default:
334 if (clk->id < IMX8QM_UART0_IPG_CLK ||
335 clk->id >= IMX8QM_CLK_END) {
336 printf("%s(Invalid clk ID #%lu)\n",
337 __func__, clk->id);
338 return -EINVAL;
339 }
340 return -ENOTSUPP;
341 }
342
343 ret = sc_pm_clock_enable(-1, resource, pm_clk, enable, 0);
344 if (ret) {
345 printf("%s err %d\n", __func__, ret);
346 return ret;
347 }
348
349 return 0;
350}