1 // SPDX-License-Identifier: GPL-2.0
4 * Peng Fan <peng.fan@nxp.com>
8 #include <clk-uclass.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>
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" },
39 int num_clks = ARRAY_SIZE(imx8_clk_names);
42 ulong imx8_clk_get_rate(struct clk *clk)
49 debug("%s(#%lu)\n", __func__, clk->id);
54 pm_clk = SC_PM_CLK_CPU;
56 case IMX8QM_I2C0_IPG_CLK:
59 resource = SC_R_I2C_0;
60 pm_clk = SC_PM_CLK_PER;
62 case IMX8QM_I2C1_IPG_CLK:
65 resource = SC_R_I2C_1;
66 pm_clk = SC_PM_CLK_PER;
68 case IMX8QM_I2C2_IPG_CLK:
71 resource = SC_R_I2C_2;
72 pm_clk = SC_PM_CLK_PER;
74 case IMX8QM_I2C3_IPG_CLK:
77 resource = SC_R_I2C_3;
78 pm_clk = SC_PM_CLK_PER;
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;
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;
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;
98 case IMX8QM_UART0_IPG_CLK:
99 case IMX8QM_UART0_CLK:
100 resource = SC_R_UART_0;
101 pm_clk = SC_PM_CLK_PER;
103 case IMX8QM_UART1_CLK:
104 resource = SC_R_UART_1;
105 pm_clk = SC_PM_CLK_PER;
107 case IMX8QM_UART2_CLK:
108 resource = SC_R_UART_2;
109 pm_clk = SC_PM_CLK_PER;
111 case IMX8QM_UART3_CLK:
112 resource = SC_R_UART_3;
113 pm_clk = SC_PM_CLK_PER;
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;
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;
130 if (clk->id < IMX8QM_UART0_IPG_CLK ||
131 clk->id >= IMX8QM_CLK_END) {
132 printf("%s(Invalid clk ID #%lu)\n",
139 ret = sc_pm_get_clock_rate(-1, resource, pm_clk,
140 (sc_pm_clock_rate_t *)&rate);
142 printf("%s err %d\n", __func__, ret);
149 ulong imx8_clk_set_rate(struct clk *clk, unsigned long rate)
156 debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
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;
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;
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;
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;
183 case IMX8QM_UART0_CLK:
184 resource = SC_R_UART_0;
185 pm_clk = SC_PM_CLK_PER;
187 case IMX8QM_UART1_CLK:
188 resource = SC_R_UART_1;
189 pm_clk = SC_PM_CLK_PER;
191 case IMX8QM_UART2_CLK:
192 resource = SC_R_UART_2;
193 pm_clk = SC_PM_CLK_PER;
195 case IMX8QM_UART3_CLK:
196 resource = SC_R_UART_3;
197 pm_clk = SC_PM_CLK_PER;
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;
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;
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;
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;
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;
234 if (clk->id < IMX8QM_UART0_IPG_CLK ||
235 clk->id >= IMX8QM_CLK_END) {
236 printf("%s(Invalid clk ID #%lu)\n",
243 ret = sc_pm_set_clock_rate(-1, resource, pm_clk, &new_rate);
245 printf("%s err %d\n", __func__, ret);
252 int __imx8_clk_enable(struct clk *clk, bool enable)
258 debug("%s(#%lu)\n", __func__, 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;
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;
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;
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;
285 case IMX8QM_UART0_CLK:
286 resource = SC_R_UART_0;
287 pm_clk = SC_PM_CLK_PER;
289 case IMX8QM_UART1_CLK:
290 resource = SC_R_UART_1;
291 pm_clk = SC_PM_CLK_PER;
293 case IMX8QM_UART2_CLK:
294 resource = SC_R_UART_2;
295 pm_clk = SC_PM_CLK_PER;
297 case IMX8QM_UART3_CLK:
298 resource = SC_R_UART_3;
299 pm_clk = SC_PM_CLK_PER;
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;
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;
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;
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;
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;
334 if (clk->id < IMX8QM_UART0_IPG_CLK ||
335 clk->id >= IMX8QM_CLK_END) {
336 printf("%s(Invalid clk ID #%lu)\n",
343 ret = sc_pm_clock_enable(-1, resource, pm_clk, enable, 0);
345 printf("%s err %d\n", __func__, ret);