1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * SPL specific code for Compulab CM-FX6 board
4  *
5  * Copyright (C) 2014, Compulab Ltd - http://compulab.co.il/
6  *
7  * Author: Nikita Kiryanov <nikita@compulab.co.il>
8  */
9 
10 #include <common.h>
11 #include <clock_legacy.h>
12 #include <hang.h>
13 #include <init.h>
14 #include <spl.h>
15 #include <asm/io.h>
16 #include <asm/gpio.h>
17 #include <asm/arch/mx6-ddr.h>
18 #include <asm/arch/clock.h>
19 #include <asm/arch/sys_proto.h>
20 #include <asm/arch/crm_regs.h>
21 #include <asm/mach-imx/iomux-v3.h>
22 #include <fsl_esdhc_imx.h>
23 #include <linux/delay.h>
24 #include "common.h"
25 
26 enum ddr_config {
27 	DDR_16BIT_256MB,
28 	DDR_32BIT_512MB,
29 	DDR_32BIT_1GB,
30 	DDR_64BIT_1GB,
31 	DDR_64BIT_2GB,
32 	DDR_64BIT_4GB,
33 	DDR_UNKNOWN,
34 };
35 
36 /*
37  * Below DRAM_RESET[DDR_SEL] = 0 which is incorrect according to
38  * Freescale QRM, but this is exactly the value used by the automatic
39  * calibration script and it works also in all our tests, so we leave
40  * it as is at this point.
41  */
42 #define CM_FX6_DDR_IOMUX_CFG \
43 	.dram_sdqs0	= 0x00000038, \
44 	.dram_sdqs1	= 0x00000038, \
45 	.dram_sdqs2	= 0x00000038, \
46 	.dram_sdqs3	= 0x00000038, \
47 	.dram_sdqs4	= 0x00000038, \
48 	.dram_sdqs5	= 0x00000038, \
49 	.dram_sdqs6	= 0x00000038, \
50 	.dram_sdqs7	= 0x00000038, \
51 	.dram_dqm0	= 0x00000038, \
52 	.dram_dqm1	= 0x00000038, \
53 	.dram_dqm2	= 0x00000038, \
54 	.dram_dqm3	= 0x00000038, \
55 	.dram_dqm4	= 0x00000038, \
56 	.dram_dqm5	= 0x00000038, \
57 	.dram_dqm6	= 0x00000038, \
58 	.dram_dqm7	= 0x00000038, \
59 	.dram_cas	= 0x00000038, \
60 	.dram_ras	= 0x00000038, \
61 	.dram_sdclk_0	= 0x00000038, \
62 	.dram_sdclk_1	= 0x00000038, \
63 	.dram_sdcke0	= 0x00003000, \
64 	.dram_sdcke1	= 0x00003000, \
65 	.dram_reset	= 0x00000038, \
66 	.dram_sdba2	= 0x00000000, \
67 	.dram_sdodt0	= 0x00000038, \
68 	.dram_sdodt1	= 0x00000038,
69 
70 #define CM_FX6_GPR_IOMUX_CFG \
71 	.grp_b0ds	= 0x00000038, \
72 	.grp_b1ds	= 0x00000038, \
73 	.grp_b2ds	= 0x00000038, \
74 	.grp_b3ds	= 0x00000038, \
75 	.grp_b4ds	= 0x00000038, \
76 	.grp_b5ds	= 0x00000038, \
77 	.grp_b6ds	= 0x00000038, \
78 	.grp_b7ds	= 0x00000038, \
79 	.grp_addds	= 0x00000038, \
80 	.grp_ddrmode_ctl = 0x00020000, \
81 	.grp_ddrpke	= 0x00000000, \
82 	.grp_ddrmode	= 0x00020000, \
83 	.grp_ctlds	= 0x00000038, \
84 	.grp_ddr_type	= 0x000C0000,
85 
86 static struct mx6sdl_iomux_ddr_regs ddr_iomux_s = { CM_FX6_DDR_IOMUX_CFG };
87 static struct mx6sdl_iomux_grp_regs grp_iomux_s = { CM_FX6_GPR_IOMUX_CFG };
88 static struct mx6dq_iomux_ddr_regs ddr_iomux_q = { CM_FX6_DDR_IOMUX_CFG };
89 static struct mx6dq_iomux_grp_regs grp_iomux_q = { CM_FX6_GPR_IOMUX_CFG };
90 
91 static struct mx6_mmdc_calibration cm_fx6_calib_s = {
92 	.p0_mpwldectrl0	= 0x005B0061,
93 	.p0_mpwldectrl1	= 0x004F0055,
94 	.p0_mpdgctrl0	= 0x0314030C,
95 	.p0_mpdgctrl1	= 0x025C0268,
96 	.p0_mprddlctl	= 0x42464646,
97 	.p0_mpwrdlctl	= 0x36322C34,
98 };
99 
100 static struct mx6_ddr_sysinfo cm_fx6_sysinfo_s = {
101 	.cs1_mirror	= 1,
102 	.cs_density	= 16,
103 	.bi_on		= 1,
104 	.rtt_nom	= 1,
105 	.rtt_wr		= 0,
106 	.ralat		= 5,
107 	.walat		= 1,
108 	.mif3_mode	= 3,
109 	.rst_to_cke	= 0x23,
110 	.sde_to_rst	= 0x10,
111 };
112 
113 static struct mx6_ddr3_cfg cm_fx6_ddr3_cfg_s = {
114 	.mem_speed	= 800,
115 	.density	= 4,
116 	.rowaddr	= 14,
117 	.coladdr	= 10,
118 	.pagesz		= 2,
119 	.trcd		= 1800,
120 	.trcmin		= 5200,
121 	.trasmin	= 3600,
122 	.SRT		= 0,
123 };
124 
spl_mx6s_dram_init(enum ddr_config dram_config,bool reset)125 static void spl_mx6s_dram_init(enum ddr_config dram_config, bool reset)
126 {
127 	if (reset)
128 		((struct mmdc_p_regs *)MX6_MMDC_P0_MDCTL)->mdmisc = 2;
129 
130 	switch (dram_config) {
131 	case DDR_16BIT_256MB:
132 		cm_fx6_sysinfo_s.dsize = 0;
133 		cm_fx6_sysinfo_s.ncs = 1;
134 		break;
135 	case DDR_32BIT_512MB:
136 		cm_fx6_sysinfo_s.dsize = 1;
137 		cm_fx6_sysinfo_s.ncs = 1;
138 		break;
139 	case DDR_32BIT_1GB:
140 		cm_fx6_sysinfo_s.dsize = 1;
141 		cm_fx6_sysinfo_s.ncs = 2;
142 		break;
143 	default:
144 		puts("Tried to setup invalid DDR configuration\n");
145 		hang();
146 	}
147 
148 	mx6_dram_cfg(&cm_fx6_sysinfo_s, &cm_fx6_calib_s, &cm_fx6_ddr3_cfg_s);
149 	udelay(100);
150 }
151 
152 static struct mx6_mmdc_calibration cm_fx6_calib_q = {
153 	.p0_mpwldectrl0	= 0x00630068,
154 	.p0_mpwldectrl1	= 0x0068005D,
155 	.p0_mpdgctrl0	= 0x04140428,
156 	.p0_mpdgctrl1	= 0x037C037C,
157 	.p0_mprddlctl	= 0x3C30303A,
158 	.p0_mpwrdlctl	= 0x3A344038,
159 	.p1_mpwldectrl0	= 0x0035004C,
160 	.p1_mpwldectrl1	= 0x00170026,
161 	.p1_mpdgctrl0	= 0x0374037C,
162 	.p1_mpdgctrl1	= 0x0350032C,
163 	.p1_mprddlctl	= 0x30322A3C,
164 	.p1_mpwrdlctl	= 0x48304A3E,
165 };
166 
167 static struct mx6_ddr_sysinfo cm_fx6_sysinfo_q = {
168 	.cs_density	= 16,
169 	.cs1_mirror	= 1,
170 	.bi_on		= 1,
171 	.rtt_nom	= 1,
172 	.rtt_wr		= 0,
173 	.ralat		= 5,
174 	.walat		= 1,
175 	.mif3_mode	= 3,
176 	.rst_to_cke	= 0x23,
177 	.sde_to_rst	= 0x10,
178 	.refsel = 1,		/* Refresh cycles at 32KHz */
179 	.refr = 7,		/* 8 refresh commands per refresh cycle */
180 };
181 
182 static struct mx6_ddr3_cfg cm_fx6_ddr3_cfg_q = {
183 	.mem_speed	= 1066,
184 	.density	= 4,
185 	.rowaddr	= 14,
186 	.coladdr	= 10,
187 	.pagesz		= 2,
188 	.trcd		= 1324,
189 	.trcmin		= 59500,
190 	.trasmin	= 9750,
191 	.SRT		= 0,
192 };
193 
spl_mx6q_dram_init(enum ddr_config dram_config,bool reset)194 static void spl_mx6q_dram_init(enum ddr_config dram_config, bool reset)
195 {
196 	if (reset)
197 		((struct mmdc_p_regs *)MX6_MMDC_P0_MDCTL)->mdmisc = 2;
198 
199 	cm_fx6_ddr3_cfg_q.rowaddr = 14;
200 	switch (dram_config) {
201 	case DDR_16BIT_256MB:
202 		cm_fx6_sysinfo_q.dsize = 0;
203 		cm_fx6_sysinfo_q.ncs = 1;
204 		break;
205 	case DDR_32BIT_512MB:
206 		cm_fx6_sysinfo_q.dsize = 1;
207 		cm_fx6_sysinfo_q.ncs = 1;
208 		break;
209 	case DDR_64BIT_1GB:
210 		cm_fx6_sysinfo_q.dsize = 2;
211 		cm_fx6_sysinfo_q.ncs = 1;
212 		break;
213 	case DDR_64BIT_2GB:
214 		cm_fx6_sysinfo_q.dsize = 2;
215 		cm_fx6_sysinfo_q.ncs = 2;
216 		break;
217 	case DDR_64BIT_4GB:
218 		cm_fx6_sysinfo_q.dsize = 2;
219 		cm_fx6_sysinfo_q.ncs = 2;
220 		cm_fx6_ddr3_cfg_q.rowaddr = 15;
221 		break;
222 	default:
223 		puts("Tried to setup invalid DDR configuration\n");
224 		hang();
225 	}
226 
227 	mx6_dram_cfg(&cm_fx6_sysinfo_q, &cm_fx6_calib_q, &cm_fx6_ddr3_cfg_q);
228 	udelay(100);
229 }
230 
cm_fx6_spl_dram_init(void)231 static int cm_fx6_spl_dram_init(void)
232 {
233 	unsigned long bank1_size, bank2_size;
234 
235 	switch (get_cpu_type()) {
236 	case MXC_CPU_MX6SOLO:
237 		mx6sdl_dram_iocfg(64, &ddr_iomux_s, &grp_iomux_s);
238 
239 		spl_mx6s_dram_init(DDR_32BIT_1GB, false);
240 		bank1_size = get_ram_size((long int *)PHYS_SDRAM_1, 0x80000000);
241 		bank2_size = get_ram_size((long int *)PHYS_SDRAM_2, 0x80000000);
242 		if (bank1_size == 0x20000000) {
243 			if (bank2_size == 0x20000000)
244 				return 0;
245 
246 			spl_mx6s_dram_init(DDR_32BIT_512MB, true);
247 			return 0;
248 		}
249 
250 		spl_mx6s_dram_init(DDR_16BIT_256MB, true);
251 		bank1_size = get_ram_size((long int *)PHYS_SDRAM_1, 0x80000000);
252 		if (bank1_size == 0x10000000)
253 			return 0;
254 
255 		break;
256 	case MXC_CPU_MX6D:
257 	case MXC_CPU_MX6Q:
258 		mx6dq_dram_iocfg(64, &ddr_iomux_q, &grp_iomux_q);
259 
260 		spl_mx6q_dram_init(DDR_64BIT_4GB, false);
261 		bank1_size = get_ram_size((long int *)PHYS_SDRAM_1, 0x80000000);
262 		if (bank1_size == 0x80000000)
263 			return 0;
264 
265 		if (bank1_size == 0x40000000) {
266 			bank2_size = get_ram_size((long int *)PHYS_SDRAM_2,
267 								0x80000000);
268 			if (bank2_size == 0x40000000) {
269 				/* Don't do a full reset here */
270 				spl_mx6q_dram_init(DDR_64BIT_2GB, false);
271 			} else {
272 				spl_mx6q_dram_init(DDR_64BIT_1GB, true);
273 			}
274 
275 			return 0;
276 		}
277 
278 		spl_mx6q_dram_init(DDR_32BIT_512MB, true);
279 		bank1_size = get_ram_size((long int *)PHYS_SDRAM_1, 0x80000000);
280 		if (bank1_size == 0x20000000)
281 			return 0;
282 
283 		spl_mx6q_dram_init(DDR_16BIT_256MB, true);
284 		bank1_size = get_ram_size((long int *)PHYS_SDRAM_1, 0x80000000);
285 		if (bank1_size == 0x10000000)
286 			return 0;
287 
288 		break;
289 	}
290 
291 	return -1;
292 }
293 
294 static iomux_v3_cfg_t const uart4_pads[] = {
295 	IOMUX_PADS(PAD_KEY_COL0__UART4_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)),
296 	IOMUX_PADS(PAD_KEY_ROW0__UART4_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)),
297 };
298 
cm_fx6_setup_uart(void)299 static void cm_fx6_setup_uart(void)
300 {
301 	SETUP_IOMUX_PADS(uart4_pads);
302 	enable_uart_clk(1);
303 }
304 
305 #ifdef CONFIG_SPL_SPI_SUPPORT
cm_fx6_setup_ecspi(void)306 static void cm_fx6_setup_ecspi(void)
307 {
308 	cm_fx6_set_ecspi_iomux();
309 	enable_spi_clk(1, 0);
310 }
311 #else
cm_fx6_setup_ecspi(void)312 static void cm_fx6_setup_ecspi(void) { }
313 #endif
314 
board_init_f(ulong dummy)315 void board_init_f(ulong dummy)
316 {
317 	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
318 
319 	/*
320 	 * We don't use DMA in SPL, but we do need it in U-Boot. U-Boot
321 	 * initializes DMA very early (before all board code), so the only
322 	 * opportunity we have to initialize APBHDMA clocks is in SPL.
323 	 */
324 	setbits_le32(&mxc_ccm->CCGR0, MXC_CCM_CCGR0_APBHDMA_MASK);
325 	enable_usdhc_clk(1, 2);
326 
327 	arch_cpu_init();
328 	timer_init();
329 	cm_fx6_setup_ecspi();
330 	cm_fx6_setup_uart();
331 	get_clocks();
332 	preloader_console_init();
333 	gpio_direction_output(CM_FX6_GREEN_LED, 1);
334 	if (cm_fx6_spl_dram_init()) {
335 		puts("!!!ERROR!!! DRAM detection failed!!!\n");
336 		hang();
337 	}
338 }
339 
board_boot_order(u32 * spl_boot_list)340 void board_boot_order(u32 *spl_boot_list)
341 {
342 	spl_boot_list[0] = spl_boot_device();
343 	switch (spl_boot_list[0]) {
344 	case BOOT_DEVICE_SPI:
345 		spl_boot_list[1] = BOOT_DEVICE_MMC1;
346 		break;
347 	case BOOT_DEVICE_MMC1:
348 		spl_boot_list[1] = BOOT_DEVICE_SPI;
349 		break;
350 	}
351 }
352 
353 #ifdef CONFIG_SPL_MMC_SUPPORT
354 static struct fsl_esdhc_cfg usdhc_cfg = {
355 	.esdhc_base = USDHC3_BASE_ADDR,
356 	.max_bus_width = 4,
357 };
358 
board_mmc_init(struct bd_info * bis)359 int board_mmc_init(struct bd_info *bis)
360 {
361 	cm_fx6_set_usdhc_iomux();
362 
363 	usdhc_cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
364 
365 	return fsl_esdhc_initialize(bis, &usdhc_cfg);
366 }
367 #endif
368