global: Migrate CONFIG_SYS_FSL* symbols to the CFG_SYS namespace
[platform/kernel/u-boot.git] / arch / arm / mach-imx / mx7ulp / clock.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2016 Freescale Semiconductor, Inc.
4  */
5
6 #include <common.h>
7 #include <clock_legacy.h>
8 #include <command.h>
9 #include <div64.h>
10 #include <asm/global_data.h>
11 #include <asm/io.h>
12 #include <errno.h>
13 #include <asm/arch/clock.h>
14 #include <asm/arch/sys_proto.h>
15
16 DECLARE_GLOBAL_DATA_PTR;
17
18 int get_clocks(void)
19 {
20 #ifdef CONFIG_FSL_ESDHC_IMX
21 #if CFG_SYS_FSL_ESDHC_ADDR == USDHC0_RBASE
22         gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
23 #elif CFG_SYS_FSL_ESDHC_ADDR == USDHC1_RBASE
24         gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
25 #endif
26 #endif
27         return 0;
28 }
29
30 static u32 get_fast_plat_clk(void)
31 {
32         return scg_clk_get_rate(SCG_NIC0_CLK);
33 }
34
35 static u32 get_slow_plat_clk(void)
36 {
37         return scg_clk_get_rate(SCG_NIC1_CLK);
38 }
39
40 static u32 get_ipg_clk(void)
41 {
42         return scg_clk_get_rate(SCG_NIC1_BUS_CLK);
43 }
44
45 u32 get_lpuart_clk(void)
46 {
47         int index = 0;
48
49         const u32 lpuart_array[] = {
50                 LPUART0_RBASE,
51                 LPUART1_RBASE,
52                 LPUART2_RBASE,
53                 LPUART3_RBASE,
54                 LPUART4_RBASE,
55                 LPUART5_RBASE,
56                 LPUART6_RBASE,
57                 LPUART7_RBASE,
58         };
59
60         const enum pcc_clk lpuart_pcc_clks[] = {
61                 PER_CLK_LPUART4,
62                 PER_CLK_LPUART5,
63                 PER_CLK_LPUART6,
64                 PER_CLK_LPUART7,
65         };
66
67         for (index = 0; index < 8; index++) {
68                 if (lpuart_array[index] == LPUART_BASE)
69                         break;
70         }
71
72         if (index < 4 || index > 7)
73                 return 0;
74
75         return pcc_clock_get_rate(lpuart_pcc_clks[index - 4]);
76 }
77
78 #ifdef CONFIG_SYS_I2C_IMX_LPI2C
79 int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
80 {
81         /* Set parent to FIRC DIV2 clock */
82         const enum pcc_clk lpi2c_pcc_clks[] = {
83                 PER_CLK_LPI2C4,
84                 PER_CLK_LPI2C5,
85                 PER_CLK_LPI2C6,
86                 PER_CLK_LPI2C7,
87         };
88
89         if (i2c_num < 4 || i2c_num > 7)
90                 return -EINVAL;
91
92         if (enable) {
93                 pcc_clock_enable(lpi2c_pcc_clks[i2c_num - 4], false);
94                 pcc_clock_sel(lpi2c_pcc_clks[i2c_num - 4], SCG_FIRC_DIV2_CLK);
95                 pcc_clock_enable(lpi2c_pcc_clks[i2c_num - 4], true);
96         } else {
97                 pcc_clock_enable(lpi2c_pcc_clks[i2c_num - 4], false);
98         }
99         return 0;
100 }
101
102 u32 imx_get_i2cclk(unsigned i2c_num)
103 {
104         const enum pcc_clk lpi2c_pcc_clks[] = {
105                 PER_CLK_LPI2C4,
106                 PER_CLK_LPI2C5,
107                 PER_CLK_LPI2C6,
108                 PER_CLK_LPI2C7,
109         };
110
111         if (i2c_num < 4 || i2c_num > 7)
112                 return 0;
113
114         return pcc_clock_get_rate(lpi2c_pcc_clks[i2c_num - 4]);
115 }
116 #endif
117
118 unsigned int mxc_get_clock(enum mxc_clock clk)
119 {
120         switch (clk) {
121         case MXC_ARM_CLK:
122                 return scg_clk_get_rate(SCG_CORE_CLK);
123         case MXC_AXI_CLK:
124                 return get_fast_plat_clk();
125         case MXC_AHB_CLK:
126                 return get_slow_plat_clk();
127         case MXC_IPG_CLK:
128                 return get_ipg_clk();
129         case MXC_I2C_CLK:
130                 return pcc_clock_get_rate(PER_CLK_LPI2C4);
131         case MXC_UART_CLK:
132                 return get_lpuart_clk();
133         case MXC_ESDHC_CLK:
134                 return pcc_clock_get_rate(PER_CLK_USDHC0);
135         case MXC_ESDHC2_CLK:
136                 return pcc_clock_get_rate(PER_CLK_USDHC1);
137         case MXC_DDR_CLK:
138                 return scg_clk_get_rate(SCG_DDR_CLK);
139         default:
140                 printf("Unsupported mxc_clock %d\n", clk);
141                 break;
142         }
143
144         return 0;
145 }
146
147 void init_clk_usdhc(u32 index)
148 {
149         switch (index) {
150         case 0:
151                 /*Disable the clock before configure it */
152                 pcc_clock_enable(PER_CLK_USDHC0, false);
153
154                 /* 158MHz / 1 = 158MHz */
155                 pcc_clock_sel(PER_CLK_USDHC0, SCG_NIC1_CLK);
156                 pcc_clock_div_config(PER_CLK_USDHC0, false, 1);
157                 pcc_clock_enable(PER_CLK_USDHC0, true);
158                 break;
159         case 1:
160                 /*Disable the clock before configure it */
161                 pcc_clock_enable(PER_CLK_USDHC1, false);
162
163                 /* 158MHz / 1 = 158MHz */
164                 pcc_clock_sel(PER_CLK_USDHC1, SCG_NIC1_CLK);
165                 pcc_clock_div_config(PER_CLK_USDHC1, false, 1);
166                 pcc_clock_enable(PER_CLK_USDHC1, true);
167                 break;
168         default:
169                 printf("Invalid index for USDHC %d\n", index);
170                 break;
171         }
172 }
173
174 #ifdef CONFIG_MXC_OCOTP
175
176 #define OCOTP_CTRL_PCC1_SLOT            (38)
177 #define OCOTP_CTRL_HIGH4K_PCC1_SLOT     (39)
178
179 void enable_ocotp_clk(unsigned char enable)
180 {
181         u32 val;
182
183         /*
184          * Seems the OCOTP CLOCKs have been enabled at default,
185          * check its inuse flag
186          */
187
188         val = readl(PCC1_RBASE + 4 * OCOTP_CTRL_PCC1_SLOT);
189         if (!(val & PCC_INUSE_MASK))
190                 writel(PCC_CGC_MASK, (PCC1_RBASE + 4 * OCOTP_CTRL_PCC1_SLOT));
191
192         val = readl(PCC1_RBASE + 4 * OCOTP_CTRL_HIGH4K_PCC1_SLOT);
193         if (!(val & PCC_INUSE_MASK))
194                 writel(PCC_CGC_MASK,
195                        (PCC1_RBASE + 4 * OCOTP_CTRL_HIGH4K_PCC1_SLOT));
196 }
197 #endif
198
199 void enable_usboh3_clk(unsigned char enable)
200 {
201         if (enable) {
202                 pcc_clock_enable(PER_CLK_USB0, false);
203                 pcc_clock_sel(PER_CLK_USB0, SCG_NIC1_BUS_CLK);
204                 pcc_clock_enable(PER_CLK_USB0, true);
205
206 #ifdef CONFIG_USB_MAX_CONTROLLER_COUNT
207                 if (CONFIG_USB_MAX_CONTROLLER_COUNT > 1) {
208                         pcc_clock_enable(PER_CLK_USB1, false);
209                         pcc_clock_sel(PER_CLK_USB1, SCG_NIC1_BUS_CLK);
210                         pcc_clock_enable(PER_CLK_USB1, true);
211                 }
212 #endif
213
214                 pcc_clock_enable(PER_CLK_USB_PHY, true);
215                 pcc_clock_enable(PER_CLK_USB_PL301, true);
216         } else {
217                 pcc_clock_enable(PER_CLK_USB0, false);
218                 pcc_clock_enable(PER_CLK_USB1, false);
219                 pcc_clock_enable(PER_CLK_USB_PHY, false);
220                 pcc_clock_enable(PER_CLK_USB_PL301, false);
221         }
222 }
223
224 static void lpuart_set_clk(uint32_t index, enum scg_clk clk)
225 {
226         const enum pcc_clk lpuart_pcc_clks[] = {
227                 PER_CLK_LPUART4,
228                 PER_CLK_LPUART5,
229                 PER_CLK_LPUART6,
230                 PER_CLK_LPUART7,
231         };
232
233         if (index < 4 || index > 7)
234                 return;
235
236 #ifndef CONFIG_CLK_DEBUG
237         pcc_clock_enable(lpuart_pcc_clks[index - 4], false);
238 #endif
239         pcc_clock_sel(lpuart_pcc_clks[index - 4], clk);
240         pcc_clock_enable(lpuart_pcc_clks[index - 4], true);
241 }
242
243 static void init_clk_lpuart(void)
244 {
245         u32 index = 0, i;
246
247         const u32 lpuart_array[] = {
248                 LPUART0_RBASE,
249                 LPUART1_RBASE,
250                 LPUART2_RBASE,
251                 LPUART3_RBASE,
252                 LPUART4_RBASE,
253                 LPUART5_RBASE,
254                 LPUART6_RBASE,
255                 LPUART7_RBASE,
256         };
257
258         for (i = 0; i < 8; i++) {
259                 if (lpuart_array[i] == LPUART_BASE) {
260                         index = i;
261                         break;
262                 }
263         }
264
265         lpuart_set_clk(index, SCG_SOSC_DIV2_CLK);
266 }
267
268 static void init_clk_rgpio2p(void)
269 {
270         /*Enable RGPIO2P1 clock */
271         pcc_clock_enable(PER_CLK_RGPIO2P1, true);
272
273         /*
274          * Hard code to enable RGPIO2P0 clock since it is not
275          * in clock frame for A7 domain
276          */
277         writel(PCC_CGC_MASK, (PCC0_RBASE + 0x3C));
278 }
279
280 /* Configure PLL/PFD freq */
281 void clock_init(void)
282 {
283         /*
284          * ROM has enabled clocks:
285          * A4 side: SIRC 16Mhz (DIV1-3 off),  FIRC 48Mhz (DIV1-2 on),
286          *          Non-LP-boot:  SOSC, SPLL PFD0 (scs selected)
287          * A7 side:  SPLL PFD0 (scs selected, 413Mhz),
288          *           APLL PFD0 (352Mhz), DDRCLK, all NIC clocks
289          *           A7 Plat0 (NIC0) = 176Mhz, Plat1 (NIC1) = 176Mhz,
290          *           IP BUS (NIC1_BUS) = 58.6Mhz
291          *
292          * In u-boot:
293          * 1. Enable PFD1-3 of APLL for A7 side. Enable FIRC and DIVs.
294          * 2. Enable USB PLL
295          * 3. Init the clocks of peripherals used in u-boot bu
296          *    without set rate interface.The clocks for these
297          *    peripherals are enabled in this intialization.
298          * 4.Other peripherals with set clock rate interface
299          *   does not be set in this function.
300          */
301
302         scg_a7_firc_init();
303
304         scg_a7_soscdiv_init();
305
306         scg_a7_init_core_clk();
307
308         /* APLL PFD1 = 270Mhz, PFD2=345.6Mhz, PFD3=800Mhz */
309         scg_enable_pll_pfd(SCG_APLL_PFD1_CLK, 35);
310         scg_enable_pll_pfd(SCG_APLL_PFD2_CLK, 28);
311         scg_enable_pll_pfd(SCG_APLL_PFD3_CLK, 12);
312
313         init_clk_lpuart();
314
315         init_clk_rgpio2p();
316
317         enable_usboh3_clk(1);
318 }
319
320 #ifdef CONFIG_IMX_HAB
321 void hab_caam_clock_enable(unsigned char enable)
322 {
323        if (enable)
324                pcc_clock_enable(PER_CLK_CAAM, true);
325        else
326                pcc_clock_enable(PER_CLK_CAAM, false);
327 }
328 #endif
329
330 #ifndef CONFIG_SPL_BUILD
331 /*
332  * Dump some core clockes.
333  */
334 int do_mx7_showclocks(struct cmd_tbl *cmdtp, int flag, int argc,
335                       char *const argv[])
336 {
337
338         u32 freq;
339         freq = decode_pll(PLL_A7_SPLL);
340         printf("PLL_A7_SPLL    %8d MHz\n", freq / 1000000);
341
342         freq = decode_pll(PLL_A7_APLL);
343         printf("PLL_A7_APLL    %8d MHz\n", freq / 1000000);
344
345         freq = decode_pll(PLL_USB);
346         printf("PLL_USB        %8d MHz\n", freq / 1000000);
347
348         printf("\n");
349
350         printf("CORE       %8d kHz\n", scg_clk_get_rate(SCG_CORE_CLK) / 1000);
351         printf("IPG        %8d kHz\n", mxc_get_clock(MXC_IPG_CLK) / 1000);
352         printf("UART       %8d kHz\n", mxc_get_clock(MXC_UART_CLK) / 1000);
353         printf("AHB        %8d kHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000);
354         printf("AXI        %8d kHz\n", mxc_get_clock(MXC_AXI_CLK) / 1000);
355         printf("DDR        %8d kHz\n", mxc_get_clock(MXC_DDR_CLK) / 1000);
356         printf("USDHC1     %8d kHz\n", mxc_get_clock(MXC_ESDHC_CLK) / 1000);
357         printf("USDHC2     %8d kHz\n", mxc_get_clock(MXC_ESDHC2_CLK) / 1000);
358         printf("I2C4       %8d kHz\n", mxc_get_clock(MXC_I2C_CLK) / 1000);
359
360         scg_a7_info();
361
362         return 0;
363 }
364
365 U_BOOT_CMD(
366         clocks, CONFIG_SYS_MAXARGS, 1, do_mx7_showclocks,
367         "display clocks",
368         ""
369 );
370 #endif