[U-Boot] [SPEAr Enhancement PATCH 7/9] spear6xx/spear3xx: Add support to boot via NAND device
Vipin Kumar
vipin.kumar at st.com
Fri Nov 2 18:39:45 CET 2012
Add support for nand boot to SPL meant for spear3xx/spear6xx based boards
Signed-off-by: Vipin Kumar <vipin.kumar at st.com>
---
arch/arm/cpu/arm926ejs/spear/Makefile | 2 +-
arch/arm/cpu/arm926ejs/spear/spl_boot.c | 44 +++++-
arch/arm/cpu/arm926ejs/spear/spl_nand.c | 121 ++++++++++++++++
arch/arm/include/asm/arch-spear/bootrom_table.h | 54 +++++++
arch/arm/include/asm/arch-spear/spl_nand.h | 181 ++++++++++++++++++++++++
include/configs/spear600-evb.h | 1 +
6 files changed, 400 insertions(+), 3 deletions(-)
create mode 100644 arch/arm/cpu/arm926ejs/spear/spl_nand.c
create mode 100644 arch/arm/include/asm/arch-spear/bootrom_table.h
create mode 100644 arch/arm/include/asm/arch-spear/spl_nand.h
diff --git a/arch/arm/cpu/arm926ejs/spear/Makefile b/arch/arm/cpu/arm926ejs/spear/Makefile
index 2e026ee..5ebdf65 100644
--- a/arch/arm/cpu/arm926ejs/spear/Makefile
+++ b/arch/arm/cpu/arm926ejs/spear/Makefile
@@ -38,7 +38,7 @@ COBJS-$(CONFIG_SOC_SPEAR320) += spear320.o
COBJS-$(CONFIG_ARCH_SPEAR6XX) += spear6xx.o
ifdef CONFIG_SPL_BUILD
-COBJS-y += spl.o spl_boot.o
+COBJS-y += spl.o spl_boot.o spl_nand.o
COBJS-$(CONFIG_SOC_SPEAR600) += spl-spear600.o
endif
diff --git a/arch/arm/cpu/arm926ejs/spear/spl_boot.c b/arch/arm/cpu/arm926ejs/spear/spl_boot.c
index 9742135..497aefc 100644
--- a/arch/arm/cpu/arm926ejs/spear/spl_boot.c
+++ b/arch/arm/cpu/arm926ejs/spear/spl_boot.c
@@ -30,6 +30,7 @@
#include <asm/io.h>
#include <asm/arch/hardware.h>
#include <asm/arch/generic.h>
+#include <asm/arch/spl_nand.h>
uint32_t crc32(uint32_t, const unsigned char *, uint);
@@ -72,6 +73,35 @@ static int snor_image_load(u8 *load_addr, void (**image_p)(void))
return 0;
}
+static int nand_image_load(u32 blkstart, void (**image_p)(void))
+{
+ image_header_t header;
+ int ret = 0, blknum = blkstart;
+ size_t size;
+ ulong load_address;
+
+ do {
+ size = sizeof(image_header_t);
+ ret = nand_read_skip_bad(blknum, 0, &size, (u_char *)&header);
+
+ if ((ret >= 0) && image_check_header(&header)) {
+ size = image_get_data_size(&header);
+ load_address = image_get_load(&header);
+
+ ret = nand_read_skip_bad(blknum,
+ sizeof(image_header_t),
+ &size, (void *)load_address);
+ if (image_check_data(&header)) {
+ /* Jump to boot image */
+ *image_p = (void (*)(void))image_get_load(&header);
+ return 1;
+ }
+ }
+ } while (++blknum < blkstart + 4);
+
+ return 0;
+}
+
static void boot_image(void (*image)(void))
{
void (*funcp)(void) __noreturn = (void *)image;
@@ -124,8 +154,18 @@ u32 spl_boot(void)
if (NAND_BOOT_SUPPORTED && nand_boot_selected()) {
/* NAND booting */
- /* Not ported from XLoader to SPL yet */
- return 0;
+ /* NAND-FSMC initialization */
+ spl_nand_init();
+
+ /* NAND booting */
+ if (nand_image_load(CONFIG_SYS_NAND_BOOT_BLK, &image)) {
+ /* Platform related late initialasations */
+ board_lowlevel_late_init();
+
+ /* Jump to boot image */
+ boot_image(image);
+ return 1;
+ }
}
if (PNOR_BOOT_SUPPORTED && pnor_boot_selected()) {
diff --git a/arch/arm/cpu/arm926ejs/spear/spl_nand.c b/arch/arm/cpu/arm926ejs/spear/spl_nand.c
new file mode 100644
index 0000000..e5d5288
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/spear/spl_nand.c
@@ -0,0 +1,121 @@
+/*
+ * (C) Copyright 2012
+ * Vipin Kumar, ST Microelectronics, vipin.kumar at st.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 <errno.h>
+#include <asm/io.h>
+#include <asm/arch/bootrom_table.h>
+#include <asm/arch/generic.h>
+#include <asm/arch/spl_nand.h>
+
+static struct flashtype flashtype;
+static boot_flashdetectandinit_ptr_type boot_flashdetectandinit;
+static boot_flashread_ptr_type boot_flashread;
+static boot_nandsanitycheck_ptr_type boot_nandsanitycheck;
+static struct boot_nand_page *tmp_page_p;
+
+void spl_nand_init(void)
+{
+ struct bootrom_table *romtb_p =
+ (struct bootrom_table *)BOOTROM_TABLE_ADDRESS;
+
+ /* Global function pointers */
+ switch (get_socrev()) {
+ case SOC_SPEAR300:
+ boot_flashdetectandinit =
+ (boot_flashdetectandinit_ptr_type)0xffff1774;
+ boot_flashread = (boot_flashread_ptr_type)0xffff1050;
+ boot_nandsanitycheck =
+ (boot_nandsanitycheck_ptr_type)0xffff193C;
+ tmp_page_p = (struct boot_nand_page *)0x50030CCC;
+ break;
+ case SOC_SPEAR600_BA:
+ case SOC_SPEAR600_BB:
+ /* NAND Boot does not work for Revisions SPEAr600 BA and BB */
+ case SOC_SPEAR600_BC:
+ boot_flashdetectandinit =
+ (boot_flashdetectandinit_ptr_type)0xffff14ec;
+ boot_flashread = (boot_flashread_ptr_type)0xffff0dc4;
+ boot_nandsanitycheck =
+ (boot_nandsanitycheck_ptr_type)0xffff1628;
+ tmp_page_p = (struct boot_nand_page *)0xd2800844;
+ break;
+ case SOC_SPEAR310:
+ case SOC_SPEAR320:
+ case SOC_SPEAR600_BD:
+ boot_flashdetectandinit =
+ (romtb_p->table.table_1_0.boot_flashdetectandinit_ptr);
+ boot_flashread = (romtb_p->table.table_1_0.boot_flashread_ptr);
+ boot_nandsanitycheck =
+ (romtb_p->table.table_1_0.boot_nandsanitycheck_ptr);
+ tmp_page_p = (struct boot_nand_page *)0xd280084C;
+ break;
+ default:
+ break;
+ }
+
+ if (boot_flashdetectandinit)
+ (*boot_flashdetectandinit) (&flashtype, 1, BOTH_8_16,
+ tmp_page_p);
+}
+
+/**
+ * nand_read_skip_bad: Read image from NAND flash. Blocks that are marked bad
+ * are skipped and the next block is read instead as long as the image is short
+ * enough to fit even after skipping the bad blocks.
+ *
+ * @block: block number to start the read
+ * @offset: offset in the block number
+ * @length: buffer length, on return holds remaining bytes to read
+ * @buffer: buffer to write to
+ * @return 0 in case of success
+ */
+int nand_read_skip_bad(u32 block, size_t offset, size_t *length,
+ u_char *buffer)
+{
+ struct command_set *command = &(flashtype.comm_set);
+ u32 chip_off, readlen;
+
+ if (!boot_nandsanitycheck || !boot_flashread)
+ return -EINVAL;
+
+ while (*length) {
+ if (BOOT_OK == (*boot_nandsanitycheck) (&flashtype, block)) {
+ /* Block is OK */
+ chip_off = command->block_size * block + offset;
+ readlen = min(command->block_size - offset, *length);
+
+ if (BOOT_OK == (*boot_flashread) (&flashtype, chip_off,
+ buffer, readlen, tmp_page_p)) {
+ offset = 0;
+ *length -= readlen;
+ buffer += readlen;
+ } else
+ return -EINVAL;
+ }
+ /* Block is bad */
+ block++;
+ }
+
+ return 0;
+}
diff --git a/arch/arm/include/asm/arch-spear/bootrom_table.h b/arch/arm/include/asm/arch-spear/bootrom_table.h
new file mode 100644
index 0000000..65bb369
--- /dev/null
+++ b/arch/arm/include/asm/arch-spear/bootrom_table.h
@@ -0,0 +1,54 @@
+/*
+ * (C) Copyright 2012
+ * Vipin Kumar, ST Microelectronics, vipin.kumar at st.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
+ */
+
+#ifndef ASM_ARCH_BOOTROM_TABLE_H
+#define ASM_ARCH_BOOTROM_TABLE_H
+
+/*
+ * BootROM Table Structures
+ */
+#define BOOTROM_TABLE_ADDRESS 0xFFFF7F00
+
+#define BOOTROM_TABLE_VERSION_1_0 1
+
+struct bootrom_table_1_0 {
+ const void *boot_flashdetectandinit_ptr;
+ const void *boot_flashread_ptr;
+ const void *boot_nandsanitycheck_ptr;
+ const void *boot_nandreadpage_ptr;
+};
+
+/*
+ * Generic bootrom table structure's union. Contains the table structure for
+ * all versions
+ */
+union bootrom_ver_table {
+ struct bootrom_table_1_0 table_1_0;
+};
+
+struct bootrom_table {
+ const unsigned int table_version;
+ union bootrom_ver_table table;
+};
+
+#endif
diff --git a/arch/arm/include/asm/arch-spear/spl_nand.h b/arch/arm/include/asm/arch-spear/spl_nand.h
new file mode 100644
index 0000000..2773ea8
--- /dev/null
+++ b/arch/arm/include/asm/arch-spear/spl_nand.h
@@ -0,0 +1,181 @@
+/*
+ * (C) Copyright 2012
+ * Vipin Kumar, ST Micoelectronics, vipin.kumar at st.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
+ */
+
+#ifndef ASM_ARCH_SPEAR_SPL_NAND_H
+#define ASM_ARCH_SPEAR_SPL_NAND_H
+
+extern void spl_nand_init(void);
+extern int nand_read_skip_bad(u32 blk, size_t off, size_t *len, u_char *buff);
+
+/*
+ * The following definitions come from BootROM library.
+ * Please do not change the routine names as the refrences are picked from
+ * BootROM library all the versions of which are also committed along with
+ * SPL sources
+ */
+
+#define BOOT_OK 0
+
+enum {
+ BOTH_8_16 = 0,
+ EIGHT_BITS_ONLY = 1,
+ SIXTEEN_BITS_ONLY = 2
+};
+
+typedef enum {
+ NAND = 0,
+ NOR = 1,
+ ONE_NAND = 2
+} t_flash_device;
+
+typedef enum {
+ /* SMALL PAGES */
+ /* 64M */
+ NAND_64MS_1V_8 = 0x39,
+ /* 128M */
+ NAND_128MS_1V_8 = 0x33,
+ NAND_128MS_1V_16 = 0x43,
+ NAND_128MS_3V_8 = 0x73,
+ NAND_128MS_3V_16 = 0x53,
+ /* 256M */
+ NAND_256MS_1V_8 = 0x35,
+ NAND_256MS_1V_16 = 0x45,
+ NAND_256MS_3V_8 = 0x75,
+ NAND_256MS_3V_16 = 0x55,
+ /* 512M */
+ NAND_512MS_1V_8 = 0x36,
+ NAND_512MS_1V_16 = 0x46,
+ NAND_512MS_3V_8 = 0x76,
+ NAND_512MS_3V_16 = 0x56,
+ /* 1G */
+ NAND_1GS_1V_8 = 0x40,
+ NAND_1GS_1V_16 = 0x49,
+ NAND_1GS_3V_8 = 0x79,
+ NAND_1GS_3V_16 = 0x59,
+ NAND_1GS_3V_DDP_16 = 0x74,
+ NAND_1GS_1V_DDP_8 = 0x78,
+ NAND_1GS_1V_DDP_16 = 0x72,
+
+ /* LARGE PAGES */
+ /* 512M */
+ NAND_512ML_1V_8 = 0xA2,
+ NAND_512ML_1V_16 = 0xB2,
+ NAND_512ML_3V_8 = 0xF2,
+ NAND_512ML_3V_16 = 0xC2,
+ /* 1G */
+ NAND_1GL_1V_8 = 0xA1,
+ NAND_1GL_1V_16 = 0xB1,
+ NAND_1GL_3V_8 = 0xF1,
+ NAND_1GL_3V_16 = 0xC1,
+ /* 2G */
+ NAND_2GL_1V_8 = 0xAA,
+ NAND_2GL_3V_8 = 0xDA,
+ NAND_2GL_1V_16 = 0xBA,
+ NAND_2GL_3V_16 = 0xCA,
+ /* 4G */
+ NAND_4GL_1V_8 = 0xAC,
+ NAND_4GL_3V_8 = 0xDC,
+ NAND_4GL_1V_16 = 0xBC,
+ NAND_4GL_3V_16 = 0xCC,
+ /* 8G */
+ NAND_8GL_1V_8 = 0xA3,
+ NAND_8GL_3V_8 = 0xD3,
+ NAND_8GL_1V_16 = 0xB3,
+ NAND_8GL_3V_16 = 0xC3,
+ /* 8G */
+ NAND_16GL_1V_8 = 0xA5,
+ NAND_16GL_3V_8 = 0xD5,
+ NAND_16GL_1V_16 = 0xB5,
+ NAND_16GL_3V_16 = 0xC5,
+ /* NOR */
+ NOR_8 = -1,
+ NOR_16 = -2,
+ /* NAND */
+ ONE_NAND_16 = -4,
+ NO_VALID_ID = 0,
+ UNKNOWN_ID = -3
+} t_flash_command_id;
+
+typedef enum {
+ NOR_BANK_0 = 0,
+ NAND_BANK_0 = 1,
+ NAND_BANK_1 = 2,
+ NAND_BANK_2 = 3,
+ LAST_BANK
+} t_flash_FSMC_bank;
+
+struct command_set {
+ u32 pagexblock;
+ u32 page_size;
+ u32 block_size;
+ u32 spare_size;
+ u32 memory_size;
+ u32 ecc_size;
+ u32 data_width;
+ u32 pmem_command;
+ u32 pmem_address[2];
+ u32 patt_command;
+ u32 pmem_read;
+ u32 mem_command;
+ u32 att_command;
+ u32 mem_command_write;
+ u32 att_command_write;
+ u32 spare_command;
+ u8 /* t_flash_FSMC_bank */ memory_bank;
+ u8 padding[3];
+};
+
+/*
+ * There is a hack while defining this structure. The bootROM interface uses the
+ * enum types for a few elements of the structure which it optimizes using the
+ * compiler flag '-fshort-enums'. Since the bootrom is fixed it can be hacked
+ * here and not let the flag apply to all other parts of code */
+struct flashtype {
+ u8 /* t_flash_device */ device;
+ u8 padding;
+ s16 /* t_flash_command_id */ read_id;
+ struct command_set comm_set;
+};
+
+typedef enum {
+ PAGE_OK,
+ PAGE_KO
+} t_valid_flag;
+
+struct boot_nand_page {
+ u32 page_start_address;
+ u8 page[512];
+ t_valid_flag page_valid;
+ u8 padding[3];
+};
+
+typedef u32 (*boot_flashdetectandinit_ptr_type) (struct flashtype *,
+ u32, u32, struct boot_nand_page *);
+typedef u32 (*boot_flashread_ptr_type) (struct flashtype *, u32,
+ u8 *, u32, struct boot_nand_page *);
+typedef u32 (*boot_nandsanitycheck_ptr_type) (struct flashtype *,
+ u32);
+typedef u32 (*boot_nandreadpage_ptr_type) (u32, struct flashtype *,
+ struct boot_nand_page *);
+
+#endif
diff --git a/include/configs/spear600-evb.h b/include/configs/spear600-evb.h
index e7c5ee3..35761eb 100644
--- a/include/configs/spear600-evb.h
+++ b/include/configs/spear600-evb.h
@@ -85,6 +85,7 @@
#define CONFIG_DDR_MT47H32M16
#define CONFIG_SPL_TEXT_BASE 0xD2800B00
#define CONFIG_SYS_SNOR_BOOT_BASE 0xF8010000
+#define CONFIG_SYS_NAND_BOOT_BLK 4
#if defined(CONFIG_ENV_IS_IN_FLASH)
/* Environment is in serial NOR flash */
--
1.7.11.4
More information about the U-Boot
mailing list