sunxi: mmc: group non-DM specific functions
[platform/kernel/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 }