xref: /rk3399_rockchip-uboot/common/spl/spl_mmc.c (revision 2b75b0ad3a2a47492a6d03199d85632f9ee3e42b)
1ade8a1a6SYing Zhang /*
2ade8a1a6SYing Zhang  * (C) Copyright 2010
3ade8a1a6SYing Zhang  * Texas Instruments, <www.ti.com>
4ade8a1a6SYing Zhang  *
5ade8a1a6SYing Zhang  * Aneesh V <aneesh@ti.com>
6ade8a1a6SYing Zhang  *
7ade8a1a6SYing Zhang  * See file CREDITS for list of people who contributed to this
8ade8a1a6SYing Zhang  * project.
9ade8a1a6SYing Zhang  *
10ade8a1a6SYing Zhang  * This program is free software; you can redistribute it and/or
11ade8a1a6SYing Zhang  * modify it under the terms of the GNU General Public License as
12ade8a1a6SYing Zhang  * published by the Free Software Foundation; either version 2 of
13ade8a1a6SYing Zhang  * the License, or (at your option) any later version.
14ade8a1a6SYing Zhang  *
15ade8a1a6SYing Zhang  * This program is distributed in the hope that it will be useful,
16ade8a1a6SYing Zhang  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17ade8a1a6SYing Zhang  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18ade8a1a6SYing Zhang  * GNU General Public License for more details.
19ade8a1a6SYing Zhang  *
20ade8a1a6SYing Zhang  * You should have received a copy of the GNU General Public License
21ade8a1a6SYing Zhang  * along with this program; if not, write to the Free Software
22ade8a1a6SYing Zhang  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23ade8a1a6SYing Zhang  * MA 02111-1307 USA
24ade8a1a6SYing Zhang  */
25ade8a1a6SYing Zhang #include <common.h>
26ade8a1a6SYing Zhang #include <spl.h>
27ade8a1a6SYing Zhang #include <asm/u-boot.h>
28ade8a1a6SYing Zhang #include <asm/utils.h>
29ade8a1a6SYing Zhang #include <mmc.h>
30ade8a1a6SYing Zhang #include <fat.h>
31ade8a1a6SYing Zhang #include <version.h>
32ade8a1a6SYing Zhang 
33ade8a1a6SYing Zhang DECLARE_GLOBAL_DATA_PTR;
34ade8a1a6SYing Zhang 
35721931f8SPeter Korsgaard static int mmc_load_image_raw(struct mmc *mmc, unsigned long sector)
36ade8a1a6SYing Zhang {
37ade8a1a6SYing Zhang 	unsigned long err;
38ade8a1a6SYing Zhang 	u32 image_size_sectors;
39ade8a1a6SYing Zhang 	struct image_header *header;
40ade8a1a6SYing Zhang 
41ade8a1a6SYing Zhang 	header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
42ade8a1a6SYing Zhang 						sizeof(struct image_header));
43ade8a1a6SYing Zhang 
44ade8a1a6SYing Zhang 	/* read image header to find the image size & load address */
45721931f8SPeter Korsgaard 	err = mmc->block_dev.block_read(0, sector, 1, header);
46ade8a1a6SYing Zhang 	if (err == 0)
47ade8a1a6SYing Zhang 		goto end;
48ade8a1a6SYing Zhang 
49ade8a1a6SYing Zhang 	spl_parse_image_header(header);
50ade8a1a6SYing Zhang 
51ade8a1a6SYing Zhang 	/* convert size to sectors - round up */
52ade8a1a6SYing Zhang 	image_size_sectors = (spl_image.size + mmc->read_bl_len - 1) /
53ade8a1a6SYing Zhang 				mmc->read_bl_len;
54ade8a1a6SYing Zhang 
55ade8a1a6SYing Zhang 	/* Read the header too to avoid extra memcpy */
56721931f8SPeter Korsgaard 	err = mmc->block_dev.block_read(0, sector, image_size_sectors,
57721931f8SPeter Korsgaard 					(void *)spl_image.load_addr);
58ade8a1a6SYing Zhang 
59ade8a1a6SYing Zhang end:
6079adb7a2SPeter Korsgaard 	if (err == 0)
61ade8a1a6SYing Zhang 		printf("spl: mmc blk read err - %lu\n", err);
6279adb7a2SPeter Korsgaard 
6379adb7a2SPeter Korsgaard 	return (err == 0);
64ade8a1a6SYing Zhang }
65ade8a1a6SYing Zhang 
66*2b75b0adSPeter Korsgaard #ifdef CONFIG_SPL_OS_BOOT
67*2b75b0adSPeter Korsgaard static int mmc_load_image_raw_os(struct mmc *mmc)
68*2b75b0adSPeter Korsgaard {
69*2b75b0adSPeter Korsgaard 	if (!mmc->block_dev.block_read(0,
70*2b75b0adSPeter Korsgaard 				       CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR,
71*2b75b0adSPeter Korsgaard 				       CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS,
72*2b75b0adSPeter Korsgaard 				       (void *)CONFIG_SYS_SPL_ARGS_ADDR)) {
73*2b75b0adSPeter Korsgaard 		printf("mmc args blk read error\n");
74*2b75b0adSPeter Korsgaard 		return -1;
75*2b75b0adSPeter Korsgaard 	}
76*2b75b0adSPeter Korsgaard 
77*2b75b0adSPeter Korsgaard 	return mmc_load_image_raw(mmc, CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR);
78*2b75b0adSPeter Korsgaard }
79*2b75b0adSPeter Korsgaard #endif
80*2b75b0adSPeter Korsgaard 
81ade8a1a6SYing Zhang #ifdef CONFIG_SPL_FAT_SUPPORT
822fabd0bcSPeter Korsgaard static int mmc_load_image_fat(struct mmc *mmc, const char *filename)
83ade8a1a6SYing Zhang {
84ade8a1a6SYing Zhang 	int err;
85ade8a1a6SYing Zhang 	struct image_header *header;
86ade8a1a6SYing Zhang 
87ade8a1a6SYing Zhang 	header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
88ade8a1a6SYing Zhang 						sizeof(struct image_header));
89ade8a1a6SYing Zhang 
902fabd0bcSPeter Korsgaard 	err = file_fat_read(filename, header, sizeof(struct image_header));
91ade8a1a6SYing Zhang 	if (err <= 0)
92ade8a1a6SYing Zhang 		goto end;
93ade8a1a6SYing Zhang 
94ade8a1a6SYing Zhang 	spl_parse_image_header(header);
95ade8a1a6SYing Zhang 
962fabd0bcSPeter Korsgaard 	err = file_fat_read(filename, (u8 *)spl_image.load_addr, 0);
97ade8a1a6SYing Zhang 
98ade8a1a6SYing Zhang end:
9979adb7a2SPeter Korsgaard 	if (err <= 0)
100ade8a1a6SYing Zhang 		printf("spl: error reading image %s, err - %d\n",
1012fabd0bcSPeter Korsgaard 		       filename, err);
10279adb7a2SPeter Korsgaard 
10379adb7a2SPeter Korsgaard 	return (err <= 0);
104ade8a1a6SYing Zhang }
1057ad2cc79SPeter Korsgaard 
1067ad2cc79SPeter Korsgaard #ifdef CONFIG_SPL_OS_BOOT
1077ad2cc79SPeter Korsgaard static int mmc_load_image_fat_os(struct mmc *mmc)
1087ad2cc79SPeter Korsgaard {
1097ad2cc79SPeter Korsgaard 	int err;
1107ad2cc79SPeter Korsgaard 
1117ad2cc79SPeter Korsgaard 	err = file_fat_read(CONFIG_SPL_FAT_LOAD_ARGS_NAME,
1127ad2cc79SPeter Korsgaard 			    (void *)CONFIG_SYS_SPL_ARGS_ADDR, 0);
1137ad2cc79SPeter Korsgaard 	if (err <= 0) {
1147ad2cc79SPeter Korsgaard 		printf("spl: error reading image %s, err - %d\n",
1157ad2cc79SPeter Korsgaard 		       CONFIG_SPL_FAT_LOAD_ARGS_NAME, err);
1167ad2cc79SPeter Korsgaard 		return -1;
1177ad2cc79SPeter Korsgaard 	}
1187ad2cc79SPeter Korsgaard 
1197ad2cc79SPeter Korsgaard 	return mmc_load_image_fat(mmc, CONFIG_SPL_FAT_LOAD_KERNEL_NAME);
1207ad2cc79SPeter Korsgaard }
1217ad2cc79SPeter Korsgaard #endif
1227ad2cc79SPeter Korsgaard 
123ade8a1a6SYing Zhang #endif
124ade8a1a6SYing Zhang 
125ade8a1a6SYing Zhang void spl_mmc_load_image(void)
126ade8a1a6SYing Zhang {
127ade8a1a6SYing Zhang 	struct mmc *mmc;
128ade8a1a6SYing Zhang 	int err;
129ade8a1a6SYing Zhang 	u32 boot_mode;
130ade8a1a6SYing Zhang 
131ade8a1a6SYing Zhang 	mmc_initialize(gd->bd);
132ade8a1a6SYing Zhang 	/* We register only one device. So, the dev id is always 0 */
133ade8a1a6SYing Zhang 	mmc = find_mmc_device(0);
134ade8a1a6SYing Zhang 	if (!mmc) {
135ade8a1a6SYing Zhang 		puts("spl: mmc device not found!!\n");
136ade8a1a6SYing Zhang 		hang();
137ade8a1a6SYing Zhang 	}
138ade8a1a6SYing Zhang 
139ade8a1a6SYing Zhang 	err = mmc_init(mmc);
140ade8a1a6SYing Zhang 	if (err) {
141ade8a1a6SYing Zhang 		printf("spl: mmc init failed: err - %d\n", err);
142ade8a1a6SYing Zhang 		hang();
143ade8a1a6SYing Zhang 	}
14479adb7a2SPeter Korsgaard 
145ade8a1a6SYing Zhang 	boot_mode = spl_boot_mode();
146ade8a1a6SYing Zhang 	if (boot_mode == MMCSD_MODE_RAW) {
147ade8a1a6SYing Zhang 		debug("boot mode - RAW\n");
148*2b75b0adSPeter Korsgaard #ifdef CONFIG_SPL_OS_BOOT
149*2b75b0adSPeter Korsgaard 		if (spl_start_uboot() || mmc_load_image_raw_os(mmc))
150*2b75b0adSPeter Korsgaard #endif
151721931f8SPeter Korsgaard 		err = mmc_load_image_raw(mmc,
152721931f8SPeter Korsgaard 					 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
153ade8a1a6SYing Zhang #ifdef CONFIG_SPL_FAT_SUPPORT
154ade8a1a6SYing Zhang 	} else if (boot_mode == MMCSD_MODE_FAT) {
155ade8a1a6SYing Zhang 		debug("boot mode - FAT\n");
1562fabd0bcSPeter Korsgaard 
1572fabd0bcSPeter Korsgaard 		err = fat_register_device(&mmc->block_dev,
1582fabd0bcSPeter Korsgaard 					  CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION);
1592fabd0bcSPeter Korsgaard 		if (err) {
1602fabd0bcSPeter Korsgaard 			printf("spl: fat register err - %d\n", err);
1612fabd0bcSPeter Korsgaard 			hang();
1622fabd0bcSPeter Korsgaard 		}
1632fabd0bcSPeter Korsgaard 
1647ad2cc79SPeter Korsgaard #ifdef CONFIG_SPL_OS_BOOT
1657ad2cc79SPeter Korsgaard 		if (spl_start_uboot() || mmc_load_image_fat_os(mmc))
1667ad2cc79SPeter Korsgaard #endif
1672fabd0bcSPeter Korsgaard 		err = mmc_load_image_fat(mmc, CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME);
168ade8a1a6SYing Zhang #endif
169ade8a1a6SYing Zhang 	} else {
170ade8a1a6SYing Zhang 		puts("spl: wrong MMC boot mode\n");
171ade8a1a6SYing Zhang 		hang();
172ade8a1a6SYing Zhang 	}
17379adb7a2SPeter Korsgaard 
17479adb7a2SPeter Korsgaard 	if (err)
17579adb7a2SPeter Korsgaard 		hang();
176ade8a1a6SYing Zhang }
177