xref: /rk3399_rockchip-uboot/common/spl/spl_mmc.c (revision 7ad2cc7964d37f3a444a0472bbccda487d51c7f6)
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 
3579adb7a2SPeter Korsgaard static int mmc_load_image_raw(struct mmc *mmc)
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 */
45ade8a1a6SYing Zhang 	err = mmc->block_dev.block_read(0,
46ade8a1a6SYing Zhang 			CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR, 1,
47ade8a1a6SYing Zhang 			header);
48ade8a1a6SYing Zhang 
49ade8a1a6SYing Zhang 	if (err == 0)
50ade8a1a6SYing Zhang 		goto end;
51ade8a1a6SYing Zhang 
52ade8a1a6SYing Zhang 	spl_parse_image_header(header);
53ade8a1a6SYing Zhang 
54ade8a1a6SYing Zhang 	/* convert size to sectors - round up */
55ade8a1a6SYing Zhang 	image_size_sectors = (spl_image.size + mmc->read_bl_len - 1) /
56ade8a1a6SYing Zhang 				mmc->read_bl_len;
57ade8a1a6SYing Zhang 
58ade8a1a6SYing Zhang 	/* Read the header too to avoid extra memcpy */
59ade8a1a6SYing Zhang 	err = mmc->block_dev.block_read(0,
60ade8a1a6SYing Zhang 			CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR,
61ade8a1a6SYing Zhang 			image_size_sectors, (void *)spl_image.load_addr);
62ade8a1a6SYing Zhang 
63ade8a1a6SYing Zhang end:
6479adb7a2SPeter Korsgaard 	if (err == 0)
65ade8a1a6SYing Zhang 		printf("spl: mmc blk read err - %lu\n", err);
6679adb7a2SPeter Korsgaard 
6779adb7a2SPeter Korsgaard 	return (err == 0);
68ade8a1a6SYing Zhang }
69ade8a1a6SYing Zhang 
70ade8a1a6SYing Zhang #ifdef CONFIG_SPL_FAT_SUPPORT
712fabd0bcSPeter Korsgaard static int mmc_load_image_fat(struct mmc *mmc, const char *filename)
72ade8a1a6SYing Zhang {
73ade8a1a6SYing Zhang 	int err;
74ade8a1a6SYing Zhang 	struct image_header *header;
75ade8a1a6SYing Zhang 
76ade8a1a6SYing Zhang 	header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
77ade8a1a6SYing Zhang 						sizeof(struct image_header));
78ade8a1a6SYing Zhang 
792fabd0bcSPeter Korsgaard 	err = file_fat_read(filename, header, sizeof(struct image_header));
80ade8a1a6SYing Zhang 	if (err <= 0)
81ade8a1a6SYing Zhang 		goto end;
82ade8a1a6SYing Zhang 
83ade8a1a6SYing Zhang 	spl_parse_image_header(header);
84ade8a1a6SYing Zhang 
852fabd0bcSPeter Korsgaard 	err = file_fat_read(filename, (u8 *)spl_image.load_addr, 0);
86ade8a1a6SYing Zhang 
87ade8a1a6SYing Zhang end:
8879adb7a2SPeter Korsgaard 	if (err <= 0)
89ade8a1a6SYing Zhang 		printf("spl: error reading image %s, err - %d\n",
902fabd0bcSPeter Korsgaard 		       filename, err);
9179adb7a2SPeter Korsgaard 
9279adb7a2SPeter Korsgaard 	return (err <= 0);
93ade8a1a6SYing Zhang }
94*7ad2cc79SPeter Korsgaard 
95*7ad2cc79SPeter Korsgaard #ifdef CONFIG_SPL_OS_BOOT
96*7ad2cc79SPeter Korsgaard static int mmc_load_image_fat_os(struct mmc *mmc)
97*7ad2cc79SPeter Korsgaard {
98*7ad2cc79SPeter Korsgaard 	int err;
99*7ad2cc79SPeter Korsgaard 
100*7ad2cc79SPeter Korsgaard 	err = file_fat_read(CONFIG_SPL_FAT_LOAD_ARGS_NAME,
101*7ad2cc79SPeter Korsgaard 			    (void *)CONFIG_SYS_SPL_ARGS_ADDR, 0);
102*7ad2cc79SPeter Korsgaard 	if (err <= 0) {
103*7ad2cc79SPeter Korsgaard 		printf("spl: error reading image %s, err - %d\n",
104*7ad2cc79SPeter Korsgaard 		       CONFIG_SPL_FAT_LOAD_ARGS_NAME, err);
105*7ad2cc79SPeter Korsgaard 		return -1;
106*7ad2cc79SPeter Korsgaard 	}
107*7ad2cc79SPeter Korsgaard 
108*7ad2cc79SPeter Korsgaard 	return mmc_load_image_fat(mmc, CONFIG_SPL_FAT_LOAD_KERNEL_NAME);
109*7ad2cc79SPeter Korsgaard }
110*7ad2cc79SPeter Korsgaard #endif
111*7ad2cc79SPeter Korsgaard 
112ade8a1a6SYing Zhang #endif
113ade8a1a6SYing Zhang 
114ade8a1a6SYing Zhang void spl_mmc_load_image(void)
115ade8a1a6SYing Zhang {
116ade8a1a6SYing Zhang 	struct mmc *mmc;
117ade8a1a6SYing Zhang 	int err;
118ade8a1a6SYing Zhang 	u32 boot_mode;
119ade8a1a6SYing Zhang 
120ade8a1a6SYing Zhang 	mmc_initialize(gd->bd);
121ade8a1a6SYing Zhang 	/* We register only one device. So, the dev id is always 0 */
122ade8a1a6SYing Zhang 	mmc = find_mmc_device(0);
123ade8a1a6SYing Zhang 	if (!mmc) {
124ade8a1a6SYing Zhang 		puts("spl: mmc device not found!!\n");
125ade8a1a6SYing Zhang 		hang();
126ade8a1a6SYing Zhang 	}
127ade8a1a6SYing Zhang 
128ade8a1a6SYing Zhang 	err = mmc_init(mmc);
129ade8a1a6SYing Zhang 	if (err) {
130ade8a1a6SYing Zhang 		printf("spl: mmc init failed: err - %d\n", err);
131ade8a1a6SYing Zhang 		hang();
132ade8a1a6SYing Zhang 	}
13379adb7a2SPeter Korsgaard 
134ade8a1a6SYing Zhang 	boot_mode = spl_boot_mode();
135ade8a1a6SYing Zhang 	if (boot_mode == MMCSD_MODE_RAW) {
136ade8a1a6SYing Zhang 		debug("boot mode - RAW\n");
13779adb7a2SPeter Korsgaard 		err = mmc_load_image_raw(mmc);
138ade8a1a6SYing Zhang #ifdef CONFIG_SPL_FAT_SUPPORT
139ade8a1a6SYing Zhang 	} else if (boot_mode == MMCSD_MODE_FAT) {
140ade8a1a6SYing Zhang 		debug("boot mode - FAT\n");
1412fabd0bcSPeter Korsgaard 
1422fabd0bcSPeter Korsgaard 		err = fat_register_device(&mmc->block_dev,
1432fabd0bcSPeter Korsgaard 					  CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION);
1442fabd0bcSPeter Korsgaard 		if (err) {
1452fabd0bcSPeter Korsgaard 			printf("spl: fat register err - %d\n", err);
1462fabd0bcSPeter Korsgaard 			hang();
1472fabd0bcSPeter Korsgaard 		}
1482fabd0bcSPeter Korsgaard 
149*7ad2cc79SPeter Korsgaard #ifdef CONFIG_SPL_OS_BOOT
150*7ad2cc79SPeter Korsgaard 		if (spl_start_uboot() || mmc_load_image_fat_os(mmc))
151*7ad2cc79SPeter Korsgaard #endif
1522fabd0bcSPeter Korsgaard 		err = mmc_load_image_fat(mmc, CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME);
153ade8a1a6SYing Zhang #endif
154ade8a1a6SYing Zhang 	} else {
155ade8a1a6SYing Zhang 		puts("spl: wrong MMC boot mode\n");
156ade8a1a6SYing Zhang 		hang();
157ade8a1a6SYing Zhang 	}
15879adb7a2SPeter Korsgaard 
15979adb7a2SPeter Korsgaard 	if (err)
16079adb7a2SPeter Korsgaard 		hang();
161ade8a1a6SYing Zhang }
162