xref: /openbmc/u-boot/board/udoo/udoo_spl.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
278506c2fSvpeter4 /*
378506c2fSvpeter4  * Copyright (C) 2015 Udoo
478506c2fSvpeter4  * Author: Tungyi Lin <tungyilin1127@gmail.com>
578506c2fSvpeter4  *         Richard Hu <hakahu@gmail.com>
678506c2fSvpeter4  * Based on board/wandboard/spl.c
778506c2fSvpeter4  */
878506c2fSvpeter4 
978506c2fSvpeter4 #include <asm/arch/clock.h>
1078506c2fSvpeter4 #include <asm/arch/imx-regs.h>
1178506c2fSvpeter4 #include <asm/arch/iomux.h>
1278506c2fSvpeter4 #include <asm/arch/mx6-pins.h>
131221ce45SMasahiro Yamada #include <linux/errno.h>
1478506c2fSvpeter4 #include <asm/gpio.h>
15552a848eSStefano Babic #include <asm/mach-imx/iomux-v3.h>
16552a848eSStefano Babic #include <asm/mach-imx/video.h>
1778506c2fSvpeter4 #include <mmc.h>
1878506c2fSvpeter4 #include <fsl_esdhc.h>
1978506c2fSvpeter4 #include <asm/arch/crm_regs.h>
2078506c2fSvpeter4 #include <asm/io.h>
2178506c2fSvpeter4 #include <asm/arch/sys_proto.h>
2278506c2fSvpeter4 #include <spl.h>
2378506c2fSvpeter4 
2478506c2fSvpeter4 #if defined(CONFIG_SPL_BUILD)
2578506c2fSvpeter4 #include <asm/arch/mx6-ddr.h>
2678506c2fSvpeter4 
2778506c2fSvpeter4 /*
2878506c2fSvpeter4  * Driving strength:
2978506c2fSvpeter4  *   0x30 == 40 Ohm
3078506c2fSvpeter4  *   0x28 == 48 Ohm
3178506c2fSvpeter4  */
3278506c2fSvpeter4 #define IMX6DQ_DRIVE_STRENGTH		0x30
3378506c2fSvpeter4 #define IMX6SDL_DRIVE_STRENGTH	0x28
3478506c2fSvpeter4 
3578506c2fSvpeter4 /* configure MX6Q/DUAL mmdc DDR io registers */
3678506c2fSvpeter4 static struct mx6dq_iomux_ddr_regs mx6dq_ddr_ioregs = {
3778506c2fSvpeter4 	.dram_sdclk_0 = IMX6DQ_DRIVE_STRENGTH,
3878506c2fSvpeter4 	.dram_sdclk_1 = IMX6DQ_DRIVE_STRENGTH,
3978506c2fSvpeter4 	.dram_cas = IMX6DQ_DRIVE_STRENGTH,
4078506c2fSvpeter4 	.dram_ras = IMX6DQ_DRIVE_STRENGTH,
4178506c2fSvpeter4 	.dram_reset = IMX6DQ_DRIVE_STRENGTH,
4278506c2fSvpeter4 	.dram_sdcke0 = IMX6DQ_DRIVE_STRENGTH,
4378506c2fSvpeter4 	.dram_sdcke1 = IMX6DQ_DRIVE_STRENGTH,
4478506c2fSvpeter4 	.dram_sdba2 = 0x00000000,
4578506c2fSvpeter4 	.dram_sdodt0 = IMX6DQ_DRIVE_STRENGTH,
4678506c2fSvpeter4 	.dram_sdodt1 = IMX6DQ_DRIVE_STRENGTH,
4778506c2fSvpeter4 	.dram_sdqs0 = IMX6DQ_DRIVE_STRENGTH,
4878506c2fSvpeter4 	.dram_sdqs1 = IMX6DQ_DRIVE_STRENGTH,
4978506c2fSvpeter4 	.dram_sdqs2 = IMX6DQ_DRIVE_STRENGTH,
5078506c2fSvpeter4 	.dram_sdqs3 = IMX6DQ_DRIVE_STRENGTH,
5178506c2fSvpeter4 	.dram_sdqs4 = IMX6DQ_DRIVE_STRENGTH,
5278506c2fSvpeter4 	.dram_sdqs5 = IMX6DQ_DRIVE_STRENGTH,
5378506c2fSvpeter4 	.dram_sdqs6 = IMX6DQ_DRIVE_STRENGTH,
5478506c2fSvpeter4 	.dram_sdqs7 = IMX6DQ_DRIVE_STRENGTH,
5578506c2fSvpeter4 	.dram_dqm0 = IMX6DQ_DRIVE_STRENGTH,
5678506c2fSvpeter4 	.dram_dqm1 = IMX6DQ_DRIVE_STRENGTH,
5778506c2fSvpeter4 	.dram_dqm2 = IMX6DQ_DRIVE_STRENGTH,
5878506c2fSvpeter4 	.dram_dqm3 = IMX6DQ_DRIVE_STRENGTH,
5978506c2fSvpeter4 	.dram_dqm4 = IMX6DQ_DRIVE_STRENGTH,
6078506c2fSvpeter4 	.dram_dqm5 = IMX6DQ_DRIVE_STRENGTH,
6178506c2fSvpeter4 	.dram_dqm6 = IMX6DQ_DRIVE_STRENGTH,
6278506c2fSvpeter4 	.dram_dqm7 = IMX6DQ_DRIVE_STRENGTH,
6378506c2fSvpeter4 };
6478506c2fSvpeter4 
6578506c2fSvpeter4 /* configure MX6Q/DUAL mmdc GRP io registers */
6678506c2fSvpeter4 static struct mx6dq_iomux_grp_regs mx6dq_grp_ioregs = {
6778506c2fSvpeter4 	.grp_ddr_type = 0x000c0000,
6878506c2fSvpeter4 	.grp_ddrmode_ctl = 0x00020000,
6978506c2fSvpeter4 	.grp_ddrpke = 0x00000000,
7078506c2fSvpeter4 	.grp_addds = IMX6DQ_DRIVE_STRENGTH,
7178506c2fSvpeter4 	.grp_ctlds = IMX6DQ_DRIVE_STRENGTH,
7278506c2fSvpeter4 	.grp_ddrmode = 0x00020000,
7378506c2fSvpeter4 	.grp_b0ds = IMX6DQ_DRIVE_STRENGTH,
7478506c2fSvpeter4 	.grp_b1ds = IMX6DQ_DRIVE_STRENGTH,
7578506c2fSvpeter4 	.grp_b2ds = IMX6DQ_DRIVE_STRENGTH,
7678506c2fSvpeter4 	.grp_b3ds = IMX6DQ_DRIVE_STRENGTH,
7778506c2fSvpeter4 	.grp_b4ds = IMX6DQ_DRIVE_STRENGTH,
7878506c2fSvpeter4 	.grp_b5ds = IMX6DQ_DRIVE_STRENGTH,
7978506c2fSvpeter4 	.grp_b6ds = IMX6DQ_DRIVE_STRENGTH,
8078506c2fSvpeter4 	.grp_b7ds = IMX6DQ_DRIVE_STRENGTH,
8178506c2fSvpeter4 };
8278506c2fSvpeter4 
8378506c2fSvpeter4 /* configure MX6SOLO/DUALLITE mmdc DDR io registers */
8478506c2fSvpeter4 struct mx6sdl_iomux_ddr_regs mx6sdl_ddr_ioregs = {
8578506c2fSvpeter4 	.dram_sdclk_0 = IMX6SDL_DRIVE_STRENGTH,
8678506c2fSvpeter4 	.dram_sdclk_1 = IMX6SDL_DRIVE_STRENGTH,
8778506c2fSvpeter4 	.dram_cas = IMX6SDL_DRIVE_STRENGTH,
8878506c2fSvpeter4 	.dram_ras = IMX6SDL_DRIVE_STRENGTH,
8978506c2fSvpeter4 	.dram_reset = IMX6SDL_DRIVE_STRENGTH,
9078506c2fSvpeter4 	.dram_sdcke0 = IMX6SDL_DRIVE_STRENGTH,
9178506c2fSvpeter4 	.dram_sdcke1 = IMX6SDL_DRIVE_STRENGTH,
9278506c2fSvpeter4 	.dram_sdba2 = 0x00000000,
9378506c2fSvpeter4 	.dram_sdodt0 = IMX6SDL_DRIVE_STRENGTH,
9478506c2fSvpeter4 	.dram_sdodt1 = IMX6SDL_DRIVE_STRENGTH,
9578506c2fSvpeter4 	.dram_sdqs0 = IMX6SDL_DRIVE_STRENGTH,
9678506c2fSvpeter4 	.dram_sdqs1 = IMX6SDL_DRIVE_STRENGTH,
9778506c2fSvpeter4 	.dram_sdqs2 = IMX6SDL_DRIVE_STRENGTH,
9878506c2fSvpeter4 	.dram_sdqs3 = IMX6SDL_DRIVE_STRENGTH,
9978506c2fSvpeter4 	.dram_sdqs4 = IMX6SDL_DRIVE_STRENGTH,
10078506c2fSvpeter4 	.dram_sdqs5 = IMX6SDL_DRIVE_STRENGTH,
10178506c2fSvpeter4 	.dram_sdqs6 = IMX6SDL_DRIVE_STRENGTH,
10278506c2fSvpeter4 	.dram_sdqs7 = IMX6SDL_DRIVE_STRENGTH,
10378506c2fSvpeter4 	.dram_dqm0 = IMX6SDL_DRIVE_STRENGTH,
10478506c2fSvpeter4 	.dram_dqm1 = IMX6SDL_DRIVE_STRENGTH,
10578506c2fSvpeter4 	.dram_dqm2 = IMX6SDL_DRIVE_STRENGTH,
10678506c2fSvpeter4 	.dram_dqm3 = IMX6SDL_DRIVE_STRENGTH,
10778506c2fSvpeter4 	.dram_dqm4 = IMX6SDL_DRIVE_STRENGTH,
10878506c2fSvpeter4 	.dram_dqm5 = IMX6SDL_DRIVE_STRENGTH,
10978506c2fSvpeter4 	.dram_dqm6 = IMX6SDL_DRIVE_STRENGTH,
11078506c2fSvpeter4 	.dram_dqm7 = IMX6SDL_DRIVE_STRENGTH,
11178506c2fSvpeter4 };
11278506c2fSvpeter4 
11378506c2fSvpeter4 /* configure MX6SOLO/DUALLITE mmdc GRP io registers */
11478506c2fSvpeter4 struct mx6sdl_iomux_grp_regs mx6sdl_grp_ioregs = {
11578506c2fSvpeter4 	.grp_ddr_type = 0x000c0000,
11678506c2fSvpeter4 	.grp_ddrmode_ctl = 0x00020000,
11778506c2fSvpeter4 	.grp_ddrpke = 0x00000000,
11878506c2fSvpeter4 	.grp_addds = IMX6SDL_DRIVE_STRENGTH,
11978506c2fSvpeter4 	.grp_ctlds = IMX6SDL_DRIVE_STRENGTH,
12078506c2fSvpeter4 	.grp_ddrmode = 0x00020000,
12178506c2fSvpeter4 	.grp_b0ds = IMX6SDL_DRIVE_STRENGTH,
12278506c2fSvpeter4 	.grp_b1ds = IMX6SDL_DRIVE_STRENGTH,
12378506c2fSvpeter4 	.grp_b2ds = IMX6SDL_DRIVE_STRENGTH,
12478506c2fSvpeter4 	.grp_b3ds = IMX6SDL_DRIVE_STRENGTH,
12578506c2fSvpeter4 	.grp_b4ds = IMX6SDL_DRIVE_STRENGTH,
12678506c2fSvpeter4 	.grp_b5ds = IMX6SDL_DRIVE_STRENGTH,
12778506c2fSvpeter4 	.grp_b6ds = IMX6SDL_DRIVE_STRENGTH,
12878506c2fSvpeter4 	.grp_b7ds = IMX6SDL_DRIVE_STRENGTH,
12978506c2fSvpeter4 };
13078506c2fSvpeter4 
13178506c2fSvpeter4 /* MT41K128M16JT-125 */
13278506c2fSvpeter4 static struct mx6_ddr3_cfg mt41k128m16jt_125 = {
13378506c2fSvpeter4 	/* quad = 1066, duallite = 800 */
13478506c2fSvpeter4 	.mem_speed = 1066,
13578506c2fSvpeter4 	.density = 2,
13678506c2fSvpeter4 	.width = 16,
13778506c2fSvpeter4 	.banks = 8,
13878506c2fSvpeter4 	.rowaddr = 14,
13978506c2fSvpeter4 	.coladdr = 10,
14078506c2fSvpeter4 	.pagesz = 2,
14178506c2fSvpeter4 	.trcd = 1375,
14278506c2fSvpeter4 	.trcmin = 4875,
14378506c2fSvpeter4 	.trasmin = 3500,
14478506c2fSvpeter4 	.SRT = 0,
14578506c2fSvpeter4 };
14678506c2fSvpeter4 
14778506c2fSvpeter4 static struct mx6_mmdc_calibration mx6q_1g_mmdc_calib = {
14878506c2fSvpeter4 	.p0_mpwldectrl0 = 0x00350035,
14978506c2fSvpeter4 	.p0_mpwldectrl1 = 0x001F001F,
15078506c2fSvpeter4 	.p1_mpwldectrl0 = 0x00010001,
15178506c2fSvpeter4 	.p1_mpwldectrl1 = 0x00010001,
15278506c2fSvpeter4 	.p0_mpdgctrl0 = 0x43510360,
15378506c2fSvpeter4 	.p0_mpdgctrl1 = 0x0342033F,
15478506c2fSvpeter4 	.p1_mpdgctrl0 = 0x033F033F,
15578506c2fSvpeter4 	.p1_mpdgctrl1 = 0x03290266,
15678506c2fSvpeter4 	.p0_mprddlctl = 0x4B3E4141,
15778506c2fSvpeter4 	.p1_mprddlctl = 0x47413B4A,
15878506c2fSvpeter4 	.p0_mpwrdlctl = 0x42404843,
15978506c2fSvpeter4 	.p1_mpwrdlctl = 0x4C3F4C45,
16078506c2fSvpeter4 };
16178506c2fSvpeter4 
16278506c2fSvpeter4 static struct mx6_mmdc_calibration mx6dl_1g_mmdc_calib = {
16378506c2fSvpeter4 	.p0_mpwldectrl0 = 0x002F0038,
16478506c2fSvpeter4 	.p0_mpwldectrl1 = 0x001F001F,
16578506c2fSvpeter4 	.p1_mpwldectrl0 = 0x001F001F,
16678506c2fSvpeter4 	.p1_mpwldectrl1 = 0x001F001F,
16778506c2fSvpeter4 	.p0_mpdgctrl0 = 0x425C0251,
16878506c2fSvpeter4 	.p0_mpdgctrl1 = 0x021B021E,
16978506c2fSvpeter4 	.p1_mpdgctrl0 = 0x021B021E,
17078506c2fSvpeter4 	.p1_mpdgctrl1 = 0x01730200,
17178506c2fSvpeter4 	.p0_mprddlctl = 0x45474C45,
17278506c2fSvpeter4 	.p1_mprddlctl = 0x44464744,
17378506c2fSvpeter4 	.p0_mpwrdlctl = 0x3F3F3336,
17478506c2fSvpeter4 	.p1_mpwrdlctl = 0x32383630,
17578506c2fSvpeter4 };
17678506c2fSvpeter4 
17778506c2fSvpeter4 /* DDR 64bit 1GB */
17878506c2fSvpeter4 static struct mx6_ddr_sysinfo mem_qdl = {
17978506c2fSvpeter4 	.dsize = 2,
18078506c2fSvpeter4 	.cs1_mirror = 0,
18178506c2fSvpeter4 	/* config for full 4GB range so that get_mem_size() works */
18278506c2fSvpeter4 	.cs_density = 32,
18378506c2fSvpeter4 	.ncs = 1,
18478506c2fSvpeter4 	.bi_on = 1,
18578506c2fSvpeter4 	/* quad = 2, duallite = 1 */
18678506c2fSvpeter4 	.rtt_nom = 2,
18778506c2fSvpeter4 	/* quad = 2, duallite = 1 */
18878506c2fSvpeter4 	.rtt_wr = 2,
18978506c2fSvpeter4 	.ralat = 5,
19078506c2fSvpeter4 	.walat = 0,
19178506c2fSvpeter4 	.mif3_mode = 3,
19278506c2fSvpeter4 	.rst_to_cke = 0x23,
19378506c2fSvpeter4 	.sde_to_rst = 0x10,
194edf00937SFabio Estevam 	.refsel = 1,	/* Refresh cycles at 32KHz */
195edf00937SFabio Estevam 	.refr = 7,	/* 8 refresh commands per refresh cycle */
19678506c2fSvpeter4 };
19778506c2fSvpeter4 
ccgr_init(void)19878506c2fSvpeter4 static void ccgr_init(void)
19978506c2fSvpeter4 {
20078506c2fSvpeter4 	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
20178506c2fSvpeter4 
20278506c2fSvpeter4 	/* set the default clock gate to save power */
20378506c2fSvpeter4 	writel(0x00C03F3F, &ccm->CCGR0);
20478506c2fSvpeter4 	writel(0x0030FC03, &ccm->CCGR1);
20578506c2fSvpeter4 	writel(0x0FFFC000, &ccm->CCGR2);
20678506c2fSvpeter4 	writel(0x3FF00000, &ccm->CCGR3);
20778506c2fSvpeter4 	writel(0x00FFF300, &ccm->CCGR4);
20878506c2fSvpeter4 	writel(0x0F0000C3, &ccm->CCGR5);
20978506c2fSvpeter4 	writel(0x000003FF, &ccm->CCGR6);
21078506c2fSvpeter4 }
21178506c2fSvpeter4 
spl_dram_init(void)21278506c2fSvpeter4 static void spl_dram_init(void)
21378506c2fSvpeter4 {
21478506c2fSvpeter4 	if (is_cpu_type(MXC_CPU_MX6DL)) {
21578506c2fSvpeter4 		mt41k128m16jt_125.mem_speed = 800;
21678506c2fSvpeter4 		mem_qdl.rtt_nom = 1;
21778506c2fSvpeter4 		mem_qdl.rtt_wr = 1;
21878506c2fSvpeter4 
21978506c2fSvpeter4 		mx6sdl_dram_iocfg(64, &mx6sdl_ddr_ioregs, &mx6sdl_grp_ioregs);
22078506c2fSvpeter4 		mx6_dram_cfg(&mem_qdl, &mx6dl_1g_mmdc_calib, &mt41k128m16jt_125);
22178506c2fSvpeter4 	} else if (is_cpu_type(MXC_CPU_MX6Q)) {
22278506c2fSvpeter4 		mt41k128m16jt_125.mem_speed = 1066;
22378506c2fSvpeter4 		mem_qdl.rtt_nom = 2;
22478506c2fSvpeter4 		mem_qdl.rtt_wr = 2;
22578506c2fSvpeter4 
22678506c2fSvpeter4 		mx6dq_dram_iocfg(64, &mx6dq_ddr_ioregs, &mx6dq_grp_ioregs);
22778506c2fSvpeter4 		mx6_dram_cfg(&mem_qdl, &mx6q_1g_mmdc_calib, &mt41k128m16jt_125);
22878506c2fSvpeter4 	}
22978506c2fSvpeter4 
23078506c2fSvpeter4 	udelay(100);
23178506c2fSvpeter4 }
23278506c2fSvpeter4 
board_init_f(ulong dummy)23378506c2fSvpeter4 void board_init_f(ulong dummy)
23478506c2fSvpeter4 {
23578506c2fSvpeter4 	ccgr_init();
23678506c2fSvpeter4 
23778506c2fSvpeter4 	/* setup AIPS and disable watchdog */
23878506c2fSvpeter4 	arch_cpu_init();
23978506c2fSvpeter4 
24078506c2fSvpeter4 	gpr_init();
24178506c2fSvpeter4 
24278506c2fSvpeter4 	/* iomux */
24378506c2fSvpeter4 	board_early_init_f();
24478506c2fSvpeter4 
24578506c2fSvpeter4 	/* setup GP timer */
24678506c2fSvpeter4 	timer_init();
24778506c2fSvpeter4 
24878506c2fSvpeter4 	/* UART clocks enabled and gd valid - init serial console */
24978506c2fSvpeter4 	preloader_console_init();
25078506c2fSvpeter4 
25178506c2fSvpeter4 	/* DDR initialization */
25278506c2fSvpeter4 	spl_dram_init();
25378506c2fSvpeter4 }
25478506c2fSvpeter4 #endif
255