xref: /rk3399_rockchip-uboot/common/spl/spl_mmc.c (revision 79adb7a2b54b0b34ec4defac33d6ee8277976ddf)
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 
35*79adb7a2SPeter 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:
64*79adb7a2SPeter Korsgaard 	if (err == 0)
65ade8a1a6SYing Zhang 		printf("spl: mmc blk read err - %lu\n", err);
66*79adb7a2SPeter Korsgaard 
67*79adb7a2SPeter Korsgaard 	return (err == 0);
68ade8a1a6SYing Zhang }
69ade8a1a6SYing Zhang 
70ade8a1a6SYing Zhang #ifdef CONFIG_SPL_FAT_SUPPORT
71*79adb7a2SPeter Korsgaard static int mmc_load_image_fat(struct mmc *mmc)
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 
79ade8a1a6SYing Zhang 	err = fat_register_device(&mmc->block_dev,
80ade8a1a6SYing Zhang 				CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION);
81ade8a1a6SYing Zhang 	if (err) {
82ade8a1a6SYing Zhang 		printf("spl: fat register err - %d\n", err);
83ade8a1a6SYing Zhang 		hang();
84ade8a1a6SYing Zhang 	}
85ade8a1a6SYing Zhang 
86ade8a1a6SYing Zhang 	err = file_fat_read(CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME,
87ade8a1a6SYing Zhang 				header, sizeof(struct image_header));
88ade8a1a6SYing Zhang 	if (err <= 0)
89ade8a1a6SYing Zhang 		goto end;
90ade8a1a6SYing Zhang 
91ade8a1a6SYing Zhang 	spl_parse_image_header(header);
92ade8a1a6SYing Zhang 
93ade8a1a6SYing Zhang 	err = file_fat_read(CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME,
94ade8a1a6SYing Zhang 				(u8 *)spl_image.load_addr, 0);
95ade8a1a6SYing Zhang 
96ade8a1a6SYing Zhang end:
97*79adb7a2SPeter Korsgaard 	if (err <= 0)
98ade8a1a6SYing Zhang 		printf("spl: error reading image %s, err - %d\n",
99ade8a1a6SYing Zhang 			CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME, err);
100*79adb7a2SPeter Korsgaard 
101*79adb7a2SPeter Korsgaard 	return (err <= 0);
102ade8a1a6SYing Zhang }
103ade8a1a6SYing Zhang #endif
104ade8a1a6SYing Zhang 
105ade8a1a6SYing Zhang void spl_mmc_load_image(void)
106ade8a1a6SYing Zhang {
107ade8a1a6SYing Zhang 	struct mmc *mmc;
108ade8a1a6SYing Zhang 	int err;
109ade8a1a6SYing Zhang 	u32 boot_mode;
110ade8a1a6SYing Zhang 
111ade8a1a6SYing Zhang 	mmc_initialize(gd->bd);
112ade8a1a6SYing Zhang 	/* We register only one device. So, the dev id is always 0 */
113ade8a1a6SYing Zhang 	mmc = find_mmc_device(0);
114ade8a1a6SYing Zhang 	if (!mmc) {
115ade8a1a6SYing Zhang 		puts("spl: mmc device not found!!\n");
116ade8a1a6SYing Zhang 		hang();
117ade8a1a6SYing Zhang 	}
118ade8a1a6SYing Zhang 
119ade8a1a6SYing Zhang 	err = mmc_init(mmc);
120ade8a1a6SYing Zhang 	if (err) {
121ade8a1a6SYing Zhang 		printf("spl: mmc init failed: err - %d\n", err);
122ade8a1a6SYing Zhang 		hang();
123ade8a1a6SYing Zhang 	}
124*79adb7a2SPeter Korsgaard 
125ade8a1a6SYing Zhang 	boot_mode = spl_boot_mode();
126ade8a1a6SYing Zhang 	if (boot_mode == MMCSD_MODE_RAW) {
127ade8a1a6SYing Zhang 		debug("boot mode - RAW\n");
128*79adb7a2SPeter Korsgaard 		err = mmc_load_image_raw(mmc);
129ade8a1a6SYing Zhang #ifdef CONFIG_SPL_FAT_SUPPORT
130ade8a1a6SYing Zhang 	} else if (boot_mode == MMCSD_MODE_FAT) {
131ade8a1a6SYing Zhang 		debug("boot mode - FAT\n");
132*79adb7a2SPeter Korsgaard 		err = mmc_load_image_fat(mmc);
133ade8a1a6SYing Zhang #endif
134ade8a1a6SYing Zhang 	} else {
135ade8a1a6SYing Zhang 		puts("spl: wrong MMC boot mode\n");
136ade8a1a6SYing Zhang 		hang();
137ade8a1a6SYing Zhang 	}
138*79adb7a2SPeter Korsgaard 
139*79adb7a2SPeter Korsgaard 	if (err)
140*79adb7a2SPeter Korsgaard 		hang();
141ade8a1a6SYing Zhang }
142