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