From 4c1c0ce776a5748bc5c832f7f5d99b27f75fbb96 Mon Sep 17 00:00:00 2001
From: Ma Haijun <mahaijuns@gmail.com>
Date: Fri, 11 Oct 2013 13:13:14 +0800
Subject: [PATCH] OXNAS: add fat support to SPL

---
 board/ox820/ox820.c        |  12 +++
 board/ox820/u-boot-spl.lds |  11 ++
 boards.cfg                 |   1 +
 common/spl/Makefile        |   2 +-
 common/spl/spl_block.c     | 202 +++++++++++++++++++++++++++++++++++++
 common/spl/spl_ide.c       |  99 ------------------
 include/configs/ox820.h    |  26 +++++
 7 files changed, 253 insertions(+), 100 deletions(-)
 create mode 100644 common/spl/spl_block.c
 delete mode 100644 common/spl/spl_ide.c

diff --git a/board/ox820/ox820.c b/board/ox820/ox820.c
index 19b66ff043..e0cc6ff387 100644
--- a/board/ox820/ox820.c
+++ b/board/ox820/ox820.c
@@ -91,6 +91,11 @@ void board_inithw(void)
 		puts("memory test done\n");
 	}
 #endif /* DEBUG */
+#ifdef CONFIG_SPL_BSS_DRAM_START
+	extern char __bss_dram_start;
+	extern char __bss_dram_end;
+	memset(&__bss_dram_start, 0, &__bss_dram_end - &__bss_dram_start);
+#endif
 }
 
 void board_init_f(ulong dummy)
@@ -114,6 +119,13 @@ u32 spl_boot_device(void)
 	return CONFIG_SPL_BOOT_DEVICE;
 }
 
