]> git.ipfire.org Git - thirdparty/u-boot.git/blob - drivers/mmc/fsl_esdhc_spl.c
common: Drop linux/printk.h from common header
[thirdparty/u-boot.git] / drivers / mmc / fsl_esdhc_spl.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright 2013 Freescale Semiconductor, Inc.
4 */
5
6 #include <common.h>
7 #include <cpu_func.h>
8 #include <hang.h>
9 #include <mmc.h>
10 #include <malloc.h>
11
12 #ifndef CFG_SYS_MMC_U_BOOT_OFFS
13 extern uchar mmc_u_boot_offs[];
14 #endif
15
16 /*
17 * The environment variables are written to just after the u-boot image
18 * on SDCard, so we must read the MBR to get the start address and code
19 * length of the u-boot image, then calculate the address of the env.
20 */
21 #define ESDHC_BOOT_SIGNATURE_OFF 0x40
22 #define ESDHC_BOOT_SIGNATURE 0x424f4f54
23 #define ESDHC_BOOT_IMAGE_SIZE 0x48
24 #define ESDHC_BOOT_IMAGE_ADDR 0x50
25 #define MBRDBR_BOOT_SIG_55 0x1fe
26 #define MBRDBR_BOOT_SIG_AA 0x1ff
27
28
29 void mmc_spl_load_image(uint32_t offs, unsigned int size, void *vdst)
30 {
31 uint blk_start, blk_cnt, err;
32
33 struct mmc *mmc = find_mmc_device(0);
34 if (!mmc) {
35 puts("spl: mmc device not found!!\n");
36 hang();
37 }
38
39 if (mmc_init(mmc)) {
40 puts("MMC init failed\n");
41 return;
42 }
43
44 blk_start = ALIGN(offs, mmc->read_bl_len) / mmc->read_bl_len;
45 blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len;
46
47 err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt,
48 vdst);
49 if (err != blk_cnt) {
50 puts("spl: mmc read failed!!\n");
51 hang();
52 }
53 }
54
55 /*
56 * The main entry for mmc booting. It's necessary that SDRAM is already
57 * configured and available since this code loads the main U-Boot image
58 * from mmc into SDRAM and starts it from there.
59 */
60
61 void __noreturn mmc_boot(void)
62 {
63 __attribute__((noreturn)) void (*uboot)(void);
64 uint blk_start, blk_cnt, err;
65 uchar *tmp_buf;
66 u32 blklen;
67 u32 blk_off;
68 #ifndef CONFIG_FSL_CORENET
69 uchar val;
70 #ifndef CONFIG_SPL_FSL_PBL
71 u32 val32;
72 #endif
73 uint i, byte_num;
74 u32 sector;
75 #endif
76 u32 offset, code_len;
77 struct mmc *mmc;
78
79 mmc = find_mmc_device(0);
80 if (!mmc) {
81 puts("spl: mmc device not found!!\n");
82 hang();
83 }
84
85 if (mmc_init(mmc)) {
86 puts("spl: mmc device init failed!\n");
87 hang();
88 }
89
90 blklen = mmc->read_bl_len;
91 if (blklen < 512)
92 blklen = 512;
93 tmp_buf = malloc(blklen);
94 if (!tmp_buf) {
95 puts("spl: malloc memory failed!!\n");
96 hang();
97 }
98
99 #ifdef CONFIG_FSL_CORENET
100 offset = CFG_SYS_MMC_U_BOOT_OFFS;
101 #else
102 sector = 0;
103 again:
104 memset(tmp_buf, 0, blklen);
105
106 /*
107 * Read source addr from sd card
108 */
109 blk_start = (sector * 512) / mmc->read_bl_len;
110 blk_off = (sector * 512) % mmc->read_bl_len;
111 blk_cnt = DIV_ROUND_UP(512, mmc->read_bl_len);
112 err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt, tmp_buf);
113 if (err != blk_cnt) {
114 puts("spl: mmc read failed!!\n");
115 hang();
116 }
117
118 #ifdef CONFIG_SPL_FSL_PBL
119 val = *(tmp_buf + blk_off + MBRDBR_BOOT_SIG_55);
120 if (0x55 != val) {
121 puts("spl: mmc MBR/DBR signature is not valid!!\n");
122 hang();
123 }
124 val = *(tmp_buf + blk_off + MBRDBR_BOOT_SIG_AA);
125 if (0xAA != val) {
126 puts("spl: mmc MBR/DBR signature is not valid!!\n");
127 hang();
128 }
129 #else
130 /*
131 * Booting from On-Chip ROM (eSDHC or eSPI), Document Number: AN3659, Rev. 2, 06/2012.
132 * Pre-PBL BootROMs (MPC8536E, MPC8569E, P2020, P1011, P1012, P1013, P1020, P1021, P1022)
133 * require custom BOOT signature on sector 0 and MBR/DBR signature is not required at all.
134 */
135 byte_num = 4;
136 val32 = 0;
137 for (i = 0; i < byte_num; i++) {
138 val = *(tmp_buf + blk_off + ESDHC_BOOT_SIGNATURE_OFF + i);
139 val32 = (val32 << 8) + val;
140 }
141 if (val32 != ESDHC_BOOT_SIGNATURE) {
142 /* BOOT signature may be on the first 24 sectors (each being 512 bytes) */
143 if (++sector < 24)
144 goto again;
145 puts("spl: mmc BOOT signature is not valid!!\n");
146 hang();
147 }
148 #endif
149
150 byte_num = 4;
151 offset = 0;
152 for (i = 0; i < byte_num; i++) {
153 val = *(tmp_buf + blk_off + ESDHC_BOOT_IMAGE_ADDR + i);
154 offset = (offset << 8) + val;
155 }
156 #ifndef CFG_SYS_MMC_U_BOOT_OFFS
157 offset += (ulong)&mmc_u_boot_offs - CONFIG_SPL_TEXT_BASE;
158 #else
159 offset += CFG_SYS_MMC_U_BOOT_OFFS;
160 #endif
161 #endif
162 /*
163 * Load U-Boot image from mmc into RAM
164 */
165 code_len = CFG_SYS_MMC_U_BOOT_SIZE;
166 blk_start = offset / mmc->read_bl_len;
167 blk_off = offset % mmc->read_bl_len;
168 blk_cnt = ALIGN(code_len, mmc->read_bl_len) / mmc->read_bl_len + 1;
169 if (blk_off) {
170 err = mmc->block_dev.block_read(&mmc->block_dev,
171 blk_start, 1, tmp_buf);
172 if (err != 1) {
173 puts("spl: mmc read failed!!\n");
174 hang();
175 }
176 blk_start++;
177 }
178 err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt,
179 (uchar *)CFG_SYS_MMC_U_BOOT_DST +
180 (blk_off ? (mmc->read_bl_len - blk_off) : 0));
181 if (err != blk_cnt) {
182 puts("spl: mmc read failed!!\n");
183 free(tmp_buf);
184 hang();
185 }
186 /*
187 * SDHC DMA may erase bytes at dst + bl_len - blk_off - 8
188 * due to unaligned access. So copy leading bytes from tmp_buf
189 * after SDHC DMA transfer.
190 */
191 if (blk_off)
192 memcpy((uchar *)CFG_SYS_MMC_U_BOOT_DST,
193 tmp_buf + blk_off, mmc->read_bl_len - blk_off);
194
195 /*
196 * Clean d-cache and invalidate i-cache, to
197 * make sure that no stale data is executed.
198 */
199 flush_cache(CFG_SYS_MMC_U_BOOT_DST, CFG_SYS_MMC_U_BOOT_SIZE);
200
201 /*
202 * Jump to U-Boot image
203 */
204 uboot = (void *)CFG_SYS_MMC_U_BOOT_START;
205 (*uboot)();
206 }