]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
bb0dc108 YZ |
2 | /* |
3 | * Copyright 2013 Freescale Semiconductor, Inc. | |
bb0dc108 YZ |
4 | */ |
5 | ||
6 | #include <common.h> | |
1eb69ae4 | 7 | #include <cpu_func.h> |
db41d65a | 8 | #include <hang.h> |
bb0dc108 YZ |
9 | #include <mmc.h> |
10 | #include <malloc.h> | |
11 | ||
65cc0e2a | 12 | #ifndef CFG_SYS_MMC_U_BOOT_OFFS |
5a428e75 T |
13 | extern uchar mmc_u_boot_offs[]; |
14 | #endif | |
15 | ||
bb0dc108 YZ |
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 | */ | |
0f58f033 T |
21 | #define ESDHC_BOOT_SIGNATURE_OFF 0x40 |
22 | #define ESDHC_BOOT_SIGNATURE 0x424f4f54 | |
bb0dc108 YZ |
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 | |
bb0dc108 | 27 | |
1eaa742d PK |
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 | ||
7c4213f6 SW |
47 | err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt, |
48 | vdst); | |
1eaa742d PK |
49 | if (err != blk_cnt) { |
50 | puts("spl: mmc read failed!!\n"); | |
51 | hang(); | |
52 | } | |
53 | } | |
54 | ||
bb0dc108 YZ |
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; | |
bb0dc108 | 65 | uchar *tmp_buf; |
613ab32c | 66 | u32 blklen; |
0980cbba | 67 | u32 blk_off; |
04e9cd7a | 68 | #ifndef CONFIG_FSL_CORENET |
bb0dc108 | 69 | uchar val; |
0f58f033 T |
70 | #ifndef CONFIG_SPL_FSL_PBL |
71 | u32 val32; | |
72 | #endif | |
bb0dc108 | 73 | uint i, byte_num; |
0980cbba | 74 | u32 sector; |
613ab32c | 75 | #endif |
bb0dc108 YZ |
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 | ||
57d527e7 T |
85 | if (mmc_init(mmc)) { |
86 | puts("spl: mmc device init failed!\n"); | |
87 | hang(); | |
88 | } | |
89 | ||
bb0dc108 | 90 | blklen = mmc->read_bl_len; |
0980cbba T |
91 | if (blklen < 512) |
92 | blklen = 512; | |
bb0dc108 YZ |
93 | tmp_buf = malloc(blklen); |
94 | if (!tmp_buf) { | |
95 | puts("spl: malloc memory failed!!\n"); | |
96 | hang(); | |
97 | } | |
0980cbba | 98 | |
04e9cd7a | 99 | #ifdef CONFIG_FSL_CORENET |
65cc0e2a | 100 | offset = CFG_SYS_MMC_U_BOOT_OFFS; |
04e9cd7a | 101 | #else |
0980cbba T |
102 | sector = 0; |
103 | again: | |
bb0dc108 YZ |
104 | memset(tmp_buf, 0, blklen); |
105 | ||
106 | /* | |
107 | * Read source addr from sd card | |
108 | */ | |
0980cbba T |
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); | |
c1abf765 | 113 | if (err != blk_cnt) { |
bb0dc108 | 114 | puts("spl: mmc read failed!!\n"); |
bb0dc108 YZ |
115 | hang(); |
116 | } | |
117 | ||
0f58f033 | 118 | #ifdef CONFIG_SPL_FSL_PBL |
0980cbba | 119 | val = *(tmp_buf + blk_off + MBRDBR_BOOT_SIG_55); |
bb0dc108 | 120 | if (0x55 != val) { |
0f58f033 | 121 | puts("spl: mmc MBR/DBR signature is not valid!!\n"); |
bb0dc108 YZ |
122 | hang(); |
123 | } | |
0980cbba | 124 | val = *(tmp_buf + blk_off + MBRDBR_BOOT_SIG_AA); |
bb0dc108 | 125 | if (0xAA != val) { |
0f58f033 | 126 | puts("spl: mmc MBR/DBR signature is not valid!!\n"); |
bb0dc108 YZ |
127 | hang(); |
128 | } | |
0f58f033 T |
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++) { | |
0980cbba | 138 | val = *(tmp_buf + blk_off + ESDHC_BOOT_SIGNATURE_OFF + i); |
0f58f033 T |
139 | val32 = (val32 << 8) + val; |
140 | } | |
141 | if (val32 != ESDHC_BOOT_SIGNATURE) { | |
0980cbba T |
142 | /* BOOT signature may be on the first 24 sectors (each being 512 bytes) */ |
143 | if (++sector < 24) | |
144 | goto again; | |
0f58f033 T |
145 | puts("spl: mmc BOOT signature is not valid!!\n"); |
146 | hang(); | |
147 | } | |
148 | #endif | |
bb0dc108 YZ |
149 | |
150 | byte_num = 4; | |
151 | offset = 0; | |
152 | for (i = 0; i < byte_num; i++) { | |
0980cbba | 153 | val = *(tmp_buf + blk_off + ESDHC_BOOT_IMAGE_ADDR + i); |
bb0dc108 YZ |
154 | offset = (offset << 8) + val; |
155 | } | |
65cc0e2a | 156 | #ifndef CFG_SYS_MMC_U_BOOT_OFFS |
5a428e75 T |
157 | offset += (ulong)&mmc_u_boot_offs - CONFIG_SPL_TEXT_BASE; |
158 | #else | |
65cc0e2a | 159 | offset += CFG_SYS_MMC_U_BOOT_OFFS; |
5a428e75 | 160 | #endif |
a91998d8 | 161 | #endif |
bb0dc108 YZ |
162 | /* |
163 | * Load U-Boot image from mmc into RAM | |
164 | */ | |
65cc0e2a | 165 | code_len = CFG_SYS_MMC_U_BOOT_SIZE; |
04e9cd7a T |
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 | } | |
7c4213f6 | 178 | err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt, |
65cc0e2a | 179 | (uchar *)CFG_SYS_MMC_U_BOOT_DST + |
04e9cd7a | 180 | (blk_off ? (mmc->read_bl_len - blk_off) : 0)); |
bb0dc108 YZ |
181 | if (err != blk_cnt) { |
182 | puts("spl: mmc read failed!!\n"); | |
183 | free(tmp_buf); | |
184 | hang(); | |
185 | } | |
04e9cd7a T |
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) | |
65cc0e2a | 192 | memcpy((uchar *)CFG_SYS_MMC_U_BOOT_DST, |
04e9cd7a | 193 | tmp_buf + blk_off, mmc->read_bl_len - blk_off); |
bb0dc108 YZ |
194 | |
195 | /* | |
196 | * Clean d-cache and invalidate i-cache, to | |
197 | * make sure that no stale data is executed. | |
198 | */ | |
65cc0e2a | 199 | flush_cache(CFG_SYS_MMC_U_BOOT_DST, CFG_SYS_MMC_U_BOOT_SIZE); |
bb0dc108 YZ |
200 | |
201 | /* | |
202 | * Jump to U-Boot image | |
203 | */ | |
65cc0e2a | 204 | uboot = (void *)CFG_SYS_MMC_U_BOOT_START; |
bb0dc108 YZ |
205 | (*uboot)(); |
206 | } |