1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2016 Amarula Solutions B.V.
4 * Copyright (C) 2016 Engicam S.r.l.
5 * Author: Jagan Teki <jagan@amarulasolutions.com>
6 */
7
8#include <common.h>
9#include <image.h>
10#include <init.h>
11#include <serial.h>
12#include <spl.h>
13#include <linux/delay.h>
14
15#include <asm/io.h>
16#include <asm/gpio.h>
17#include <linux/sizes.h>
18
19#include <asm/arch/clock.h>
20#include <asm/arch/crm_regs.h>
21#include <asm/arch/iomux.h>
22#include <asm/arch/mx6-ddr.h>
23#include <asm/arch/mx6-pins.h>
24#include <asm/arch/sys_proto.h>
25
26#include <asm/mach-imx/iomux-v3.h>
27#include <asm/mach-imx/video.h>
28
29#ifdef CONFIG_SPL_LOAD_FIT
30int board_fit_config_name_match(const char *name)
31{
32        if (is_mx6dq() && !strcmp(name, "imx6q-icore"))
33                return 0;
34        else if (is_mx6dq() && !strcmp(name, "imx6q-icore-rqs"))
35                return 0;
36        else if (is_mx6dq() && !strcmp(name, "imx6q-icore-mipi"))
37                return 0;
38        else if ((is_mx6dl() || is_mx6solo()) && !strcmp(name, "imx6dl-icore"))
39                return 0;
40        else if ((is_mx6dl() || is_mx6solo()) && !strcmp(name, "imx6dl-icore-rqs"))
41                return 0;
42        else if ((is_mx6dl() || is_mx6solo()) && !strcmp(name, "imx6dl-icore-mipi"))
43                return 0;
44        else
45                return -1;
46}
47#endif
48
49#ifdef CONFIG_ENV_IS_IN_MMC
50void board_boot_order(u32 *spl_boot_list)
51{
52	u32 bmode = imx6_src_get_boot_mode();
53	u8 boot_dev = BOOT_DEVICE_MMC1;
54
55	switch ((bmode & IMX6_BMODE_MASK) >> IMX6_BMODE_SHIFT) {
56	case IMX6_BMODE_SD:
57	case IMX6_BMODE_ESD:
58		/* SD/eSD - BOOT_DEVICE_MMC1 */
59		break;
60	case IMX6_BMODE_MMC:
61	case IMX6_BMODE_EMMC:
62		/* MMC/eMMC */
63		boot_dev = BOOT_DEVICE_MMC2;
64		break;
65	default:
66		/* Default - BOOT_DEVICE_MMC1 */
67		printf("Wrong board boot order\n");
68		break;
69	}
70
71	spl_boot_list[0] = boot_dev;
72}
73#endif
74
75#ifdef CONFIG_SPL_OS_BOOT
76int spl_start_uboot(void)
77{
78	/* break into full u-boot on 'c' */
79	if (serial_tstc() && serial_getc() == 'c')
80		return 1;
81
82	return 0;
83}
84#endif
85
86#ifdef CONFIG_MX6QDL
87/*
88 * Driving strength:
89 *   0x30 == 40 Ohm
90 *   0x28 == 48 Ohm
91 */
92#define IMX6DQ_DRIVE_STRENGTH		0x30
93#define IMX6SDL_DRIVE_STRENGTH		0x28
94
95/* configure MX6Q/DUAL mmdc DDR io registers */
96static struct mx6dq_iomux_ddr_regs mx6dq_ddr_ioregs = {
97	.dram_sdqs0 = IMX6DQ_DRIVE_STRENGTH,
98	.dram_sdqs1 = IMX6DQ_DRIVE_STRENGTH,
99	.dram_sdqs2 = IMX6DQ_DRIVE_STRENGTH,
100	.dram_sdqs3 = IMX6DQ_DRIVE_STRENGTH,
101	.dram_sdqs4 = IMX6DQ_DRIVE_STRENGTH,
102	.dram_sdqs5 = IMX6DQ_DRIVE_STRENGTH,
103	.dram_sdqs6 = IMX6DQ_DRIVE_STRENGTH,
104	.dram_sdqs7 = IMX6DQ_DRIVE_STRENGTH,
105	.dram_dqm0 = IMX6DQ_DRIVE_STRENGTH,
106	.dram_dqm1 = IMX6DQ_DRIVE_STRENGTH,
107	.dram_dqm2 = IMX6DQ_DRIVE_STRENGTH,
108	.dram_dqm3 = IMX6DQ_DRIVE_STRENGTH,
109	.dram_dqm4 = IMX6DQ_DRIVE_STRENGTH,
110	.dram_dqm5 = IMX6DQ_DRIVE_STRENGTH,
111	.dram_dqm6 = IMX6DQ_DRIVE_STRENGTH,
112	.dram_dqm7 = IMX6DQ_DRIVE_STRENGTH,
113	.dram_cas = IMX6DQ_DRIVE_STRENGTH,
114	.dram_ras = IMX6DQ_DRIVE_STRENGTH,
115	.dram_sdclk_0 = IMX6DQ_DRIVE_STRENGTH,
116	.dram_sdclk_1 = IMX6DQ_DRIVE_STRENGTH,
117	.dram_reset = IMX6DQ_DRIVE_STRENGTH,
118	.dram_sdcke0 = IMX6DQ_DRIVE_STRENGTH,
119	.dram_sdcke1 = IMX6DQ_DRIVE_STRENGTH,
120	.dram_sdba2 = 0x00000000,
121	.dram_sdodt0 = IMX6DQ_DRIVE_STRENGTH,
122	.dram_sdodt1 = IMX6DQ_DRIVE_STRENGTH,
123};
124
125/* configure MX6Q/DUAL mmdc GRP io registers */
126static struct mx6dq_iomux_grp_regs mx6dq_grp_ioregs = {
127	.grp_b0ds = IMX6DQ_DRIVE_STRENGTH,
128	.grp_b1ds = IMX6DQ_DRIVE_STRENGTH,
129	.grp_b2ds = IMX6DQ_DRIVE_STRENGTH,
130	.grp_b3ds = IMX6DQ_DRIVE_STRENGTH,
131	.grp_b4ds = IMX6DQ_DRIVE_STRENGTH,
132	.grp_b5ds = IMX6DQ_DRIVE_STRENGTH,
133	.grp_b6ds = IMX6DQ_DRIVE_STRENGTH,
134	.grp_b7ds = IMX6DQ_DRIVE_STRENGTH,
135	.grp_addds = IMX6DQ_DRIVE_STRENGTH,
136	.grp_ddrmode_ctl = 0x00020000,
137	.grp_ddrpke = 0x00000000,
138	.grp_ddrmode = 0x00020000,
139	.grp_ctlds = IMX6DQ_DRIVE_STRENGTH,
140	.grp_ddr_type = 0x000c0000,
141};
142
143/* configure MX6SOLO/DUALLITE mmdc DDR io registers */
144struct mx6sdl_iomux_ddr_regs mx6sdl_ddr_ioregs = {
145	.dram_sdclk_0 = IMX6SDL_DRIVE_STRENGTH,
146	.dram_sdclk_1 = IMX6SDL_DRIVE_STRENGTH,
147	.dram_cas = IMX6SDL_DRIVE_STRENGTH,
148	.dram_ras = IMX6SDL_DRIVE_STRENGTH,
149	.dram_reset = IMX6SDL_DRIVE_STRENGTH,
150	.dram_sdcke0 = IMX6SDL_DRIVE_STRENGTH,
151	.dram_sdcke1 = IMX6SDL_DRIVE_STRENGTH,
152	.dram_sdba2 = 0x00000000,
153	.dram_sdodt0 = IMX6SDL_DRIVE_STRENGTH,
154	.dram_sdodt1 = IMX6SDL_DRIVE_STRENGTH,
155	.dram_sdqs0 = IMX6SDL_DRIVE_STRENGTH,
156	.dram_sdqs1 = IMX6SDL_DRIVE_STRENGTH,
157	.dram_sdqs2 = IMX6SDL_DRIVE_STRENGTH,
158	.dram_sdqs3 = IMX6SDL_DRIVE_STRENGTH,
159	.dram_sdqs4 = IMX6SDL_DRIVE_STRENGTH,
160	.dram_sdqs5 = IMX6SDL_DRIVE_STRENGTH,
161	.dram_sdqs6 = IMX6SDL_DRIVE_STRENGTH,
162	.dram_sdqs7 = IMX6SDL_DRIVE_STRENGTH,
163	.dram_dqm0 = IMX6SDL_DRIVE_STRENGTH,
164	.dram_dqm1 = IMX6SDL_DRIVE_STRENGTH,
165	.dram_dqm2 = IMX6SDL_DRIVE_STRENGTH,
166	.dram_dqm3 = IMX6SDL_DRIVE_STRENGTH,
167	.dram_dqm4 = IMX6SDL_DRIVE_STRENGTH,
168	.dram_dqm5 = IMX6SDL_DRIVE_STRENGTH,
169	.dram_dqm6 = IMX6SDL_DRIVE_STRENGTH,
170	.dram_dqm7 = IMX6SDL_DRIVE_STRENGTH,
171};
172
173/* configure MX6SOLO/DUALLITE mmdc GRP io registers */
174struct mx6sdl_iomux_grp_regs mx6sdl_grp_ioregs = {
175	.grp_ddr_type = 0x000c0000,
176	.grp_ddrmode_ctl = 0x00020000,
177	.grp_ddrpke = 0x00000000,
178	.grp_addds = IMX6SDL_DRIVE_STRENGTH,
179	.grp_ctlds = IMX6SDL_DRIVE_STRENGTH,
180	.grp_ddrmode = 0x00020000,
181	.grp_b0ds = IMX6SDL_DRIVE_STRENGTH,
182	.grp_b1ds = IMX6SDL_DRIVE_STRENGTH,
183	.grp_b2ds = IMX6SDL_DRIVE_STRENGTH,
184	.grp_b3ds = IMX6SDL_DRIVE_STRENGTH,
185	.grp_b4ds = IMX6SDL_DRIVE_STRENGTH,
186	.grp_b5ds = IMX6SDL_DRIVE_STRENGTH,
187	.grp_b6ds = IMX6SDL_DRIVE_STRENGTH,
188	.grp_b7ds = IMX6SDL_DRIVE_STRENGTH,
189};
190
191/* mt41j256 */
192static struct mx6_ddr3_cfg mt41j256 = {
193	.mem_speed = 1066,
194	.density = 2,
195	.width = 16,
196	.banks = 8,
197	.rowaddr = 13,
198	.coladdr = 10,
199	.pagesz = 2,
200	.trcd = 1375,
201	.trcmin = 4875,
202	.trasmin = 3500,
203	.SRT = 0,
204};
205
206static struct mx6_mmdc_calibration mx6dq_mmdc_calib = {
207	.p0_mpwldectrl0 = 0x000E0009,
208	.p0_mpwldectrl1 = 0x0018000E,
209	.p1_mpwldectrl0 = 0x00000007,
210	.p1_mpwldectrl1 = 0x00000000,
211	.p0_mpdgctrl0 = 0x43280334,
212	.p0_mpdgctrl1 = 0x031C0314,
213	.p1_mpdgctrl0 = 0x4318031C,
214	.p1_mpdgctrl1 = 0x030C0258,
215	.p0_mprddlctl = 0x3E343A40,
216	.p1_mprddlctl = 0x383C3844,
217	.p0_mpwrdlctl = 0x40404440,
218	.p1_mpwrdlctl = 0x4C3E4446,
219};
220
221/* DDR 64bit */
222static struct mx6_ddr_sysinfo mem_q = {
223	.ddr_type	= DDR_TYPE_DDR3,
224	.dsize		= 2,
225	.cs1_mirror	= 0,
226	/* config for full 4GB range so that get_mem_size() works */
227	.cs_density	= 32,
228	.ncs		= 1,
229	.bi_on		= 1,
230	.rtt_nom	= 2,
231	.rtt_wr		= 2,
232	.ralat		= 5,
233	.walat		= 0,
234	.mif3_mode	= 3,
235	.rst_to_cke	= 0x23,
236	.sde_to_rst	= 0x10,
237};
238
239static struct mx6_mmdc_calibration mx6dl_mmdc_calib = {
240	.p0_mpwldectrl0 = 0x001F0024,
241	.p0_mpwldectrl1 = 0x00110018,
242	.p1_mpwldectrl0 = 0x001F0024,
243	.p1_mpwldectrl1 = 0x00110018,
244	.p0_mpdgctrl0 = 0x4230022C,
245	.p0_mpdgctrl1 = 0x02180220,
246	.p1_mpdgctrl0 = 0x42440248,
247	.p1_mpdgctrl1 = 0x02300238,
248	.p0_mprddlctl = 0x44444A48,
249	.p1_mprddlctl = 0x46484A42,
250	.p0_mpwrdlctl = 0x38383234,
251	.p1_mpwrdlctl = 0x3C34362E,
252};
253
254/* DDR 64bit 1GB */
255static struct mx6_ddr_sysinfo mem_dl = {
256	.dsize		= 2,
257	.cs1_mirror	= 0,
258	/* config for full 4GB range so that get_mem_size() works */
259	.cs_density	= 32,
260	.ncs		= 1,
261	.bi_on		= 1,
262	.rtt_nom	= 1,
263	.rtt_wr		= 1,
264	.ralat		= 5,
265	.walat		= 0,
266	.mif3_mode	= 3,
267	.rst_to_cke	= 0x23,
268	.sde_to_rst	= 0x10,
269};
270
271/* DDR 32bit 512MB */
272static struct mx6_ddr_sysinfo mem_s = {
273	.dsize		= 1,
274	.cs1_mirror	= 0,
275	/* config for full 4GB range so that get_mem_size() works */
276	.cs_density	= 32,
277	.ncs		= 1,
278	.bi_on		= 1,
279	.rtt_nom	= 1,
280	.rtt_wr		= 1,
281	.ralat		= 5,
282	.walat		= 0,
283	.mif3_mode	= 3,
284	.rst_to_cke	= 0x23,
285	.sde_to_rst	= 0x10,
286};
287#endif /* CONFIG_MX6QDL */
288
289#ifdef CONFIG_MX6UL
290static struct mx6ul_iomux_grp_regs mx6_grp_ioregs = {
291	.grp_addds = 0x00000030,
292	.grp_ddrmode_ctl = 0x00020000,
293	.grp_b0ds = 0x00000030,
294	.grp_ctlds = 0x00000030,
295	.grp_b1ds = 0x00000030,
296	.grp_ddrpke = 0x00000000,
297	.grp_ddrmode = 0x00020000,
298	.grp_ddr_type = 0x000c0000,
299};
300
301static struct mx6ul_iomux_ddr_regs mx6_ddr_ioregs = {
302	.dram_dqm0 = 0x00000030,
303	.dram_dqm1 = 0x00000030,
304	.dram_ras = 0x00000030,
305	.dram_cas = 0x00000030,
306	.dram_odt0 = 0x00000030,
307	.dram_odt1 = 0x00000030,
308	.dram_sdba2 = 0x00000000,
309	.dram_sdclk_0 = 0x00000008,
310	.dram_sdqs0 = 0x00000038,
311	.dram_sdqs1 = 0x00000030,
312	.dram_reset = 0x00000030,
313};
314
315static struct mx6_mmdc_calibration mx6_mmcd_calib = {
316	.p0_mpwldectrl0 = 0x00070007,
317	.p0_mpdgctrl0 = 0x41490145,
318	.p0_mprddlctl = 0x40404546,
319	.p0_mpwrdlctl = 0x4040524D,
320};
321
322struct mx6_ddr_sysinfo ddr_sysinfo = {
323	.dsize = 0,
324	.cs_density = 20,
325	.ncs = 1,
326	.cs1_mirror = 0,
327	.rtt_wr = 2,
328	.rtt_nom = 1,		/* RTT_Nom = RZQ/2 */
329	.walat = 1,		/* Write additional latency */
330	.ralat = 5,		/* Read additional latency */
331	.mif3_mode = 3,		/* Command prediction working mode */
332	.bi_on = 1,		/* Bank interleaving enabled */
333	.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
334	.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
335	.ddr_type = DDR_TYPE_DDR3,
336};
337
338static struct mx6_ddr3_cfg mem_ddr = {
339	.mem_speed = 800,
340	.density = 4,
341	.width = 16,
342	.banks = 8,
343#ifdef TARGET_MX6UL_ISIOT
344	.rowaddr = 15,
345#else
346	.rowaddr = 13,
347#endif
348	.coladdr = 10,
349	.pagesz = 2,
350	.trcd = 1375,
351	.trcmin = 4875,
352	.trasmin = 3500,
353};
354#endif /* CONFIG_MX6UL */
355
356static void ccgr_init(void)
357{
358	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
359
360#ifdef CONFIG_MX6QDL
361	writel(0x00003F3F, &ccm->CCGR0);
362	writel(0x0030FC00, &ccm->CCGR1);
363	writel(0x000FC000, &ccm->CCGR2);
364	writel(0x3F300000, &ccm->CCGR3);
365	writel(0xFF00F300, &ccm->CCGR4);
366	writel(0x0F0000C3, &ccm->CCGR5);
367	writel(0x000003CC, &ccm->CCGR6);
368#elif CONFIG_MX6UL
369	writel(0x00c03f3f, &ccm->CCGR0);
370	writel(0xfcffff00, &ccm->CCGR1);
371	writel(0x0cffffcc, &ccm->CCGR2);
372	writel(0x3f3c3030, &ccm->CCGR3);
373	writel(0xff00fffc, &ccm->CCGR4);
374	writel(0x033f30ff, &ccm->CCGR5);
375	writel(0x00c00fff, &ccm->CCGR6);
376#endif
377}
378
379static void spl_dram_init(void)
380{
381#ifdef CONFIG_MX6QDL
382	if (is_mx6solo()) {
383		mx6sdl_dram_iocfg(32, &mx6sdl_ddr_ioregs, &mx6sdl_grp_ioregs);
384		mx6_dram_cfg(&mem_s, &mx6dl_mmdc_calib, &mt41j256);
385	} else if (is_mx6dl()) {
386		mx6sdl_dram_iocfg(64, &mx6sdl_ddr_ioregs, &mx6sdl_grp_ioregs);
387		mx6_dram_cfg(&mem_dl, &mx6dl_mmdc_calib, &mt41j256);
388	} else if (is_mx6dq()) {
389		mx6dq_dram_iocfg(64, &mx6dq_ddr_ioregs, &mx6dq_grp_ioregs);
390		mx6_dram_cfg(&mem_q, &mx6dq_mmdc_calib, &mt41j256);
391	}
392#elif CONFIG_MX6UL
393	mx6ul_dram_iocfg(mem_ddr.width, &mx6_ddr_ioregs, &mx6_grp_ioregs);
394	mx6_dram_cfg(&ddr_sysinfo, &mx6_mmcd_calib, &mem_ddr);
395#endif
396
397	udelay(100);
398}
399
400void board_init_f(ulong dummy)
401{
402	ccgr_init();
403
404	/* setup AIPS and disable watchdog */
405	arch_cpu_init();
406
407	if (!(is_mx6ul()))
408		gpr_init();
409
410	/* setup GP timer */
411	timer_init();
412
413	/* Enable device tree and early DM support*/
414	spl_early_init();
415
416	/* UART clocks enabled and gd valid - init serial console */
417	preloader_console_init();
418
419	/* DDR initialization */
420	spl_dram_init();
421}
422