Merge tag 'u-boot-atmel-fixes-2021.01-b' of https://gitlab.denx.de/u-boot/custodians...
[platform/kernel/u-boot.git] / drivers / clk / imx / clk-imx8qm.c
1 // 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>
10 #include <log.h>
11 #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)
20 struct 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
39 int num_clks = ARRAY_SIZE(imx8_clk_names);
40 #endif
41
42 ulong 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;
56         case IMX8QM_I2C0_IPG_CLK:
57         case IMX8QM_I2C0_CLK:
58         case IMX8QM_I2C0_DIV:
59                 resource = SC_R_I2C_0;
60                 pm_clk = SC_PM_CLK_PER;
61                 break;
62         case IMX8QM_I2C1_IPG_CLK:
63         case IMX8QM_I2C1_CLK:
64         case IMX8QM_I2C1_DIV:
65                 resource = SC_R_I2C_1;
66                 pm_clk = SC_PM_CLK_PER;
67                 break;
68         case IMX8QM_I2C2_IPG_CLK:
69         case IMX8QM_I2C2_CLK:
70         case IMX8QM_I2C2_DIV:
71                 resource = SC_R_I2C_2;
72                 pm_clk = SC_PM_CLK_PER;
73                 break;
74         case IMX8QM_I2C3_IPG_CLK:
75         case IMX8QM_I2C3_CLK:
76         case IMX8QM_I2C3_DIV:
77                 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;
92         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;
98         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
149 ulong 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) {
159         case IMX8QM_I2C0_IPG_CLK:
160         case IMX8QM_I2C0_CLK:
161         case IMX8QM_I2C0_DIV:
162                 resource = SC_R_I2C_0;
163                 pm_clk = SC_PM_CLK_PER;
164                 break;
165         case IMX8QM_I2C1_IPG_CLK:
166         case IMX8QM_I2C1_CLK:
167         case IMX8QM_I2C1_DIV:
168                 resource = SC_R_I2C_1;
169                 pm_clk = SC_PM_CLK_PER;
170                 break;
171         case IMX8QM_I2C2_IPG_CLK:
172         case IMX8QM_I2C2_CLK:
173         case IMX8QM_I2C2_DIV:
174                 resource = SC_R_I2C_2;
175                 pm_clk = SC_PM_CLK_PER;
176                 break;
177         case IMX8QM_I2C3_IPG_CLK:
178         case IMX8QM_I2C3_CLK:
179         case IMX8QM_I2C3_DIV:
180                 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;
211         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;
217         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
252 int __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) {
261         case IMX8QM_I2C0_IPG_CLK:
262         case IMX8QM_I2C0_CLK:
263         case IMX8QM_I2C0_DIV:
264                 resource = SC_R_I2C_0;
265                 pm_clk = SC_PM_CLK_PER;
266                 break;
267         case IMX8QM_I2C1_IPG_CLK:
268         case IMX8QM_I2C1_CLK:
269         case IMX8QM_I2C1_DIV:
270                 resource = SC_R_I2C_1;
271                 pm_clk = SC_PM_CLK_PER;
272                 break;
273         case IMX8QM_I2C2_IPG_CLK:
274         case IMX8QM_I2C2_CLK:
275         case IMX8QM_I2C2_DIV:
276                 resource = SC_R_I2C_2;
277                 pm_clk = SC_PM_CLK_PER;
278                 break;
279         case IMX8QM_I2C3_IPG_CLK:
280         case IMX8QM_I2C3_CLK:
281         case IMX8QM_I2C3_DIV:
282                 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;
313         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;
319         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 }