From 8ead31f9eee7c63b1679c387af98b834f2123b6d Mon Sep 17 00:00:00 2001
From: Aneesh V <aneesh@ti.com>
Date: Thu, 17 Feb 2011 18:02:44 +0530
Subject: [PATCH 20/22] omap: add MMC support to SPL

Signed-off-by: Aneesh V <aneesh@ti.com>
---
 arch/arm/cpu/armv7/start.S         |    1 +
 arch/arm/include/asm/omap_common.h |    4 +
 include/configs/omap4_sdp4430.h    |    7 ++-
 spl/board/ti/sdp4430/Makefile      |   35 +++++++++++
 spl/board/ti/spl-omap.c            |  112 +++++++++++++++++++++++++++++++++++-
 5 files changed, 156 insertions(+), 3 deletions(-)

diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S
index 1cbd128..927476c 100644
--- a/arch/arm/cpu/armv7/start.S
+++ b/arch/arm/cpu/armv7/start.S
@@ -64,6 +64,7 @@ _pad:			.word 0x12345678 /* now 16*4=64 */
 
 .global _end_vect
 _end_vect:
+/* This label should be at the same location for SPL and U-Boot */
 .global	_u_boot_size
 _u_boot_size:
 	.word	0xDEADBEEF
diff --git a/arch/arm/include/asm/omap_common.h b/arch/arm/include/asm/omap_common.h
index 9f2616c..c2efa7c 100644
--- a/arch/arm/include/asm/omap_common.h
+++ b/arch/arm/include/asm/omap_common.h
@@ -99,4 +99,8 @@ u32 omap_boot_device(void);
 u32 omap_boot_mode(void);
 void preloader_console_init(void);
 
+/* symbols from start.S */
+extern u32 _u_boot_size;
+extern u32 _start;
+
 #endif /* _OMAP_COMMON_H_ */
diff --git a/include/configs/omap4_sdp4430.h b/include/configs/omap4_sdp4430.h
index a4332b7..0ed474d 100644
--- a/include/configs/omap4_sdp4430.h
+++ b/include/configs/omap4_sdp4430.h
@@ -257,7 +257,10 @@
 #define CONFIG_SYS_SPL_MAX_SIZE		0x7800	/* 30 K */
 #define CONFIG_SYS_SPL_STACK		LOW_LEVEL_SRAM_STACK
 
-#define CONFIG_SYS_SPL_BSS_START_ADDR	0x80000000
-#define CONFIG_SYS_SPL_BSS_MAX_SIZE	0x80000		/* 512 KB */
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR	0x300 /* address 0x60000 */
+#define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS	0x200 /* 256 KB */
+
+#define CONFIG_SYS_SPL_BSS_START_ADDR		0x80000000
+#define CONFIG_SYS_SPL_BSS_MAX_SIZE		0x80000		/* 512 KB */
 
 #endif /* __CONFIG_H */
diff --git a/spl/board/ti/sdp4430/Makefile b/spl/board/ti/sdp4430/Makefile
index d89dea0..18c5b8e 100644
--- a/spl/board/ti/sdp4430/Makefile
+++ b/spl/board/ti/sdp4430/Makefile
@@ -68,6 +68,41 @@ $(obj)ctype.c:
 COBJS	+= serial.o ns16550.o string.o vsprintf.o console.o stdio.o
 COBJS	+= ctype.o eabi_compat.o div64.o
 
+
+# mmc
+$(obj)mmc.c:
+	@rm -f $@
+	@ln -s $(TOPDIR)/drivers/mmc/mmc.c $@
+
+$(obj)omap_hsmmc.c:
+	@rm -f $@
+	@ln -s $(TOPDIR)/drivers/mmc/omap_hsmmc.c $@
+
+$(obj)omap24xx_i2c.c: $(obj)omap24xx_i2c.h
+	@rm -f $@
+	@ln -s $(TOPDIR)/drivers/i2c/omap24xx_i2c.c $@
+
+$(obj)omap24xx_i2c.h:
+	@rm -f $@
+	@ln -s $(TOPDIR)/drivers/i2c/omap24xx_i2c.h $@
+
+$(obj)time.c:
+	@rm -f $@
+	@ln -s $(TOPDIR)/lib/time.c $@
+
+$(obj)part.c:
+	@rm -f $@
+	@ln -s $(TOPDIR)/disk/part.c $@
+
+$(obj)part_dos.c: $(obj)part_dos.h
+	@rm -f $@
+	@ln -s $(TOPDIR)/disk/part_dos.c $@
+
+$(obj)part_dos.h:
+	@rm -f $@
+	@ln -s $(TOPDIR)/disk/part_dos.h $@
+
+COBJS	+= omap_hsmmc.o omap24xx_i2c.o mmc.o time.o part.o part_dos.o
 # armv7
 $(obj)start.S:
 	@rm -f $@
