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