ARM: dts: at91: sama5d2_icp: fix i2c eeprom compatible
[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_CLK:
57                 resource = SC_R_I2C_0;
58                 pm_clk = SC_PM_CLK_PER;
59                 break;
60         case IMX8QM_I2C1_CLK:
61                 resource = SC_R_I2C_1;
62                 pm_clk = SC_PM_CLK_PER;
63                 break;
64         case IMX8QM_I2C2_CLK:
65                 resource = SC_R_I2C_2;
66                 pm_clk = SC_PM_CLK_PER;
67                 break;
68         case IMX8QM_I2C3_CLK:
69                 resource = SC_R_I2C_3;
70                 pm_clk = SC_PM_CLK_PER;
71                 break;
72         case IMX8QM_SDHC0_IPG_CLK:
73         case IMX8QM_SDHC0_CLK:
74         case IMX8QM_SDHC0_DIV:
75                 resource = SC_R_SDHC_0;
76                 pm_clk = SC_PM_CLK_PER;
77                 break;
78         case IMX8QM_SDHC1_IPG_CLK:
79         case IMX8QM_SDHC1_CLK:
80         case IMX8QM_SDHC1_DIV:
81                 resource = SC_R_SDHC_1;
82                 pm_clk = SC_PM_CLK_PER;
83                 break;
84         case IMX8QM_SDHC2_IPG_CLK:
85         case IMX8QM_SDHC2_CLK:
86         case IMX8QM_SDHC2_DIV:
87                 resource = SC_R_SDHC_2;
88                 pm_clk = SC_PM_CLK_PER;
89                 break;
90         case IMX8QM_UART0_IPG_CLK:
91         case IMX8QM_UART0_CLK:
92                 resource = SC_R_UART_0;
93                 pm_clk = SC_PM_CLK_PER;
94                 break;
95         case IMX8QM_UART1_CLK:
96                 resource = SC_R_UART_1;
97                 pm_clk = SC_PM_CLK_PER;
98                 break;
99         case IMX8QM_UART2_CLK:
100                 resource = SC_R_UART_2;
101                 pm_clk = SC_PM_CLK_PER;
102                 break;
103         case IMX8QM_UART3_CLK:
104                 resource = SC_R_UART_3;
105                 pm_clk = SC_PM_CLK_PER;
106                 break;
107         case IMX8QM_ENET0_IPG_CLK:
108         case IMX8QM_ENET0_AHB_CLK:
109         case IMX8QM_ENET0_REF_DIV:
110         case IMX8QM_ENET0_PTP_CLK:
111                 resource = SC_R_ENET_0;
112                 pm_clk = SC_PM_CLK_PER;
113                 break;
114         case IMX8QM_ENET1_IPG_CLK:
115         case IMX8QM_ENET1_AHB_CLK:
116         case IMX8QM_ENET1_REF_DIV:
117         case IMX8QM_ENET1_PTP_CLK:
118                 resource = SC_R_ENET_1;
119                 pm_clk = SC_PM_CLK_PER;
120                 break;
121         default:
122                 if (clk->id < IMX8QM_UART0_IPG_CLK ||
123                     clk->id >= IMX8QM_CLK_END) {
124                         printf("%s(Invalid clk ID #%lu)\n",
125                                __func__, clk->id);
126                         return -EINVAL;
127                 }
128                 return -ENOTSUPP;
129         };
130
131         ret = sc_pm_get_clock_rate(-1, resource, pm_clk,
132                                    (sc_pm_clock_rate_t *)&rate);
133         if (ret) {
134                 printf("%s err %d\n", __func__, ret);
135                 return ret;
136         }
137
138         return rate;
139 }
140
141 ulong imx8_clk_set_rate(struct clk *clk, unsigned long rate)
142 {
143         sc_pm_clk_t pm_clk;
144         u32 new_rate = rate;
145         u16 resource;
146         int ret;
147
148         debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
149
150         switch (clk->id) {
151         case IMX8QM_I2C0_CLK:
152                 resource = SC_R_I2C_0;
153                 pm_clk = SC_PM_CLK_PER;
154                 break;
155         case IMX8QM_I2C1_CLK:
156                 resource = SC_R_I2C_1;
157                 pm_clk = SC_PM_CLK_PER;
158                 break;
159         case IMX8QM_I2C2_CLK:
160                 resource = SC_R_I2C_2;
161                 pm_clk = SC_PM_CLK_PER;
162                 break;
163         case IMX8QM_I2C3_CLK:
164                 resource = SC_R_I2C_3;
165                 pm_clk = SC_PM_CLK_PER;
166                 break;
167         case IMX8QM_UART0_CLK:
168                 resource = SC_R_UART_0;
169                 pm_clk = SC_PM_CLK_PER;
170                 break;
171         case IMX8QM_UART1_CLK:
172                 resource = SC_R_UART_1;
173                 pm_clk = SC_PM_CLK_PER;
174                 break;
175         case IMX8QM_UART2_CLK:
176                 resource = SC_R_UART_2;
177                 pm_clk = SC_PM_CLK_PER;
178                 break;
179         case IMX8QM_UART3_CLK:
180                 resource = SC_R_UART_3;
181                 pm_clk = SC_PM_CLK_PER;
182                 break;
183         case IMX8QM_SDHC0_IPG_CLK:
184         case IMX8QM_SDHC0_CLK:
185         case IMX8QM_SDHC0_DIV:
186                 resource = SC_R_SDHC_0;
187                 pm_clk = SC_PM_CLK_PER;
188                 break;
189         case IMX8QM_SDHC1_IPG_CLK:
190         case IMX8QM_SDHC1_CLK:
191         case IMX8QM_SDHC1_DIV:
192                 resource = SC_R_SDHC_1;
193                 pm_clk = SC_PM_CLK_PER;
194                 break;
195         case IMX8QM_SDHC2_IPG_CLK:
196         case IMX8QM_SDHC2_CLK:
197         case IMX8QM_SDHC2_DIV:
198                 resource = SC_R_SDHC_2;
199                 pm_clk = SC_PM_CLK_PER;
200                 break;
201         case IMX8QM_ENET0_IPG_CLK:
202         case IMX8QM_ENET0_AHB_CLK:
203         case IMX8QM_ENET0_REF_DIV:
204         case IMX8QM_ENET0_PTP_CLK:
205         case IMX8QM_ENET0_ROOT_DIV:
206                 resource = SC_R_ENET_0;
207                 pm_clk = SC_PM_CLK_PER;
208                 break;
209         case IMX8QM_ENET1_IPG_CLK:
210         case IMX8QM_ENET1_AHB_CLK:
211         case IMX8QM_ENET1_REF_DIV:
212         case IMX8QM_ENET1_PTP_CLK:
213         case IMX8QM_ENET1_ROOT_DIV:
214                 resource = SC_R_ENET_1;
215                 pm_clk = SC_PM_CLK_PER;
216                 break;
217         default:
218                 if (clk->id < IMX8QM_UART0_IPG_CLK ||
219                     clk->id >= IMX8QM_CLK_END) {
220                         printf("%s(Invalid clk ID #%lu)\n",
221                                __func__, clk->id);
222                         return -EINVAL;
223                 }
224                 return -ENOTSUPP;
225         };
226
227         ret = sc_pm_set_clock_rate(-1, resource, pm_clk, &new_rate);
228         if (ret) {
229                 printf("%s err %d\n", __func__, ret);
230                 return ret;
231         }
232
233         return new_rate;
234 }
235
236 int __imx8_clk_enable(struct clk *clk, bool enable)
237 {
238         sc_pm_clk_t pm_clk;
239         u16 resource;
240         int ret;
241
242         debug("%s(#%lu)\n", __func__, clk->id);
243
244         switch (clk->id) {
245         case IMX8QM_I2C0_CLK:
246                 resource = SC_R_I2C_0;
247                 pm_clk = SC_PM_CLK_PER;
248                 break;
249         case IMX8QM_I2C1_CLK:
250                 resource = SC_R_I2C_1;
251                 pm_clk = SC_PM_CLK_PER;
252                 break;
253         case IMX8QM_I2C2_CLK:
254                 resource = SC_R_I2C_2;
255                 pm_clk = SC_PM_CLK_PER;
256                 break;
257         case IMX8QM_I2C3_CLK:
258                 resource = SC_R_I2C_3;
259                 pm_clk = SC_PM_CLK_PER;
260                 break;
261         case IMX8QM_UART0_CLK:
262                 resource = SC_R_UART_0;
263                 pm_clk = SC_PM_CLK_PER;
264                 break;
265         case IMX8QM_UART1_CLK:
266                 resource = SC_R_UART_1;
267                 pm_clk = SC_PM_CLK_PER;
268                 break;
269         case IMX8QM_UART2_CLK:
270                 resource = SC_R_UART_2;
271                 pm_clk = SC_PM_CLK_PER;
272                 break;
273         case IMX8QM_UART3_CLK:
274                 resource = SC_R_UART_3;
275                 pm_clk = SC_PM_CLK_PER;
276                 break;
277         case IMX8QM_SDHC0_IPG_CLK:
278         case IMX8QM_SDHC0_CLK:
279         case IMX8QM_SDHC0_DIV:
280                 resource = SC_R_SDHC_0;
281                 pm_clk = SC_PM_CLK_PER;
282                 break;
283         case IMX8QM_SDHC1_IPG_CLK:
284         case IMX8QM_SDHC1_CLK:
285         case IMX8QM_SDHC1_DIV:
286                 resource = SC_R_SDHC_1;
287                 pm_clk = SC_PM_CLK_PER;
288                 break;
289         case IMX8QM_SDHC2_IPG_CLK:
290         case IMX8QM_SDHC2_CLK:
291         case IMX8QM_SDHC2_DIV:
292                 resource = SC_R_SDHC_2;
293                 pm_clk = SC_PM_CLK_PER;
294                 break;
295         case IMX8QM_ENET0_IPG_CLK:
296         case IMX8QM_ENET0_AHB_CLK:
297         case IMX8QM_ENET0_REF_DIV:
298         case IMX8QM_ENET0_PTP_CLK:
299                 resource = SC_R_ENET_0;
300                 pm_clk = SC_PM_CLK_PER;
301                 break;
302         case IMX8QM_ENET1_IPG_CLK:
303         case IMX8QM_ENET1_AHB_CLK:
304         case IMX8QM_ENET1_REF_DIV:
305         case IMX8QM_ENET1_PTP_CLK:
306                 resource = SC_R_ENET_1;
307                 pm_clk = SC_PM_CLK_PER;
308                 break;
309         default:
310                 if (clk->id < IMX8QM_UART0_IPG_CLK ||
311                     clk->id >= IMX8QM_CLK_END) {
312                         printf("%s(Invalid clk ID #%lu)\n",
313                                __func__, clk->id);
314                         return -EINVAL;
315                 }
316                 return -ENOTSUPP;
317         }
318
319         ret = sc_pm_clock_enable(-1, resource, pm_clk, enable, 0);
320         if (ret) {
321                 printf("%s err %d\n", __func__, ret);
322                 return ret;
323         }
324
325         return 0;
326 }