]>
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> | |
7 | #include <mmc.h> | |
8 | #include <malloc.h> | |
9 | ||
10 | /* | |
11 | * The environment variables are written to just after the u-boot image | |
12 | * on SDCard, so we must read the MBR to get the start address and code | |
13 | * length of the u-boot image, then calculate the address of the env. | |
14 | */ | |
15 | #define ESDHC_BOOT_IMAGE_SIZE 0x48 | |
16 | #define ESDHC_BOOT_IMAGE_ADDR 0x50 | |
17 | #define MBRDBR_BOOT_SIG_55 0x1fe | |
18 | #define MBRDBR_BOOT_SIG_AA 0x1ff | |
19 | #define CONFIG_CFG_DATA_SECTOR 0 | |
20 | ||
1eaa742d PK |
21 | |
22 | void mmc_spl_load_image(uint32_t offs, unsigned int size, void *vdst) | |
23 | { | |
24 | uint blk_start, blk_cnt, err; | |
25 | ||
26 | struct mmc *mmc = find_mmc_device(0); | |
27 | if (!mmc) { | |
28 | puts("spl: mmc device not found!!\n"); | |
29 | hang(); | |
30 | } | |
31 | ||
32 | if (mmc_init(mmc)) { | |
33 | puts("MMC init failed\n"); | |
34 | return; | |
35 | } | |
36 | ||
37 | blk_start = ALIGN(offs, mmc->read_bl_len) / mmc->read_bl_len; | |
38 | blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len; | |
39 | ||
7c4213f6 SW |
40 | err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt, |
41 | vdst); | |
1eaa742d PK |
42 | if (err != blk_cnt) { |
43 | puts("spl: mmc read failed!!\n"); | |
44 | hang(); | |
45 | } | |
46 | } | |
47 | ||
bb0dc108 YZ |
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; | |
613ab32c | 58 | #ifndef CONFIG_FSL_CORENET |
bb0dc108 | 59 | uchar *tmp_buf; |
613ab32c | 60 | u32 blklen; |
bb0dc108 YZ |
61 | uchar val; |
62 | uint i, byte_num; | |
613ab32c | 63 | #endif |
bb0dc108 YZ |
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 | ||
4520a2f2 PJ |
73 | #ifdef CONFIG_FSL_CORENET |
74 | offset = CONFIG_SYS_MMC_U_BOOT_OFFS; | |
75 | code_len = CONFIG_SYS_MMC_U_BOOT_SIZE; | |
76 | #else | |
bb0dc108 YZ |
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 | */ | |
7c4213f6 SW |
88 | err = mmc->block_dev.block_read(&mmc->block_dev, |
89 | CONFIG_CFG_DATA_SECTOR, 1, tmp_buf); | |
bb0dc108 YZ |
90 | if (err != 1) { |
91 | puts("spl: mmc read failed!!\n"); | |
92 | free(tmp_buf); | |
93 | hang(); | |
94 | } | |
95 | ||
96 | val = *(tmp_buf + MBRDBR_BOOT_SIG_55); | |
97 | if (0x55 != val) { | |
98 | puts("spl: mmc signature is not valid!!\n"); | |
99 | free(tmp_buf); | |
100 | hang(); | |
101 | } | |
102 | val = *(tmp_buf + MBRDBR_BOOT_SIG_AA); | |
103 | if (0xAA != val) { | |
104 | puts("spl: mmc signature is not valid!!\n"); | |
105 | free(tmp_buf); | |
106 | hang(); | |
107 | } | |
108 | ||
109 | byte_num = 4; | |
110 | offset = 0; | |
111 | for (i = 0; i < byte_num; i++) { | |
112 | val = *(tmp_buf + ESDHC_BOOT_IMAGE_ADDR + i); | |
113 | offset = (offset << 8) + val; | |
114 | } | |
115 | offset += CONFIG_SYS_MMC_U_BOOT_OFFS; | |
116 | /* Get the code size from offset 0x48 */ | |
117 | byte_num = 4; | |
118 | code_len = 0; | |
119 | for (i = 0; i < byte_num; i++) { | |
120 | val = *(tmp_buf + ESDHC_BOOT_IMAGE_SIZE + i); | |
121 | code_len = (code_len << 8) + val; | |
122 | } | |
123 | code_len -= CONFIG_SYS_MMC_U_BOOT_OFFS; | |
124 | /* | |
125 | * Load U-Boot image from mmc into RAM | |
126 | */ | |
4520a2f2 | 127 | #endif |
bb0dc108 YZ |
128 | blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len; |
129 | blk_cnt = ALIGN(code_len, mmc->read_bl_len) / mmc->read_bl_len; | |
7c4213f6 | 130 | err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt, |
bb0dc108 YZ |
131 | (uchar *)CONFIG_SYS_MMC_U_BOOT_DST); |
132 | if (err != blk_cnt) { | |
133 | puts("spl: mmc read failed!!\n"); | |
613ab32c | 134 | #ifndef CONFIG_FSL_CORENET |
bb0dc108 | 135 | free(tmp_buf); |
613ab32c | 136 | #endif |
bb0dc108 YZ |
137 | hang(); |
138 | } | |
139 | ||
140 | /* | |
141 | * Clean d-cache and invalidate i-cache, to | |
142 | * make sure that no stale data is executed. | |
143 | */ | |
144 | flush_cache(CONFIG_SYS_MMC_U_BOOT_DST, CONFIG_SYS_MMC_U_BOOT_SIZE); | |
145 | ||
146 | /* | |
147 | * Jump to U-Boot image | |
148 | */ | |
149 | uboot = (void *)CONFIG_SYS_MMC_U_BOOT_START; | |
150 | (*uboot)(); | |
151 | } |