xref: /openbmc/u-boot/drivers/mmc/fsl_esdhc_spl.c (revision 2bb1cd53)
1 /*
2  * Copyright 2013 Freescale Semiconductor, Inc.
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <common.h>
8 #include <mmc.h>
9 #include <malloc.h>
10 
11 /*
12  * The environment variables are written to just after the u-boot image
13  * on SDCard, so we must read the MBR to get the start address and code
14  * length of the u-boot image, then calculate the address of the env.
15  */
16 #define ESDHC_BOOT_IMAGE_SIZE	0x48
17 #define ESDHC_BOOT_IMAGE_ADDR	0x50
18 #define MBRDBR_BOOT_SIG_55	0x1fe
19 #define MBRDBR_BOOT_SIG_AA	0x1ff
20 #define CONFIG_CFG_DATA_SECTOR	0
21 
22 
23 void mmc_spl_load_image(uint32_t offs, unsigned int size, void *vdst)
24 {
25 	uint blk_start, blk_cnt, err;
26 
27 	struct mmc *mmc = find_mmc_device(0);
28 	if (!mmc) {
29 		puts("spl: mmc device not found!!\n");
30 		hang();
31 	}
32 
33 	if (mmc_init(mmc)) {
34 		puts("MMC init failed\n");
35 		return;
36 	}
37 
38 	blk_start = ALIGN(offs, mmc->read_bl_len) / mmc->read_bl_len;
39 	blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len;
40 
41 	err = mmc->block_dev.block_read(0, blk_start, blk_cnt, vdst);
42 	if (err != blk_cnt) {
43 		puts("spl: mmc read failed!!\n");
44 		hang();
45 	}
46 }
47 
48 /*
49  * The main entry for mmc booting. It's necessary that SDRAM is already
50  * configured and available since this code loads the main U-Boot image
51  * from mmc into SDRAM and starts it from there.
52  */
53 
54 void __noreturn mmc_boot(void)
55 {
56 	__attribute__((noreturn)) void (*uboot)(void);
57 	uint blk_start, blk_cnt, err;
58 #ifndef CONFIG_FSL_CORENET
59 	uchar *tmp_buf;
60 	u32 blklen;
61 	uchar val;
62 	uint i, byte_num;
63 #endif
64 	u32 offset, code_len;
65 	struct mmc *mmc;
66 
67 	mmc = find_mmc_device(0);
68 	if (!mmc) {
69 		puts("spl: mmc device not found!!\n");
70 		hang();
71 	}
72 
73 #ifdef CONFIG_FSL_CORENET
74 	offset = CONFIG_SYS_MMC_U_BOOT_OFFS;
75 	code_len = CONFIG_SYS_MMC_U_BOOT_SIZE;
76 #else
77 	blklen = mmc->read_bl_len;
78 	tmp_buf = malloc(blklen);
79 	if (!tmp_buf) {
80 		puts("spl: malloc memory failed!!\n");
81 		hang();
82 	}
83 	memset(tmp_buf, 0, blklen);
84 
85 	/*
86 	* Read source addr from sd card
87 	*/
88 	err = mmc->block_dev.block_read(0, CONFIG_CFG_DATA_SECTOR, 1, tmp_buf);
89 	if (err != 1) {
90 		puts("spl: mmc read failed!!\n");
91 		free(tmp_buf);
92 		hang();
93 	}
94 
95 	val = *(tmp_buf + MBRDBR_BOOT_SIG_55);
96 	if (0x55 != val) {
97 		puts("spl: mmc signature is not valid!!\n");
98 		free(tmp_buf);
99 		hang();
100 	}
101 	val = *(tmp_buf + MBRDBR_BOOT_SIG_AA);
102 	if (0xAA != val) {
103 		puts("spl: mmc signature is not valid!!\n");
104 		free(tmp_buf);
105 		hang();
106 	}
107 
108 	byte_num = 4;
109 	offset = 0;
110 	for (i = 0; i < byte_num; i++) {
111 		val = *(tmp_buf + ESDHC_BOOT_IMAGE_ADDR + i);
112 		offset = (offset << 8) + val;
113 	}
114 	offset += CONFIG_SYS_MMC_U_BOOT_OFFS;
115 	/* Get the code size from offset 0x48 */
116 	byte_num = 4;
117 	code_len = 0;
118 	for (i = 0; i < byte_num; i++) {
119 		val = *(tmp_buf + ESDHC_BOOT_IMAGE_SIZE + i);
120 		code_len = (code_len << 8) + val;
121 	}
122 	code_len -= CONFIG_SYS_MMC_U_BOOT_OFFS;
123 	/*
124 	* Load U-Boot image from mmc into RAM
125 	*/
126 #endif
127 	blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len;
128 	blk_cnt = ALIGN(code_len, mmc->read_bl_len) / mmc->read_bl_len;
129 	err = mmc->block_dev.block_read(0, blk_start, blk_cnt,
130 					(uchar *)CONFIG_SYS_MMC_U_BOOT_DST);
131 	if (err != blk_cnt) {
132 		puts("spl: mmc read failed!!\n");
133 #ifndef CONFIG_FSL_CORENET
134 		free(tmp_buf);
135 #endif
136 		hang();
137 	}
138 
139 	/*
140 	* Clean d-cache and invalidate i-cache, to
141 	* make sure that no stale data is executed.
142 	*/
143 	flush_cache(CONFIG_SYS_MMC_U_BOOT_DST, CONFIG_SYS_MMC_U_BOOT_SIZE);
144 
145 	/*
146 	* Jump to U-Boot image
147 	*/
148 	uboot = (void *)CONFIG_SYS_MMC_U_BOOT_START;
149 	(*uboot)();
150 }
151