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