blob: 3dd106bed4bf284c7606b5c96aca015fab0e8b49 [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
Tom Rinidec7ea02024-05-20 13:35:03 -06006#include <config.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
Tom Rini6a5dccc2022-11-16 13:10:41 -050012#ifndef CFG_SYS_MMC_U_BOOT_OFFS
Pali Rohár7e6a4ee2022-08-05 22:09:41 +020013extern 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 +053028void 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
Stephen Warrene73f2962015-12-07 11:38:48 -070046 err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt,
47 vdst);
Prabhakar Kushwaha9ea255a2014-04-08 19:13:22 +053048 if (err != blk_cnt) {
49 puts("spl: mmc read failed!!\n");
50 hang();
51 }
52}
53
Ying Zhang9ff70262013-08-16 15:16:11 +080054/*
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
60void __noreturn mmc_boot(void)
61{
62 __attribute__((noreturn)) void (*uboot)(void);
63 uint blk_start, blk_cnt, err;
Ying Zhang9ff70262013-08-16 15:16:11 +080064 uchar *tmp_buf;
Prabhakar Kushwaha568bb762014-03-31 15:32:03 +053065 u32 blklen;
Pali Roháreca18112022-04-04 18:33:11 +020066 u32 blk_off;
Pali Roháree0fdb42022-08-05 22:09:39 +020067#ifndef CONFIG_FSL_CORENET
Ying Zhang9ff70262013-08-16 15:16:11 +080068 uchar val;
Pali Rohár8cff7ac2022-04-03 00:16:59 +020069#ifndef CONFIG_SPL_FSL_PBL
70 u32 val32;
71#endif
Ying Zhang9ff70262013-08-16 15:16:11 +080072 uint i, byte_num;
Pali Roháreca18112022-04-04 18:33:11 +020073 u32 sector;
Prabhakar Kushwaha568bb762014-03-31 15:32:03 +053074#endif
Ying Zhang9ff70262013-08-16 15:16:11 +080075 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
Pali Rohára897c342022-04-03 00:17:01 +020084 if (mmc_init(mmc)) {
85 puts("spl: mmc device init failed!\n");
86 hang();
87 }
88
Ying Zhang9ff70262013-08-16 15:16:11 +080089 blklen = mmc->read_bl_len;
Pali Roháreca18112022-04-04 18:33:11 +020090 if (blklen < 512)
91 blklen = 512;
Ying Zhang9ff70262013-08-16 15:16:11 +080092 tmp_buf = malloc(blklen);
93 if (!tmp_buf) {
94 puts("spl: malloc memory failed!!\n");
95 hang();
96 }
Pali Roháreca18112022-04-04 18:33:11 +020097
Pali Roháree0fdb42022-08-05 22:09:39 +020098#ifdef CONFIG_FSL_CORENET
Tom Rini6a5dccc2022-11-16 13:10:41 -050099 offset = CFG_SYS_MMC_U_BOOT_OFFS;
Pali Roháree0fdb42022-08-05 22:09:39 +0200100#else
Pali Roháreca18112022-04-04 18:33:11 +0200101 sector = 0;
102again:
Ying Zhang9ff70262013-08-16 15:16:11 +0800103 memset(tmp_buf, 0, blklen);
104
105 /*
106 * Read source addr from sd card
107 */
Pali Roháreca18112022-04-04 18:33:11 +0200108 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);
Pali Rohár1ee59ef2022-05-11 20:28:28 +0200112 if (err != blk_cnt) {
Ying Zhang9ff70262013-08-16 15:16:11 +0800113 puts("spl: mmc read failed!!\n");
Ying Zhang9ff70262013-08-16 15:16:11 +0800114 hang();
115 }
116
Pali Rohár8cff7ac2022-04-03 00:16:59 +0200117#ifdef CONFIG_SPL_FSL_PBL
Pali Roháreca18112022-04-04 18:33:11 +0200118 val = *(tmp_buf + blk_off + MBRDBR_BOOT_SIG_55);
Ying Zhang9ff70262013-08-16 15:16:11 +0800119 if (0x55 != val) {
Pali Rohár8cff7ac2022-04-03 00:16:59 +0200120 puts("spl: mmc MBR/DBR signature is not valid!!\n");
Ying Zhang9ff70262013-08-16 15:16:11 +0800121 hang();
122 }
Pali Roháreca18112022-04-04 18:33:11 +0200123 val = *(tmp_buf + blk_off + MBRDBR_BOOT_SIG_AA);
Ying Zhang9ff70262013-08-16 15:16:11 +0800124 if (0xAA != val) {
Pali Rohár8cff7ac2022-04-03 00:16:59 +0200125 puts("spl: mmc MBR/DBR signature is not valid!!\n");
Ying Zhang9ff70262013-08-16 15:16:11 +0800126 hang();
127 }
Pali Rohár8cff7ac2022-04-03 00:16:59 +0200128#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++) {
Pali Roháreca18112022-04-04 18:33:11 +0200137 val = *(tmp_buf + blk_off + ESDHC_BOOT_SIGNATURE_OFF + i);
Pali Rohár8cff7ac2022-04-03 00:16:59 +0200138 val32 = (val32 << 8) + val;
139 }
140 if (val32 != ESDHC_BOOT_SIGNATURE) {
Pali Roháreca18112022-04-04 18:33:11 +0200141 /* BOOT signature may be on the first 24 sectors (each being 512 bytes) */
142 if (++sector < 24)
143 goto again;
Pali Rohár8cff7ac2022-04-03 00:16:59 +0200144 puts("spl: mmc BOOT signature is not valid!!\n");
145 hang();
146 }
147#endif
Ying Zhang9ff70262013-08-16 15:16:11 +0800148
149 byte_num = 4;
150 offset = 0;
151 for (i = 0; i < byte_num; i++) {
Pali Roháreca18112022-04-04 18:33:11 +0200152 val = *(tmp_buf + blk_off + ESDHC_BOOT_IMAGE_ADDR + i);
Ying Zhang9ff70262013-08-16 15:16:11 +0800153 offset = (offset << 8) + val;
154 }
Tom Rini6a5dccc2022-11-16 13:10:41 -0500155#ifndef CFG_SYS_MMC_U_BOOT_OFFS
Pali Rohár7e6a4ee2022-08-05 22:09:41 +0200156 offset += (ulong)&mmc_u_boot_offs - CONFIG_SPL_TEXT_BASE;
157#else
Tom Rini6a5dccc2022-11-16 13:10:41 -0500158 offset += CFG_SYS_MMC_U_BOOT_OFFS;
Pali Rohár2d832072022-04-03 00:17:00 +0200159#endif
Pali Rohár7e6a4ee2022-08-05 22:09:41 +0200160#endif
Ying Zhang9ff70262013-08-16 15:16:11 +0800161 /*
162 * Load U-Boot image from mmc into RAM
163 */
Tom Rini6a5dccc2022-11-16 13:10:41 -0500164 code_len = CFG_SYS_MMC_U_BOOT_SIZE;
Pali Roháree0fdb42022-08-05 22:09:39 +0200165 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 }
Stephen Warrene73f2962015-12-07 11:38:48 -0700177 err = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt,
Tom Rini6a5dccc2022-11-16 13:10:41 -0500178 (uchar *)CFG_SYS_MMC_U_BOOT_DST +
Pali Roháree0fdb42022-08-05 22:09:39 +0200179 (blk_off ? (mmc->read_bl_len - blk_off) : 0));
Ying Zhang9ff70262013-08-16 15:16:11 +0800180 if (err != blk_cnt) {
181 puts("spl: mmc read failed!!\n");
182 free(tmp_buf);
Ying Zhang9ff70262013-08-16 15:16:11 +0800183 hang();
184 }
Pali Roháree0fdb42022-08-05 22:09:39 +0200185 /*
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)
Tom Rini6a5dccc2022-11-16 13:10:41 -0500191 memcpy((uchar *)CFG_SYS_MMC_U_BOOT_DST,
Pali Roháree0fdb42022-08-05 22:09:39 +0200192 tmp_buf + blk_off, mmc->read_bl_len - blk_off);
Ying Zhang9ff70262013-08-16 15:16:11 +0800193
194 /*
195 * Clean d-cache and invalidate i-cache, to
196 * make sure that no stale data is executed.
197 */
Tom Rini6a5dccc2022-11-16 13:10:41 -0500198 flush_cache(CFG_SYS_MMC_U_BOOT_DST, CFG_SYS_MMC_U_BOOT_SIZE);
Ying Zhang9ff70262013-08-16 15:16:11 +0800199
200 /*
201 * Jump to U-Boot image
202 */
Tom Rini6a5dccc2022-11-16 13:10:41 -0500203 uboot = (void *)CFG_SYS_MMC_U_BOOT_START;
Ying Zhang9ff70262013-08-16 15:16:11 +0800204 (*uboot)();
205}