xref: /rk3399_rockchip-uboot/common/spl/spl_mmc.c (revision 2fabd0bcaa941e6b960077cf7693ca3a98fa655f)
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
71*2fabd0bcSPeter 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 
79*2fabd0bcSPeter 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 
85*2fabd0bcSPeter 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",
90*2fabd0bcSPeter Korsgaard 		       filename, err);
9179adb7a2SPeter Korsgaard 
9279adb7a2SPeter Korsgaard 	return (err <= 0);
93ade8a1a6SYing Zhang }
94ade8a1a6SYing Zhang #endif
95ade8a1a6SYing Zhang 
96ade8a1a6SYing Zhang void spl_mmc_load_image(void)
97ade8a1a6SYing Zhang {
98ade8a1a6SYing Zhang 	struct mmc *mmc;
99ade8a1a6SYing Zhang 	int err;
100ade8a1a6SYing Zhang 	u32 boot_mode;
101ade8a1a6SYing Zhang 
102ade8a1a6SYing Zhang 	mmc_initialize(gd->bd);
103ade8a1a6SYing Zhang 	/* We register only one device. So, the dev id is always 0 */
104ade8a1a6SYing Zhang 	mmc = find_mmc_device(0);
105ade8a1a6SYing Zhang 	if (!mmc) {
106ade8a1a6SYing Zhang 		puts("spl: mmc device not found!!\n");
107ade8a1a6SYing Zhang 		hang();
108ade8a1a6SYing Zhang 	}
109ade8a1a6SYing Zhang 
110ade8a1a6SYing Zhang 	err = mmc_init(mmc);
111ade8a1a6SYing Zhang 	if (err) {
112ade8a1a6SYing Zhang 		printf("spl: mmc init failed: err - %d\n", err);
113ade8a1a6SYing Zhang 		hang();
114ade8a1a6SYing Zhang 	}
11579adb7a2SPeter Korsgaard 
116ade8a1a6SYing Zhang 	boot_mode = spl_boot_mode();
117ade8a1a6SYing Zhang 	if (boot_mode == MMCSD_MODE_RAW) {
118ade8a1a6SYing Zhang 		debug("boot mode - RAW\n");
11979adb7a2SPeter Korsgaard 		err = mmc_load_image_raw(mmc);
120ade8a1a6SYing Zhang #ifdef CONFIG_SPL_FAT_SUPPORT
121ade8a1a6SYing Zhang 	} else if (boot_mode == MMCSD_MODE_FAT) {
122ade8a1a6SYing Zhang 		debug("boot mode - FAT\n");
123*2fabd0bcSPeter Korsgaard 
124*2fabd0bcSPeter Korsgaard 		err = fat_register_device(&mmc->block_dev,
125*2fabd0bcSPeter Korsgaard 					  CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION);
126*2fabd0bcSPeter Korsgaard 		if (err) {
127*2fabd0bcSPeter Korsgaard 			printf("spl: fat register err - %d\n", err);
128*2fabd0bcSPeter Korsgaard 			hang();
129*2fabd0bcSPeter Korsgaard 		}
130*2fabd0bcSPeter Korsgaard 
131*2fabd0bcSPeter Korsgaard 		err = mmc_load_image_fat(mmc, CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME);
132ade8a1a6SYing Zhang #endif
133ade8a1a6SYing Zhang 	} else {
134ade8a1a6SYing Zhang 		puts("spl: wrong MMC boot mode\n");
135ade8a1a6SYing Zhang 		hang();
136ade8a1a6SYing Zhang 	}
13779adb7a2SPeter Korsgaard 
13879adb7a2SPeter Korsgaard 	if (err)
13979adb7a2SPeter Korsgaard 		hang();
140ade8a1a6SYing Zhang }
141