+#ifdef CONFIG_SPL_BLOCK_SUPPORT
+void spl_block_device_init(void)
+{
+	ide_init();
+}
+#endif
+
 void spl_display_print(void)
 {
 	/* print a hint, so that we will not use the wrong SPL by mistake */
diff --git a/board/ox820/u-boot-spl.lds b/board/ox820/u-boot-spl.lds
index c38557c80c..e04ac18352 100644
--- a/board/ox820/u-boot-spl.lds
+++ b/board/ox820/u-boot-spl.lds
@@ -70,6 +70,17 @@ SECTIONS
 
 	_end = .;
 
+#ifdef CONFIG_SPL_BSS_DRAM_START
+	. = CONFIG_SPL_BSS_DRAM_START;
+	.bss.dram : {
+		__bss_dram_start = .;
+#ifdef CONFIG_SPL_FAT_SUPPORT
+		fs/fat/libfat.o(.bss*)
+#endif /* CONFIG_SPL_FAT_SUPPORT */
+		__bss_dram_end = .;
+	}
+#endif /* CONFIG_SPL_BSS_DRAM_START */
+
 	.bss __rel_dyn_start (OVERLAY) : {
 		__bss_start = .;
 		*(.bss*)
diff --git a/boards.cfg b/boards.cfg
index 2206c7618d..5f0bfd4327 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -54,6 +54,7 @@ woodburn                     arm         arm1136     -                   -
 woodburn_sd                  arm         arm1136     woodburn            -              mx35        woodburn_sd:IMX_CONFIG=board/woodburn/imximage.cfg
 ox820                        arm         arm1136     ox820               -              nas782x     ox820
 ox820_sata                   arm         arm1136     ox820               -              nas782x     ox820:BOOT_FROM_SATA
+ox820_fat                    arm         arm1136     ox820               -              nas782x     ox820:BOOT_FROM_SATA,BOOT_FROM_FAT
 ox820_nand                   arm         arm1136     ox820               -              nas782x     ox820:BOOT_FROM_NAND
 tnetv107x_evm                arm         arm1176     tnetv107xevm        ti             tnetv107x
 rpi_b                        arm         arm1176     rpi_b               raspberrypi    bcm2835
diff --git a/common/spl/Makefile b/common/spl/Makefile
index 43acc12266..b320fd2b63 100644
--- a/common/spl/Makefile
+++ b/common/spl/Makefile
@@ -21,7 +21,7 @@ COBJS-$(CONFIG_SPL_NAND_SUPPORT) += spl_nand.o
 COBJS-$(CONFIG_SPL_ONENAND_SUPPORT) += spl_onenand.o
 COBJS-$(CONFIG_SPL_NET_SUPPORT) += spl_net.o
 COBJS-$(CONFIG_SPL_MMC_SUPPORT) += spl_mmc.o
-COBJS-$(CONFIG_SPL_BLOCK_SUPPORT) += spl_ide.o
+COBJS-$(CONFIG_SPL_BLOCK_SUPPORT) += spl_block.o
 endif
 
 COBJS	:= $(sort $(COBJS-y))
diff --git a/common/spl/spl_block.c b/common/spl/spl_block.c
new file mode 100644
index 0000000000..85a94b23ae
--- /dev/null
+++ b/common/spl/spl_block.c
@@ -0,0 +1,202 @@
+/*
+ * (C) Copyright 2013
+ *
+ * Ma Haijun <mahaijuns@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <common.h>
+#include <spl.h>
+#include <asm/u-boot.h>
+#include <asm/utils.h>
+#include <version.h>
+#include <part.h>
+#include <fat.h>
+
+/* should be implemented by board */
+extern void spl_block_device_init(void);
+
+block_dev_desc_t * spl_get_block_device(void)
+{
+	block_dev_desc_t * device;
+
+	spl_block_device_init();
+
+	device = get_dev(CONFIG_SPL_BLOCKDEV_INTERFACE, CONFIG_SPL_BLOCKDEV_ID);
+	if (!device) {
+		printf("blk device %s%d not exists\n",
+			CONFIG_SPL_BLOCKDEV_INTERFACE,
+			CONFIG_SPL_BLOCKDEV_ID);
+		hang();
+	}
+
+	return device;
+}
+
+#ifdef CONFIG_SPL_FAT_SUPPORT
+static int block_load_image_fat(const char *filename)
+{
+	int err;
+	struct image_header *header;
+
+	header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
+						sizeof(struct image_header));
+
+	err = file_fat_read(filename, header, sizeof(struct image_header));
+	if (err <= 0)
+		goto end;
+
+	spl_parse_image_header(header);
+
+	err = file_fat_read(filename, (u8 *)spl_image.load_addr, 0);
+
+end:
+	if (err <= 0)
+		printf("spl: error reading image %s, err - %d\n",
+		       filename, err);
+
+	return (err <= 0);
+}
+
+#ifdef CONFIG_SPL_OS_BOOT
+static int block_load_image_fat_os()
+{
+	int err;
+
+	err = file_fat_read(CONFIG_SPL_FAT_LOAD_ARGS_NAME,
+			    (void *)CONFIG_SYS_SPL_ARGS_ADDR, 0);
+	if (err <= 0) {
+		printf("spl: error reading image %s, err - %d\n",
+		       CONFIG_SPL_FAT_LOAD_ARGS_NAME, err);
+		return -1;
+	}
+
+	return block_load_image_fat(CONFIG_SPL_FAT_LOAD_KERNEL_NAME);
+}
+#endif
+
+void spl_block_load_image(void)
+{
+	int err;
+	block_dev_desc_t * device;
+
+	device = spl_get_block_device();
+	err = fat_register_device(device, CONFIG_BLOCKDEV_FAT_BOOT_PARTITION);
+	if (err) {
+		printf("spl: fat register err - %d\n", err);
+		hang();
+	}
+#ifdef CONFIG_SPL_OS_BOOT
+	if (spl_start_uboot() || block_load_image_fat_os())
+#endif
+	err = block_load_image_fat(CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME);
+	if (err)
+		hang();
+}
+
+/* quick and dirty memory allocation */
+static ulong next_mem = CONFIG_SPL_MALLOC_START;
+
+void *memalign(size_t alignment, size_t bytes)
+{
+	ulong mem = next_mem;
+
+	mem += alignment;
+	mem &= ~alignment;
+	next_mem = mem + bytes;
+
+	if (next_mem > CONFIG_SYS_SDRAM_BASE + SDRAM_SIZE) {
+		printf("spl: out of memory\n");
+		hang();
+	}
+
+	return (void *)mem;
+}
+
+void free(void* mem)
+{
+}
+
+#else /* CONFIG_SPL_FAT_SUPPORT */
+static int block_load_image_raw(block_dev_desc_t * device, unsigned long sector)
+{
+	int n;
+	u32 image_size_sectors;
+	struct image_header *header;
+
+	header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
+						sizeof(struct image_header));
+
+	/* read image header to find the image size & load address */
+	n = device->block_read(device->dev, sector, 1, header);
+
+	if (n != 1) {
+		printf("spl: blk read err\n");
+		return 1;
+	}
+
+	spl_parse_image_header(header);
+
+	/* convert size to sectors - round up */
+	image_size_sectors = (spl_image.size + 512 - 1) / 512;
+	n = device->block_read(device->dev, sector, image_size_sectors,
+					(void *)spl_image.load_addr);
+
+	if (n != image_size_sectors) {
+		printf("spl: blk read err\n");
+		return 1;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_SPL_OS_BOOT
+static int block_load_image_raw_os(block_dev_desc_t * device)
+{
+	int n;
+
+	n = device->block_read(device->dev, CONFIG_SYS_BLOCK_RAW_MODE_ARGS_SECTOR,
+					CONFIG_SYS_BLOCK_RAW_MODE_ARGS_SECTORS,
+					(u32 *)CONFIG_SYS_SPL_ARGS_ADDR);
+	/* flush cache after read */
+	flush_cache(addr, CONFIG_SYS_BLOCK_RAW_MODE_ARGS_SECTORS * 512);
+
+	if (n != CONFIG_SYS_BLOCK_RAW_MODE_ARGS_SECTORS) {
+		printf("args blk read error\n");
+		return -1;
+	}
+
+	return block_load_image_raw(device, CONFIG_SYS_BLOCK_RAW_MODE_KERNEL_SECTOR);
+}
+#endif
+
+void spl_block_load_image(void)
+{
+	int err;
+	block_dev_desc_t * device;
+
+	device = spl_get_block_device();
+#ifdef CONFIG_SPL_OS_BOOT
+	if (spl_start_uboot() || block_load_image_raw_os(device))
+#endif
+	err = block_load_image_raw(device,
+				 CONFIG_SYS_BLOCK_RAW_MODE_U_BOOT_SECTOR);
+	if (err)
+		hang();
+}
+#endif /* CONFIG_SPL_FAT_SUPPORT */
diff --git a/common/spl/spl_ide.c b/common/spl/spl_ide.c
deleted file mode 100644
index ed639efe55..0000000000
--- a/common/spl/spl_ide.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * (C) Copyright 2010
- * Texas Instruments, <www.ti.com>
- *
- * Aneesh V <aneesh@ti.com>
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-#include <common.h>
-#include <spl.h>
-#include <asm/u-boot.h>
-#include <asm/utils.h>
-#include <version.h>
-#include <ide.h>
-
-inline void  init_part (block_dev_desc_t *dev_desc) {}
-inline void dev_print(block_dev_desc_t *dev_desc) {}
-
-static int ide_load_image_raw(int device, unsigned long sector)
-{
-	int n;
-	u32 image_size_sectors;
-	struct image_header *header;
-
-	header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
-						sizeof(struct image_header));
-
-	/* read image header to find the image size & load address */
-	n = ide_read(device, sector, 1, header);
-	if (n != 1) {
-		printf("spl: ide blk read err\n");
-		return 1;
-	}
-
-	spl_parse_image_header(header);
-
-	/* convert size to sectors - round up */
-	image_size_sectors = (spl_image.size + 512 - 1) / 512;
-
-	n = ide_read(device, sector, image_size_sectors, (void *)spl_image.load_addr);
-	if (n != image_size_sectors) {
-		printf("spl: ide blk read err\n");
-		return 1;
-	}
-	return 0;
-}
-
-#ifdef CONFIG_SPL_OS_BOOT
-static int ide_load_image_raw_os(int device)
-{
-	int n;
-	n = ide_read(device, CONFIG_SYS_BLOCK_RAW_MODE_ARGS_SECTOR,
-		CONFIG_SYS_BLOCK_RAW_MODE_ARGS_SECTORS,
-		(u32 *)CONFIG_SYS_SPL_ARGS_ADDR);
-
-	/* flush cache after read */
-	flush_cache(addr, CONFIG_SYS_BLOCK_RAW_MODE_ARGS_SECTORS * 512);
-
-	if (n != CONFIG_SYS_BLOCK_RAW_MODE_ARGS_SECTORS) {
-		printf("ide args blk read error\n");
-		return -1;
-	}
-
-	return ide_load_image_raw(device, CONFIG_SYS_BLOCK_RAW_MODE_KERNEL_SECTOR);
-}
-#endif
-
-
-void spl_block_load_image(void)
-{
-	int err;
-
-	ide_init();
-
-#ifdef CONFIG_SPL_OS_BOOT
-	if (spl_start_uboot() || ide_load_image_raw_os(0))
-#endif
-	err = ide_load_image_raw(0,
-				 CONFIG_SYS_BLOCK_RAW_MODE_U_BOOT_SECTOR);
-
-	if (err)
-		hang();
-}
diff --git a/include/configs/ox820.h b/include/configs/ox820.h
index 88e4cb6c78..2a13e24e65 100644
--- a/include/configs/ox820.h
+++ b/include/configs/ox820.h
@@ -123,12 +123,36 @@
 #define BOOT_DEVICE_BLOCK				860202
 #define CONFIG_SPL_BOOT_DEVICE				BOOT_DEVICE_BLOCK
 #define CONFIG_SPL_MAX_SIZE				(32 * 1024)
+#define CONFIG_SPL_LIBDISK_SUPPORT
+#define CONFIG_SPL_BLOCKDEV_INTERFACE			"ide"
+#define CONFIG_SPL_BLOCKDEV_ID				0
+
+#ifdef CONFIG_BOOT_FROM_FAT /* u-boot in fat partition */
+
+#define CONFIG_SPL_FAT_SUPPORT
+#define CONFIG_SPL_BSS_DRAM_START			0x65000000
+#define CONFIG_SPL_MALLOC_START				0x66000000
+#ifdef CONFIG_SPL_BUILD
+#define USE_DL_PREFIX	/* rename malloc free etc, so we can override them */
+#endif
+
+#define CONFIG_BLOCKDEV_FAT_BOOT_PARTITION		1 /* first partition */
+#define CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME		"u-boot.img" /* u-boot file name */
+/* spl kernel load is not enabled */
+#define CONFIG_SPL_FAT_LOAD_ARGS_NAME			"bootargs.bin" /* boot parameters */
+#define CONFIG_SPL_FAT_LOAD_KERNEL_NAME			"uImage" /* kernel */
+#define CONFIG_SYS_SPL_ARGS_ADDR			(CONFIG_SYS_SDRAM_BASE + 0x100)
+
+#else /* u-boot in raw sectors */
+
 #define CONFIG_SYS_BLOCK_RAW_MODE_U_BOOT_SECTOR		1024
 /* spl kernel load is not enabled */
 #define CONFIG_SYS_BLOCK_RAW_MODE_KERNEL_SECTOR		4096
 #define CONFIG_SYS_BLOCK_RAW_MODE_ARGS_SECTOR		0
 #define CONFIG_SYS_BLOCK_RAW_MODE_ARGS_SECTORS		(1024 / 512)
 #define CONFIG_SYS_SPL_ARGS_ADDR			(CONFIG_SYS_SDRAM_BASE + 0x100)
+
+#endif /* CONFIG_BOOT_FROM_FAT */
 /* CONFIG_BOOT_FROM_SATA end */
 
 #else
@@ -241,7 +265,9 @@
 /* #define CONFIG_USB_EHCI_TXFIFO_THRESH	0x3F */
 #define CONFIG_USB_PLLB_CLK
 #define CONFIG_USB_EHCI_OXNAS
+#ifndef CONFIG_SPL_BUILD
 #define CONFIG_USB_STORAGE
+#endif
 #define CONFIG_CMD_USB
 
 /* cmds */