blob: aa00d7e2014debd68af8cc0ebe9e3a20b77a4329 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Ying Zhang9ff70262013-08-16 15:16:11 +08002/*
3 * Copyright 2013 Freescale Semiconductor, Inc.
Ying Zhang9ff70262013-08-16 15:16:11 +08004 */
5
6#include <common.h>
Simon Glass63334482019-11-14 12:57:39 -07007#include <cpu_func.h>
Simon Glassf11478f2019-12-28 10:45:07 -07008#include <hang.h>
Ying Zhang9ff70262013-08-16 15:16:11 +08009#include <mmc.h>
10#include <malloc.h>
11
Pali Rohár7e6a4ee2022-08-05 22:09:41 +020012#ifndef CONFIG_SYS_MMC_U_BOOT_OFFS
13extern uchar mmc_u_boot_offs[];
14#endif
15
Ying Zhang9ff70262013-08-16 15:16:11 +080016/*
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 */
Pali Rohár8cff7ac2022-04-03 00:16:59 +020021#define ESDHC_BOOT_SIGNATURE_OFF 0x40
22#define ESDHC_BOOT_SIGNATURE 0x424f4f54
Ying Zhang9ff70262013-08-16 15:16:11 +080023#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
Ying Zhang9ff70262013-08-16 15:16:11 +080027
Prabhakar Kushwaha9ea255a2014-04-08 19:13:22 +053028
29void 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
Stephen Warrene73f2962015-12-07 11:38:48 -070047 err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt,
48 vdst);
Prabhakar Kushwaha9ea255a2014-04-08 19:13:22 +053049 if (err != blk_cnt) {
50 puts("spl: mmc read failed!!\n");
51 hang();
52 }
53}
54
Ying Zhang9ff70262013-08-16 15:16:11 +080055/*
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
61void __noreturn mmc_boot(void)
62{
63 __attribute__((noreturn)) void (*uboot)(void);
64 uint blk_start, blk_cnt, err;
Ying Zhang9ff70262013-08-16 15:16:11 +080065 uchar *tmp_buf;
Prabhakar Kushwaha568bb762014-03-31 15:32:03 +053066 u32 blklen;
Pali Roháreca18112022-04-04 18:33:11 +020067 u32 blk_off;
Pali Roháree0fdb42022-08-05 22:09:39 +020068#ifndef CONFIG_FSL_CORENET
Ying Zhang9ff70262013-08-16 15:16:11 +080069 uchar val;
Pali Rohár8cff7ac2022-04-03 00:16:59 +020070#ifndef CONFIG_SPL_FSL_PBL
71 u32 val32;
72#endif
Ying Zhang9ff70262013-08-16 15:16:11 +080073 uint i, byte_num;
Pali Roháreca18112022-04-04 18:33:11 +020074 u32 sector;
Prabhakar Kushwaha568bb762014-03-31 15:32:03 +053075#endif
Ying Zhang9ff70262013-08-16 15:16:11 +080076 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
Pali Rohára897c342022-04-03 00:17:01 +020085 if (mmc_init(mmc)) {
86 puts("spl: mmc device init failed!\n");
87 hang();
88 }
89
Ying Zhang9ff70262013-08-16 15:16:11 +080090 blklen = mmc->read_bl_len;
Pali Roháreca18112022-04-04 18:33:11 +020091 if (blklen < 512)
92 blklen = 512;
Ying Zhang9ff70262013-08-16 15:16:11 +080093 tmp_buf = malloc(blklen);
94 if (!tmp_buf) {
95 puts("spl: malloc memory failed!!\n");
96 hang();
97 }
Pali Roháreca18112022-04-04 18:33:11 +020098
Pali Roháree0fdb42022-08-05 22:09:39 +020099#ifdef CONFIG_FSL_CORENET
100 offset = CONFIG_SYS_MMC_U_BOOT_OFFS;
101#else
Pali Roháreca18112022-04-04 18:33:11 +0200102 sector = 0;
103again:
Ying Zhang9ff70262013-08-16 15:16:11 +0800104 memset(tmp_buf, 0, blklen);
105
106 /*
107 * Read source addr from sd card
108 */
Pali Roháreca18112022-04-04 18:33:11 +0200109 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);
Pali Rohár1ee59ef2022-05-11 20:28:28 +0200113 if (err != blk_cnt) {
Ying Zhang9ff70262013-08-16 15:16:11 +0800114 puts("spl: mmc read failed!!\n");
Ying Zhang9ff70262013-08-16 15:16:11 +0800115 hang();
116 }
117
Pali Rohár8cff7ac2022-04-03 00:16:59 +0200118#ifdef CONFIG_SPL_FSL_PBL
Pali Roháreca18112022-04-04 18:33:11 +0200119 val = *(tmp_buf + blk_off + MBRDBR_BOOT_SIG_55);
Ying Zhang9ff70262013-08-16 15:16:11 +0800120 if (0x55 != val) {
Pali Rohár8cff7ac2022-04-03 00:16:59 +0200121 puts("spl: mmc MBR/DBR signature is not valid!!\n");
Ying Zhang9ff70262013-08-16 15:16:11 +0800122 hang();
123 }
Pali Roháreca18112022-04-04 18:33:11 +0200124 val = *(tmp_buf + blk_off + MBRDBR_BOOT_SIG_AA);
Ying Zhang9ff70262013-08-16 15:16:11 +0800125 if (0xAA != val) {
Pali Rohár8cff7ac2022-04-03 00:16:59 +0200126 puts("spl: mmc MBR/DBR signature is not valid!!\n");
Ying Zhang9ff70262013-08-16 15:16:11 +0800127 hang();
128 }
Pali Rohár8cff7ac2022-04-03 00:16:59 +0200129#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++) {
Pali Roháreca18112022-04-04 18:33:11 +0200138 val = *(tmp_buf + blk_off + ESDHC_BOOT_SIGNATURE_OFF + i);
Pali Rohár8cff7ac2022-04-03 00:16:59 +0200139 val32 = (val32 << 8) + val;
140 }
141 if (val32 != ESDHC_BOOT_SIGNATURE) {
Pali Roháreca18112022-04-04 18:33:11 +0200142 /* BOOT signature may be on the first 24 sectors (each being 512 bytes) */
143 if (++sector < 24)
144 goto again;
Pali Rohár8cff7ac2022-04-03 00:16:59 +0200145 puts("spl: mmc BOOT signature is not valid!!\n");
146 hang();
147 }
148#endif
Ying Zhang9ff70262013-08-16 15:16:11 +0800149
150 byte_num = 4;
151 offset = 0;
152 for (i = 0; i < byte_num; i++) {
Pali Roháreca18112022-04-04 18:33:11 +0200153 val = *(tmp_buf + blk_off + ESDHC_BOOT_IMAGE_ADDR + i);
Ying Zhang9ff70262013-08-16 15:16:11 +0800154 offset = (offset << 8) + val;
155 }
Pali Rohár7e6a4ee2022-08-05 22:09:41 +0200156#ifndef CONFIG_SYS_MMC_U_BOOT_OFFS
157 offset += (ulong)&mmc_u_boot_offs - CONFIG_SPL_TEXT_BASE;
158#else
Ying Zhang9ff70262013-08-16 15:16:11 +0800159 offset += CONFIG_SYS_MMC_U_BOOT_OFFS;
Pali Rohár2d832072022-04-03 00:17:00 +0200160#endif
Pali Rohár7e6a4ee2022-08-05 22:09:41 +0200161#endif
Ying Zhang9ff70262013-08-16 15:16:11 +0800162 /*
163 * Load U-Boot image from mmc into RAM
164 */
Pali Rohár2d832072022-04-03 00:17:00 +0200165 code_len = CONFIG_SYS_MMC_U_BOOT_SIZE;
Pali Roháree0fdb42022-08-05 22:09:39 +0200166 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 }
Stephen Warrene73f2962015-12-07 11:38:48 -0700178 err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt,
Pali Roháree0fdb42022-08-05 22:09:39 +0200179 (uchar *)CONFIG_SYS_MMC_U_BOOT_DST +
180 (blk_off ? (mmc->read_bl_len - blk_off) : 0));
Ying Zhang9ff70262013-08-16 15:16:11 +0800181 if (err != blk_cnt) {
182 puts("spl: mmc read failed!!\n");
183 free(tmp_buf);
Ying Zhang9ff70262013-08-16 15:16:11 +0800184 hang();
185 }
Pali Roháree0fdb42022-08-05 22:09:39 +0200186 /*
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 *)CONFIG_SYS_MMC_U_BOOT_DST,
193 tmp_buf + blk_off, mmc->read_bl_len - blk_off);
Ying Zhang9ff70262013-08-16 15:16:11 +0800194
195 /*
196 * Clean d-cache and invalidate i-cache, to
197 * make sure that no stale data is executed.
198 */
199 flush_cache(CONFIG_SYS_MMC_U_BOOT_DST, CONFIG_SYS_MMC_U_BOOT_SIZE);
200
201 /*
202 * Jump to U-Boot image
203 */
204 uboot = (void *)CONFIG_SYS_MMC_U_BOOT_START;
205 (*uboot)();
206}