diff --git a/spl/board/ti/spl-omap.c b/spl/board/ti/spl-omap.c
index 57ddb7d..b64eac9 100644
--- a/spl/board/ti/spl-omap.c
+++ b/spl/board/ti/spl-omap.c
@@ -28,24 +28,134 @@
 #include <common.h>
 #include <asm/u-boot.h>
 #include <asm/arch/sys_proto.h>
+#include <mmc.h>
 #include <timestamp_autogenerated.h>
+#include <asm/omap_common.h>
+#include <asm/arch/mmc_host_def.h>
+#include <i2c.h>
 
 /* Define global data structure pointer to it*/
 gd_t gdata __attribute__ ((section(".data")));
 bd_t bdata __attribute__ ((section(".data")));
 gd_t *gd = &gdata;
 
+typedef void (*u_boot_entry_t)(void)__attribute__ ((noreturn));
+
 void board_init_f(ulong dummy)
 {
 	relocate_code(CONFIG_SYS_SPL_STACK, &gdata, CONFIG_SYS_SPL_TEXT_BASE);
 }
 
-void board_init_r(gd_t *id, ulong dummy)
+inline void hang(void)
 {
+	puts("### ERROR ### Please RESET the board ###\n");
 	for (;;)
 		;
 }
 
+#ifdef CONFIG_GENERIC_MMC
+int board_mmc_init(bd_t *bis)
+{
+	omap_mmc_init(0);
+	omap_mmc_init(1);
+	return 0;
+}
+#endif
+
+static void mmc_load_uboot_raw(struct mmc *mmc, u32 mmc_dev)
+{
+	u32 u_boot_size_sectors, err;
+	u32 *u_boot_size = (u32 *)(CONFIG_SYS_TEXT_BASE +
+				(u32) &_u_boot_size - (u32) &_start);
+
+	/* read one sector first to find u-boot size */
+	err = mmc->block_dev.block_read(mmc_dev,
+			CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR, 1,
+			(void *)CONFIG_SYS_TEXT_BASE);
+	if (err <= 0)
+		goto end;
+
+	if (*u_boot_size != 0xDEADBEEF) {
+		err = 0xDEADBEEF;
+		goto end;
+	}
+
+	/* move to the next word that has size */
+	u_boot_size++;
+
+	/*
+	 * convert size to sectors - round down is fine because we have
+	 * already read 1 sector
+	 */
+	u_boot_size_sectors = *u_boot_size/MMCSD_SECTOR_SIZE;
+	debug("spl: u-boot raw sectors - %d\n", u_boot_size_sectors + 1);
+	/* read one sector first to find u-boot size */
+	err = mmc->block_dev.block_read(mmc_dev,
+			CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR + 1,
+			u_boot_size_sectors,
+			(void *)(CONFIG_SYS_TEXT_BASE + MMCSD_SECTOR_SIZE));
+end:
+	if (err <= 0) {
+		printf("spl: mmc blk read err - %d\n", err);
+		hang();
+	}
+}
+
+static void mmc_load_uboot(u32 mmc_dev)
+{
+	struct mmc *mmc;
+	int err;
+	u32 boot_mode;
+
+	mmc_initialize(gd->bd);
+	mmc = find_mmc_device(mmc_dev);
+	if (!mmc) {
+		puts("spl: mmc device not found!!\n");
+		hang();
+	}
+
+	err = mmc_init(mmc);
+	if (err) {
+		printf("spl: mmc init failed: mmc_dev - %d err - %d\n",
+			mmc_dev, err);
+		hang();
+	}
+
+	boot_mode = omap_boot_mode();
+	if (boot_mode == MMCSD_MODE_RAW)
+		mmc_load_uboot_raw(mmc, mmc_dev);
+	else {
+		puts("spl: wrong MMC boot mode\n");
+		hang();
+	}
+}
+
+void board_init_r(gd_t *id, ulong dummy)
+{
+	u32 boot_device;
+	u_boot_entry_t u_boot_entry = (u_boot_entry_t) CONFIG_SYS_TEXT_BASE;
+
+	timer_init();
+	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+	boot_device = omap_boot_device();
+	switch (boot_device) {
+	case BOOT_DEVICE_MMC1:
+	case BOOT_DEVICE_MMC2:
+		mmc_load_uboot(boot_device - BOOT_DEVICE_MMC1);
+		break;
+	default:
+		printf("SPL: Un-supported Boot Device - %d!!!\n", boot_device);
+		hang();
+		break;
+	}
+
+	/*
+	 * Jump to u-boot with magic number as input to indicate that it
+	 * was loaded by SPL
+	 */
+	u_boot_entry();
+}
+
 void preloader_console_init(void)
 {
 	gd->bd = &bdata;
-- 
1.7.2.3

