1 /*
2  * SPL board functions for CompuLab CL-SOM-iMX7 module
3  *
4  * (C) Copyright 2017 CompuLab, Ltd. http://www.compulab.com
5  *
6  * Author: Uri Mashiach <uri.mashiach@compulab.co.il>
7  *
8  * SPDX-License-Identifier:	GPL-2.0+
9  */
10 
11 #include <common.h>
12 #include <spl.h>
13 #include <fsl_esdhc.h>
14 #include <asm/mach-imx/iomux-v3.h>
15 #include <asm/arch-mx7/mx7-pins.h>
16 #include <asm/arch-mx7/clock.h>
17 #include <asm/arch-mx7/mx7-ddr.h>
18 #include "common.h"
19 
20 #ifdef CONFIG_FSL_ESDHC
21 
22 static struct fsl_esdhc_cfg cl_som_imx7_spl_usdhc_cfg = {
23 	USDHC1_BASE_ADDR, 0, 4};
24 
25 int board_mmc_init(bd_t *bis)
26 {
27 	cl_som_imx7_usdhc1_pads_set();
28 	cl_som_imx7_spl_usdhc_cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
29 	return fsl_esdhc_initialize(bis, &cl_som_imx7_spl_usdhc_cfg);
30 }
31 #endif /* CONFIG_FSL_ESDHC */
32 
33 static iomux_v3_cfg_t const led_pads[] = {
34 	MX7D_PAD_SAI1_TX_SYNC__GPIO6_IO14 | MUX_PAD_CTRL(PAD_CTL_PUS_PU5KOHM |
35 		PAD_CTL_PUE | PAD_CTL_SRE_SLOW)
36 };
37 
38 static struct ddrc cl_som_imx7_spl_ddrc_regs_val = {
39 	.init1		= 0x00690000,
40 	.init0		= 0x00020083,
41 	.init3		= 0x09300004,
42 	.init4		= 0x04080000,
43 	.init5		= 0x00100004,
44 	.rankctl	= 0x0000033F,
45 	.dramtmg1	= 0x0007020E,
46 	.dramtmg2	= 0x03040407,
47 	.dramtmg3	= 0x00002006,
48 	.dramtmg4	= 0x04020305,
49 	.dramtmg5	= 0x03030202,
50 	.dramtmg8	= 0x00000803,
51 	.zqctl0		= 0x00810021,
52 	.dfitmg0	= 0x02098204,
53 	.dfitmg1	= 0x00030303,
54 	.dfiupd0	= 0x80400003,
55 	.dfiupd1	= 0x00100020,
56 	.dfiupd2	= 0x80100004,
57 	.addrmap4	= 0x00000F0F,
58 	.odtcfg		= 0x06000604,
59 	.odtmap		= 0x00000001,
60 };
61 
62 static struct ddrc_mp cl_som_imx7_spl_ddrc_mp_val = {
63 	.pctrl_0	= 0x00000001,
64 };
65 
66 static struct ddr_phy cl_som_imx7_spl_ddr_phy_regs_val = {
67 	.phy_con0	= 0x17420F40,
68 	.phy_con1	= 0x10210100,
69 	.phy_con4	= 0x00060807,
70 	.mdll_con0	= 0x1010007E,
71 	.drvds_con0	= 0x00000D6E,
72 	.cmd_sdll_con0	= 0x00000010,
73 	.offset_lp_con0	= 0x0000000F,
74 };
75 
76 struct mx7_calibration cl_som_imx7_spl_calib_param = {
77 	.num_val	= 5,
78 	.values		= {
79 		0x0E407304,
80 		0x0E447304,
81 		0x0E447306,
82 		0x0E447304,
83 		0x0E407304,
84 	},
85 };
86 
87 static void cl_som_imx7_spl_dram_cfg_size(u32 ram_size)
88 {
89 	switch (ram_size) {
90 	case SZ_256M:
91 		cl_som_imx7_spl_ddrc_regs_val.mstr		= 0x01041001;
92 		cl_som_imx7_spl_ddrc_regs_val.rfshtmg		= 0x00400046;
93 		cl_som_imx7_spl_ddrc_regs_val.dramtmg0		= 0x090E1109;
94 		cl_som_imx7_spl_ddrc_regs_val.addrmap0		= 0x00000014;
95 		cl_som_imx7_spl_ddrc_regs_val.addrmap1		= 0x00151515;
96 		cl_som_imx7_spl_ddrc_regs_val.addrmap5		= 0x03030303;
97 		cl_som_imx7_spl_ddrc_regs_val.addrmap6		= 0x0F0F0303;
98 		cl_som_imx7_spl_ddr_phy_regs_val.offset_rd_con0	= 0x0C0C0C0C;
99 		cl_som_imx7_spl_ddr_phy_regs_val.offset_wr_con0	= 0x04040404;
100 		break;
101 	case SZ_512M:
102 		cl_som_imx7_spl_ddrc_regs_val.mstr		= 0x01040001;
103 		cl_som_imx7_spl_ddrc_regs_val.rfshtmg		= 0x00400046;
104 		cl_som_imx7_spl_ddrc_regs_val.dramtmg0		= 0x090E1109;
105 		cl_som_imx7_spl_ddrc_regs_val.addrmap0		= 0x00000015;
106 		cl_som_imx7_spl_ddrc_regs_val.addrmap1		= 0x00161616;
107 		cl_som_imx7_spl_ddrc_regs_val.addrmap5		= 0x04040404;
108 		cl_som_imx7_spl_ddrc_regs_val.addrmap6		= 0x0F0F0404;
109 		cl_som_imx7_spl_ddr_phy_regs_val.offset_rd_con0	= 0x0C0C0C0C;
110 		cl_som_imx7_spl_ddr_phy_regs_val.offset_wr_con0	= 0x04040404;
111 		break;
112 	case SZ_1G:
113 		cl_som_imx7_spl_ddrc_regs_val.mstr		= 0x01040001;
114 		cl_som_imx7_spl_ddrc_regs_val.rfshtmg		= 0x00400046;
115 		cl_som_imx7_spl_ddrc_regs_val.dramtmg0		= 0x090E1109;
116 		cl_som_imx7_spl_ddrc_regs_val.addrmap0		= 0x00000016;
117 		cl_som_imx7_spl_ddrc_regs_val.addrmap1		= 0x00171717;
118 		cl_som_imx7_spl_ddrc_regs_val.addrmap5		= 0x04040404;
119 		cl_som_imx7_spl_ddrc_regs_val.addrmap6		= 0x0F040404;
120 		cl_som_imx7_spl_ddr_phy_regs_val.offset_rd_con0	= 0x0A0A0A0A;
121 		cl_som_imx7_spl_ddr_phy_regs_val.offset_wr_con0	= 0x02020202;
122 		break;
123 	case SZ_2G:
124 		cl_som_imx7_spl_ddrc_regs_val.mstr		= 0x01040001;
125 		cl_som_imx7_spl_ddrc_regs_val.rfshtmg		= 0x0040005E;
126 		cl_som_imx7_spl_ddrc_regs_val.dramtmg0		= 0x090E110A;
127 		cl_som_imx7_spl_ddrc_regs_val.addrmap0		= 0x00000018;
128 		cl_som_imx7_spl_ddrc_regs_val.addrmap1		= 0x00181818;
129 		cl_som_imx7_spl_ddrc_regs_val.addrmap5		= 0x04040404;
130 		cl_som_imx7_spl_ddrc_regs_val.addrmap6		= 0x04040404;
131 		cl_som_imx7_spl_ddr_phy_regs_val.offset_rd_con0	= 0x0A0A0A0A;
132 		cl_som_imx7_spl_ddr_phy_regs_val.offset_wr_con0	= 0x04040404;
133 		break;
134 	}
135 
136 	mx7_dram_cfg(&cl_som_imx7_spl_ddrc_regs_val,
137 		     &cl_som_imx7_spl_ddrc_mp_val,
138 		     &cl_som_imx7_spl_ddr_phy_regs_val,
139 		     &cl_som_imx7_spl_calib_param);
140 }
141 
142 static void cl_som_imx7_spl_dram_cfg(void)
143 {
144 	ulong ram_size_test, ram_size = 0;
145 
146 	for (ram_size = SZ_2G; ram_size >= SZ_256M; ram_size >>= 1) {
147 		cl_som_imx7_spl_dram_cfg_size(ram_size);
148 		ram_size_test = get_ram_size((long int *)PHYS_SDRAM, ram_size);
149 		if (ram_size_test == ram_size)
150 			break;
151 	}
152 
153 	if (ram_size < SZ_256M) {
154 		puts("!!!ERROR!!! DRAM detection failed!!!\n");
155 		hang();
156 	}
157 }
158 
159 #ifdef CONFIG_SPL_SPI_SUPPORT
160 
161 static void cl_som_imx7_spl_spi_init(void)
162 {
163 	cl_som_imx7_espi1_pads_set();
164 }
165 #else /* !CONFIG_SPL_SPI_SUPPORT */
166 static void cl_som_imx7_spl_spi_init(void) {}
167 #endif /* CONFIG_SPL_SPI_SUPPORT */
168 
169 void board_init_f(ulong dummy)
170 {
171 	imx_iomux_v3_setup_multiple_pads(led_pads, 1);
172 	/* setup AIPS and disable watchdog */
173 	arch_cpu_init();
174 	/* setup GP timer */
175 	timer_init();
176 	cl_som_imx7_spl_spi_init();
177 	cl_som_imx7_uart1_pads_set();
178 	/* UART clocks enabled and gd valid - init serial console */
179 	preloader_console_init();
180 	/* DRAM detection  */
181 	cl_som_imx7_spl_dram_cfg();
182 	/* Clear the BSS. */
183 	memset(__bss_start, 0, __bss_end - __bss_start);
184 	/* load/boot image from boot device */
185 	board_init_r(NULL, 0);
186 }
187 
188 void spl_board_init(void)
189 {
190 	u32 boot_device = spl_boot_device();
191 
192 	if (boot_device == BOOT_DEVICE_SPI)
193 		puts("Booting from SPI flash\n");
194 	else if (boot_device == BOOT_DEVICE_MMC1)
195 		puts("Booting from SD card\n");
196 	else
197 		puts("Unknown boot device\n");
198 }
199 
200 void board_boot_order(u32 *spl_boot_list)
201 {
202 	spl_boot_list[0] = spl_boot_device();
203 	switch (spl_boot_list[0]) {
204 	case BOOT_DEVICE_SPI:
205 		spl_boot_list[1] = BOOT_DEVICE_MMC1;
206 		break;
207 	case BOOT_DEVICE_MMC1:
208 		spl_boot_list[1] = BOOT_DEVICE_SPI;
209 		break;
210 	}
211 }
212