command: Remove the cmd_tbl_t typedef
[oweals/u-boot.git] / arch / arm / cpu / armv7 / vf610 / generic.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2013 Freescale Semiconductor, Inc.
4  */
5
6 #include <common.h>
7 #include <clock_legacy.h>
8 #include <command.h>
9 #include <cpu_func.h>
10 #include <init.h>
11 #include <net.h>
12 #include <asm/cache.h>
13 #include <asm/io.h>
14 #include <asm/arch/imx-regs.h>
15 #include <asm/arch/clock.h>
16 #include <asm/arch/crm_regs.h>
17 #include <asm/mach-imx/sys_proto.h>
18 #include <env.h>
19 #include <netdev.h>
20 #ifdef CONFIG_FSL_ESDHC_IMX
21 #include <fsl_esdhc_imx.h>
22 #endif
23
24 #ifdef CONFIG_FSL_ESDHC_IMX
25 DECLARE_GLOBAL_DATA_PTR;
26 #endif
27
28 static char soc_type[] = "xx0";
29
30 #ifdef CONFIG_MXC_OCOTP
31 void enable_ocotp_clk(unsigned char enable)
32 {
33         struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
34         u32 reg;
35
36         reg = readl(&ccm->ccgr6);
37         if (enable)
38                 reg |= CCM_CCGR6_OCOTP_CTRL_MASK;
39         else
40                 reg &= ~CCM_CCGR6_OCOTP_CTRL_MASK;
41         writel(reg, &ccm->ccgr6);
42 }
43 #endif
44
45 static u32 get_mcu_main_clk(void)
46 {
47         struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
48         u32 ccm_ccsr, ccm_cacrr, armclk_div;
49         u32 sysclk_sel, pll_pfd_sel = 0;
50         u32 freq = 0;
51
52         ccm_ccsr = readl(&ccm->ccsr);
53         sysclk_sel = ccm_ccsr & CCM_CCSR_SYS_CLK_SEL_MASK;
54         sysclk_sel >>= CCM_CCSR_SYS_CLK_SEL_OFFSET;
55
56         ccm_cacrr = readl(&ccm->cacrr);
57         armclk_div = ccm_cacrr & CCM_CACRR_ARM_CLK_DIV_MASK;
58         armclk_div >>= CCM_CACRR_ARM_CLK_DIV_OFFSET;
59         armclk_div += 1;
60
61         switch (sysclk_sel) {
62         case 0:
63                 freq = FASE_CLK_FREQ;
64                 break;
65         case 1:
66                 freq = SLOW_CLK_FREQ;
67                 break;
68         case 2:
69                 pll_pfd_sel = ccm_ccsr & CCM_CCSR_PLL2_PFD_CLK_SEL_MASK;
70                 pll_pfd_sel >>= CCM_CCSR_PLL2_PFD_CLK_SEL_OFFSET;
71                 if (pll_pfd_sel == 0)
72                         freq = PLL2_MAIN_FREQ;
73                 else if (pll_pfd_sel == 1)
74                         freq = PLL2_PFD1_FREQ;
75                 else if (pll_pfd_sel == 2)
76                         freq = PLL2_PFD2_FREQ;
77                 else if (pll_pfd_sel == 3)
78                         freq = PLL2_PFD3_FREQ;
79                 else if (pll_pfd_sel == 4)
80                         freq = PLL2_PFD4_FREQ;
81                 break;
82         case 3:
83                 freq = PLL2_MAIN_FREQ;
84                 break;
85         case 4:
86                 pll_pfd_sel = ccm_ccsr & CCM_CCSR_PLL1_PFD_CLK_SEL_MASK;
87                 pll_pfd_sel >>= CCM_CCSR_PLL1_PFD_CLK_SEL_OFFSET;
88                 if (pll_pfd_sel == 0)
89                         freq = PLL1_MAIN_FREQ;
90                 else if (pll_pfd_sel == 1)
91                         freq = PLL1_PFD1_FREQ;
92                 else if (pll_pfd_sel == 2)
93                         freq = PLL1_PFD2_FREQ;
94                 else if (pll_pfd_sel == 3)
95                         freq = PLL1_PFD3_FREQ;
96                 else if (pll_pfd_sel == 4)
97                         freq = PLL1_PFD4_FREQ;
98                 break;
99         case 5:
100                 freq = PLL3_MAIN_FREQ;
101                 break;
102         default:
103                 printf("unsupported system clock select\n");
104         }
105
106         return freq / armclk_div;
107 }
108
109 static u32 get_bus_clk(void)
110 {
111         struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
112         u32 ccm_cacrr, busclk_div;
113
114         ccm_cacrr = readl(&ccm->cacrr);
115
116         busclk_div = ccm_cacrr & CCM_CACRR_BUS_CLK_DIV_MASK;
117         busclk_div >>= CCM_CACRR_BUS_CLK_DIV_OFFSET;
118         busclk_div += 1;
119
120         return get_mcu_main_clk() / busclk_div;
121 }
122
123 static u32 get_ipg_clk(void)
124 {
125         struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
126         u32 ccm_cacrr, ipgclk_div;
127
128         ccm_cacrr = readl(&ccm->cacrr);
129
130         ipgclk_div = ccm_cacrr & CCM_CACRR_IPG_CLK_DIV_MASK;
131         ipgclk_div >>= CCM_CACRR_IPG_CLK_DIV_OFFSET;
132         ipgclk_div += 1;
133
134         return get_bus_clk() / ipgclk_div;
135 }
136
137 static u32 get_uart_clk(void)
138 {
139         return get_ipg_clk();
140 }
141
142 static u32 get_sdhc_clk(void)
143 {
144         struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
145         u32 ccm_cscmr1, ccm_cscdr2, sdhc_clk_sel, sdhc_clk_div;
146         u32 freq = 0;
147
148         ccm_cscmr1 = readl(&ccm->cscmr1);
149         sdhc_clk_sel = ccm_cscmr1 & CCM_CSCMR1_ESDHC1_CLK_SEL_MASK;
150         sdhc_clk_sel >>= CCM_CSCMR1_ESDHC1_CLK_SEL_OFFSET;
151
152         ccm_cscdr2 = readl(&ccm->cscdr2);
153         sdhc_clk_div = ccm_cscdr2 & CCM_CSCDR2_ESDHC1_CLK_DIV_MASK;
154         sdhc_clk_div >>= CCM_CSCDR2_ESDHC1_CLK_DIV_OFFSET;
155         sdhc_clk_div += 1;
156
157         switch (sdhc_clk_sel) {
158         case 0:
159                 freq = PLL3_MAIN_FREQ;
160                 break;
161         case 1:
162                 freq = PLL3_PFD3_FREQ;
163                 break;
164         case 2:
165                 freq = PLL1_PFD3_FREQ;
166                 break;
167         case 3:
168                 freq = get_bus_clk();
169                 break;
170         }
171
172         return freq / sdhc_clk_div;
173 }
174
175 u32 get_fec_clk(void)
176 {
177         struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
178         u32 ccm_cscmr2, rmii_clk_sel;
179         u32 freq = 0;
180
181         ccm_cscmr2 = readl(&ccm->cscmr2);
182         rmii_clk_sel = ccm_cscmr2 & CCM_CSCMR2_RMII_CLK_SEL_MASK;
183         rmii_clk_sel >>= CCM_CSCMR2_RMII_CLK_SEL_OFFSET;
184
185         switch (rmii_clk_sel) {
186         case 0:
187                 freq = ENET_EXTERNAL_CLK;
188                 break;
189         case 1:
190                 freq = AUDIO_EXTERNAL_CLK;
191                 break;
192         case 2:
193                 freq = PLL5_MAIN_FREQ;
194                 break;
195         case 3:
196                 freq = PLL5_MAIN_FREQ / 2;
197                 break;
198         }
199
200         return freq;
201 }
202
203 static u32 get_i2c_clk(void)
204 {
205         return get_ipg_clk();
206 }
207
208 static u32 get_dspi_clk(void)
209 {
210         return get_ipg_clk();
211 }
212
213 u32 get_lpuart_clk(void)
214 {
215         return get_uart_clk();
216 }
217
218 unsigned int mxc_get_clock(enum mxc_clock clk)
219 {
220         switch (clk) {
221         case MXC_ARM_CLK:
222                 return get_mcu_main_clk();
223         case MXC_BUS_CLK:
224                 return get_bus_clk();
225         case MXC_IPG_CLK:
226                 return get_ipg_clk();
227         case MXC_UART_CLK:
228                 return get_uart_clk();
229         case MXC_ESDHC_CLK:
230                 return get_sdhc_clk();
231         case MXC_FEC_CLK:
232                 return get_fec_clk();
233         case MXC_I2C_CLK:
234                 return get_i2c_clk();
235         case MXC_DSPI_CLK:
236                 return get_dspi_clk();
237         default:
238                 break;
239         }
240         return -1;
241 }
242
243 /* Dump some core clocks */
244 int do_vf610_showclocks(struct cmd_tbl *cmdtp, int flag, int argc,
245                         char *const argv[])
246 {
247         printf("\n");
248         printf("cpu clock : %8d MHz\n", mxc_get_clock(MXC_ARM_CLK) / 1000000);
249         printf("bus clock : %8d MHz\n", mxc_get_clock(MXC_BUS_CLK) / 1000000);
250         printf("ipg clock : %8d MHz\n", mxc_get_clock(MXC_IPG_CLK) / 1000000);
251
252         return 0;
253 }
254
255 U_BOOT_CMD(
256         clocks, CONFIG_SYS_MAXARGS, 1, do_vf610_showclocks,
257         "display clocks",
258         ""
259 );
260
261 #ifdef CONFIG_FEC_MXC
262 __weak void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
263 {
264         struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
265         struct fuse_bank *bank = &ocotp->bank[4];
266         struct fuse_bank4_regs *fuse =
267                 (struct fuse_bank4_regs *)bank->fuse_regs;
268
269         u32 value = readl(&fuse->mac_addr0);
270         mac[0] = (value >> 8);
271         mac[1] = value;
272
273         value = readl(&fuse->mac_addr1);
274         mac[2] = value >> 24;
275         mac[3] = value >> 16;
276         mac[4] = value >> 8;
277         mac[5] = value;
278 }
279 #endif
280
281 u32 get_cpu_rev(void)
282 {
283         return MXC_CPU_VF610 << 12;
284 }
285
286 #if defined(CONFIG_DISPLAY_CPUINFO)
287 static char *get_reset_cause(void)
288 {
289         u32 cause;
290         struct src *src_regs = (struct src *)SRC_BASE_ADDR;
291
292         cause = readl(&src_regs->srsr);
293         writel(cause, &src_regs->srsr);
294
295         if (cause & SRC_SRSR_POR_RST)
296                 return "POWER ON RESET";
297         else if (cause & SRC_SRSR_WDOG_A5)
298                 return "WDOG A5";
299         else if (cause & SRC_SRSR_WDOG_M4)
300                 return "WDOG M4";
301         else if (cause & SRC_SRSR_JTAG_RST)
302                 return "JTAG HIGH-Z";
303         else if (cause & SRC_SRSR_SW_RST)
304                 return "SW RESET";
305         else if (cause & SRC_SRSR_RESETB)
306                 return "EXTERNAL RESET";
307         else
308                 return "unknown reset";
309 }
310
311 int print_cpuinfo(void)
312 {
313         printf("CPU: Freescale Vybrid VF%s at %d MHz\n",
314                soc_type, mxc_get_clock(MXC_ARM_CLK) / 1000000);
315         printf("Reset cause: %s\n", get_reset_cause());
316
317         return 0;
318 }
319 #endif
320
321 int arch_cpu_init(void)
322 {
323         struct mscm *mscm = (struct mscm *)MSCM_BASE_ADDR;
324
325         soc_type[0] = mscm->cpxcount ? '6' : '5'; /*Dual Core => VF6x0 */
326         soc_type[1] = mscm->cpxcfg1 ? '1' : '0'; /* L2 Cache => VFx10 */
327
328         return 0;
329 }
330
331 #ifdef CONFIG_ARCH_MISC_INIT
332 int arch_misc_init(void)
333 {
334         char soc[6];
335
336         strcpy(soc, "vf");
337         strcat(soc, soc_type);
338         env_set("soc", soc);
339
340         return 0;
341 }
342 #endif
343
344 int cpu_eth_init(bd_t *bis)
345 {
346         int rc = -ENODEV;
347
348 #if defined(CONFIG_FEC_MXC)
349         rc = fecmxc_initialize(bis);
350 #endif
351
352         return rc;
353 }
354
355 #ifdef CONFIG_FSL_ESDHC_IMX
356 int cpu_mmc_init(bd_t *bis)
357 {
358         return fsl_esdhc_mmc_init(bis);
359 }
360 #endif
361
362 int get_clocks(void)
363 {
364 #ifdef CONFIG_FSL_ESDHC_IMX
365         gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
366 #endif
367         return 0;
368 }
369
370 #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
371 void enable_caches(void)
372 {
373 #if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
374         enum dcache_option option = DCACHE_WRITETHROUGH;
375 #else
376         enum dcache_option option = DCACHE_WRITEBACK;
377 #endif
378         dcache_enable();
379         icache_enable();
380
381     /* Enable caching on OCRAM */
382         mmu_set_region_dcache_behaviour(IRAM_BASE_ADDR, IRAM_SIZE, option);
383 }
384 #endif
385
386 #ifdef CONFIG_SYS_I2C_MXC
387 /* i2c_num can be from 0 - 3 */
388 int enable_i2c_clk(unsigned char enable, unsigned int i2c_num)
389 {
390         struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
391
392         switch (i2c_num) {
393         case 0:
394                 clrsetbits_le32(&ccm->ccgr4, CCM_CCGR4_I2C0_CTRL_MASK,
395                                 CCM_CCGR4_I2C0_CTRL_MASK);
396         case 2:
397                 clrsetbits_le32(&ccm->ccgr10, CCM_CCGR10_I2C2_CTRL_MASK,
398                                 CCM_CCGR10_I2C2_CTRL_MASK);
399                 break;
400         default:
401                 return -EINVAL;
402         }
403
404         return 0;
405 }
406 #endif